/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/tests/test__dirstate_helpers.py

  • Committer: Jelmer Vernooij
  • Date: 2018-05-06 11:48:54 UTC
  • mto: This revision was merged to the branch mainline in revision 6960.
  • Revision ID: jelmer@jelmer.uk-20180506114854-h4qd9ojaqy8wxjsd
Move .mailmap to root.

Show diffs side-by-side

added added

removed removed

Lines of Context:
51
51
# FIXME: we should also parametrize against SHA1Provider !
52
52
 
53
53
ue_scenarios = [('dirstate_Python',
54
 
                 {'update_entry': dirstate.py_update_entry})]
 
54
    {'update_entry': dirstate.py_update_entry})]
55
55
if compiled_dirstate_helpers_feature.available():
56
56
    update_entry = compiled_dirstate_helpers_feature.module.update_entry
57
57
    ue_scenarios.append(('dirstate_Pyrex', {'update_entry': update_entry}))
58
58
 
59
59
pe_scenarios = [('dirstate_Python',
60
 
                 {'_process_entry': dirstate.ProcessEntryPython})]
 
60
    {'_process_entry': dirstate.ProcessEntryPython})]
61
61
if compiled_dirstate_helpers_feature.available():
62
62
    process_entry = compiled_dirstate_helpers_feature.module.ProcessEntryC
63
63
    pe_scenarios.append(('dirstate_Pyrex', {'_process_entry': process_entry}))
65
65
helper_scenarios = [('dirstate_Python', {'helpers': _dirstate_helpers_py})]
66
66
if compiled_dirstate_helpers_feature.available():
67
67
    helper_scenarios.append(('dirstate_Pyrex',
68
 
                             {'helpers': compiled_dirstate_helpers_feature.module}))
 
68
        {'helpers': compiled_dirstate_helpers_feature.module}))
69
69
 
70
70
 
71
71
class TestBisectPathMixin(object):
120
120
                            bisect_split_idx, bisect_path_idx, path)
121
121
                         )
122
122
        if exists:
123
 
            self.assertEqual(path, paths[bisect_path_idx + offset])
 
123
            self.assertEqual(path, paths[bisect_path_idx+offset])
124
124
 
125
125
    def split_for_dirblocks(self, paths):
126
126
        dir_split_paths = []
127
127
        for path in paths:
128
128
            dirname, basename = os.path.split(path)
129
 
            dir_split_paths.append((dirname.split(b'/'), basename))
 
129
            dir_split_paths.append((dirname.split('/'), basename))
130
130
        dir_split_paths.sort()
131
131
        return dir_split_paths
132
132
 
133
133
    def test_simple(self):
134
134
        """In the simple case it works just like bisect_left"""
135
 
        paths = [b'', b'a', b'b', b'c', b'd']
 
135
        paths = ['', 'a', 'b', 'c', 'd']
136
136
        split_paths = self.split_for_dirblocks(paths)
137
137
        for path in paths:
138
138
            self.assertBisect(paths, split_paths, path, exists=True)
139
 
        self.assertBisect(paths, split_paths, b'_', exists=False)
140
 
        self.assertBisect(paths, split_paths, b'aa', exists=False)
141
 
        self.assertBisect(paths, split_paths, b'bb', exists=False)
142
 
        self.assertBisect(paths, split_paths, b'cc', exists=False)
143
 
        self.assertBisect(paths, split_paths, b'dd', exists=False)
144
 
        self.assertBisect(paths, split_paths, b'a/a', exists=False)
145
 
        self.assertBisect(paths, split_paths, b'b/b', exists=False)
146
 
        self.assertBisect(paths, split_paths, b'c/c', exists=False)
147
 
        self.assertBisect(paths, split_paths, b'd/d', exists=False)
 
139
        self.assertBisect(paths, split_paths, '_', exists=False)
 
140
        self.assertBisect(paths, split_paths, 'aa', exists=False)
 
141
        self.assertBisect(paths, split_paths, 'bb', exists=False)
 
142
        self.assertBisect(paths, split_paths, 'cc', exists=False)
 
143
        self.assertBisect(paths, split_paths, 'dd', exists=False)
 
144
        self.assertBisect(paths, split_paths, 'a/a', exists=False)
 
145
        self.assertBisect(paths, split_paths, 'b/b', exists=False)
 
146
        self.assertBisect(paths, split_paths, 'c/c', exists=False)
 
147
        self.assertBisect(paths, split_paths, 'd/d', exists=False)
148
148
 
149
149
    def test_involved(self):
150
150
        """This is where bisect_path_* diverges slightly."""
181
181
        # children are mentioned.
182
182
        # So all the root-directory paths, then all the
183
183
        # first sub directory, etc.
184
 
        paths = [  # content of '/'
185
 
            b'', b'a', b'a-a', b'a-z', b'a=a', b'a=z',
 
184
        paths = [# content of '/'
 
185
                 '', 'a', 'a-a', 'a-z', 'a=a', 'a=z',
186
186
                 # content of 'a/'
187
 
                 b'a/a', b'a/a-a', b'a/a-z',
188
 
                 b'a/a=a', b'a/a=z',
189
 
                 b'a/z', b'a/z-a', b'a/z-z',
190
 
                 b'a/z=a', b'a/z=z',
 
187
                 'a/a', 'a/a-a', 'a/a-z',
 
188
                 'a/a=a', 'a/a=z',
 
189
                 'a/z', 'a/z-a', 'a/z-z',
 
190
                 'a/z=a', 'a/z=z',
191
191
                 # content of 'a/a/'
192
 
                 b'a/a/a', b'a/a/z',
 
192
                 'a/a/a', 'a/a/z',
193
193
                 # content of 'a/a-a'
194
 
                 b'a/a-a/a',
 
194
                 'a/a-a/a',
195
195
                 # content of 'a/a-z'
196
 
                 b'a/a-z/z',
 
196
                 'a/a-z/z',
197
197
                 # content of 'a/a=a'
198
 
                 b'a/a=a/a',
 
198
                 'a/a=a/a',
199
199
                 # content of 'a/a=z'
200
 
                 b'a/a=z/z',
 
200
                 'a/a=z/z',
201
201
                 # content of 'a/z/'
202
 
                 b'a/z/a', b'a/z/z',
 
202
                 'a/z/a', 'a/z/z',
203
203
                 # content of 'a-a'
204
 
                 b'a-a/a',
 
204
                 'a-a/a',
205
205
                 # content of 'a-z'
206
 
                 b'a-z/z',
 
206
                 'a-z/z',
207
207
                 # content of 'a=a'
208
 
                 b'a=a/a',
 
208
                 'a=a/a',
209
209
                 # content of 'a=z'
210
 
                 b'a=z/z',
211
 
            ]
 
210
                 'a=z/z',
 
211
                ]
212
212
        split_paths = self.split_for_dirblocks(paths)
213
213
        sorted_paths = []
214
214
        for dir_parts, basename in split_paths:
215
 
            if dir_parts == [b'']:
 
215
            if dir_parts == ['']:
216
216
                sorted_paths.append(basename)
217
217
            else:
218
 
                sorted_paths.append(b'/'.join(dir_parts + [basename]))
 
218
                sorted_paths.append('/'.join(dir_parts + [basename]))
219
219
 
220
220
        self.assertEqual(sorted_paths, paths)
221
221
 
294
294
        bisect_dirblock = self.get_bisect_dirblock()
295
295
        self.assertIsInstance(dirblocks, list)
296
296
        bisect_split_idx = bisect_dirblock(dirblocks, path, *args, **kwargs)
297
 
        split_dirblock = (path.split(b'/'), [])
 
297
        split_dirblock = (path.split('/'), [])
298
298
        bisect_left_idx = bisect.bisect_left(split_dirblocks, split_dirblock,
299
299
                                             *args)
300
300
        self.assertEqual(bisect_left_idx, bisect_split_idx,
309
309
        Also, ensure that the paths are in proper sorted order.
310
310
        """
311
311
        dirblocks = [(path, []) for path in paths]
312
 
        split_dirblocks = [(path.split(b'/'), []) for path in paths]
 
312
        split_dirblocks = [(path.split('/'), []) for path in paths]
313
313
        self.assertEqual(sorted(split_dirblocks), split_dirblocks)
314
314
        return dirblocks, split_dirblocks
315
315
 
316
316
    def test_simple(self):
317
317
        """In the simple case it works just like bisect_left"""
318
 
        paths = [b'', b'a', b'b', b'c', b'd']
 
318
        paths = ['', 'a', 'b', 'c', 'd']
319
319
        dirblocks, split_dirblocks = self.paths_to_dirblocks(paths)
320
320
        for path in paths:
321
321
            self.assertBisect(dirblocks, split_dirblocks, path)
322
 
        self.assertBisect(dirblocks, split_dirblocks, b'_')
323
 
        self.assertBisect(dirblocks, split_dirblocks, b'aa')
324
 
        self.assertBisect(dirblocks, split_dirblocks, b'bb')
325
 
        self.assertBisect(dirblocks, split_dirblocks, b'cc')
326
 
        self.assertBisect(dirblocks, split_dirblocks, b'dd')
327
 
        self.assertBisect(dirblocks, split_dirblocks, b'a/a')
328
 
        self.assertBisect(dirblocks, split_dirblocks, b'b/b')
329
 
        self.assertBisect(dirblocks, split_dirblocks, b'c/c')
330
 
        self.assertBisect(dirblocks, split_dirblocks, b'd/d')
 
322
        self.assertBisect(dirblocks, split_dirblocks, '_')
 
323
        self.assertBisect(dirblocks, split_dirblocks, 'aa')
 
324
        self.assertBisect(dirblocks, split_dirblocks, 'bb')
 
325
        self.assertBisect(dirblocks, split_dirblocks, 'cc')
 
326
        self.assertBisect(dirblocks, split_dirblocks, 'dd')
 
327
        self.assertBisect(dirblocks, split_dirblocks, 'a/a')
 
328
        self.assertBisect(dirblocks, split_dirblocks, 'b/b')
 
329
        self.assertBisect(dirblocks, split_dirblocks, 'c/c')
 
330
        self.assertBisect(dirblocks, split_dirblocks, 'd/d')
331
331
 
332
332
    def test_involved(self):
333
333
        """This is where bisect_left diverges slightly."""
334
 
        paths = [b'', b'a',
335
 
                 b'a/a', b'a/a/a', b'a/a/z', b'a/a-a', b'a/a-z',
336
 
                 b'a/z', b'a/z/a', b'a/z/z', b'a/z-a', b'a/z-z',
337
 
                 b'a-a', b'a-z',
338
 
                 b'z', b'z/a/a', b'z/a/z', b'z/a-a', b'z/a-z',
339
 
                 b'z/z', b'z/z/a', b'z/z/z', b'z/z-a', b'z/z-z',
340
 
                 b'z-a', b'z-z',
341
 
                 ]
 
334
        paths = ['', 'a',
 
335
                 'a/a', 'a/a/a', 'a/a/z', 'a/a-a', 'a/a-z',
 
336
                 'a/z', 'a/z/a', 'a/z/z', 'a/z-a', 'a/z-z',
 
337
                 'a-a', 'a-z',
 
338
                 'z', 'z/a/a', 'z/a/z', 'z/a-a', 'z/a-z',
 
339
                 'z/z', 'z/z/a', 'z/z/z', 'z/z-a', 'z/z-z',
 
340
                 'z-a', 'z-z',
 
341
                ]
342
342
        dirblocks, split_dirblocks = self.paths_to_dirblocks(paths)
343
343
        for path in paths:
344
344
            self.assertBisect(dirblocks, split_dirblocks, path)
345
345
 
346
346
    def test_involved_cached(self):
347
347
        """This is where bisect_left diverges slightly."""
348
 
        paths = [b'', b'a',
349
 
                 b'a/a', b'a/a/a', b'a/a/z', b'a/a-a', b'a/a-z',
350
 
                 b'a/z', b'a/z/a', b'a/z/z', b'a/z-a', b'a/z-z',
351
 
                 b'a-a', b'a-z',
352
 
                 b'z', b'z/a/a', b'z/a/z', b'z/a-a', b'z/a-z',
353
 
                 b'z/z', b'z/z/a', b'z/z/z', b'z/z-a', b'z/z-z',
354
 
                 b'z-a', b'z-z',
355
 
                 ]
 
348
        paths = ['', 'a',
 
349
                 'a/a', 'a/a/a', 'a/a/z', 'a/a-a', 'a/a-z',
 
350
                 'a/z', 'a/z/a', 'a/z/z', 'a/z-a', 'a/z-z',
 
351
                 'a-a', 'a-z',
 
352
                 'z', 'z/a/a', 'z/a/z', 'z/a-a', 'z/a-z',
 
353
                 'z/z', 'z/z/a', 'z/z/z', 'z/z-a', 'z/z-z',
 
354
                 'z-a', 'z-z',
 
355
                ]
356
356
        cache = {}
357
357
        dirblocks, split_dirblocks = self.paths_to_dirblocks(paths)
358
358
        for path in paths:
414
414
 
415
415
    def test_cmp_empty(self):
416
416
        """Compare against the empty string."""
417
 
        self.assertCmpByDirs(0, b'', b'')
418
 
        self.assertCmpByDirs(1, b'a', b'')
419
 
        self.assertCmpByDirs(1, b'ab', b'')
420
 
        self.assertCmpByDirs(1, b'abc', b'')
421
 
        self.assertCmpByDirs(1, b'abcd', b'')
422
 
        self.assertCmpByDirs(1, b'abcde', b'')
423
 
        self.assertCmpByDirs(1, b'abcdef', b'')
424
 
        self.assertCmpByDirs(1, b'abcdefg', b'')
425
 
        self.assertCmpByDirs(1, b'abcdefgh', b'')
426
 
        self.assertCmpByDirs(1, b'abcdefghi', b'')
427
 
        self.assertCmpByDirs(1, b'test/ing/a/path/', b'')
 
417
        self.assertCmpByDirs(0, '', '')
 
418
        self.assertCmpByDirs(1, 'a', '')
 
419
        self.assertCmpByDirs(1, 'ab', '')
 
420
        self.assertCmpByDirs(1, 'abc', '')
 
421
        self.assertCmpByDirs(1, 'abcd', '')
 
422
        self.assertCmpByDirs(1, 'abcde', '')
 
423
        self.assertCmpByDirs(1, 'abcdef', '')
 
424
        self.assertCmpByDirs(1, 'abcdefg', '')
 
425
        self.assertCmpByDirs(1, 'abcdefgh', '')
 
426
        self.assertCmpByDirs(1, 'abcdefghi', '')
 
427
        self.assertCmpByDirs(1, 'test/ing/a/path/', '')
428
428
 
429
429
    def test_cmp_same_str(self):
430
430
        """Compare the same string"""
431
 
        self.assertCmpByDirs(0, b'a', b'a')
432
 
        self.assertCmpByDirs(0, b'ab', b'ab')
433
 
        self.assertCmpByDirs(0, b'abc', b'abc')
434
 
        self.assertCmpByDirs(0, b'abcd', b'abcd')
435
 
        self.assertCmpByDirs(0, b'abcde', b'abcde')
436
 
        self.assertCmpByDirs(0, b'abcdef', b'abcdef')
437
 
        self.assertCmpByDirs(0, b'abcdefg', b'abcdefg')
438
 
        self.assertCmpByDirs(0, b'abcdefgh', b'abcdefgh')
439
 
        self.assertCmpByDirs(0, b'abcdefghi', b'abcdefghi')
440
 
        self.assertCmpByDirs(0, b'testing a long string',
441
 
                             b'testing a long string')
442
 
        self.assertCmpByDirs(0, b'x' * 10000, b'x' * 10000)
443
 
        self.assertCmpByDirs(0, b'a/b', b'a/b')
444
 
        self.assertCmpByDirs(0, b'a/b/c', b'a/b/c')
445
 
        self.assertCmpByDirs(0, b'a/b/c/d', b'a/b/c/d')
446
 
        self.assertCmpByDirs(0, b'a/b/c/d/e', b'a/b/c/d/e')
 
431
        self.assertCmpByDirs(0, 'a', 'a')
 
432
        self.assertCmpByDirs(0, 'ab', 'ab')
 
433
        self.assertCmpByDirs(0, 'abc', 'abc')
 
434
        self.assertCmpByDirs(0, 'abcd', 'abcd')
 
435
        self.assertCmpByDirs(0, 'abcde', 'abcde')
 
436
        self.assertCmpByDirs(0, 'abcdef', 'abcdef')
 
437
        self.assertCmpByDirs(0, 'abcdefg', 'abcdefg')
 
438
        self.assertCmpByDirs(0, 'abcdefgh', 'abcdefgh')
 
439
        self.assertCmpByDirs(0, 'abcdefghi', 'abcdefghi')
 
440
        self.assertCmpByDirs(0, 'testing a long string', 'testing a long string')
 
441
        self.assertCmpByDirs(0, 'x'*10000, 'x'*10000)
 
442
        self.assertCmpByDirs(0, 'a/b', 'a/b')
 
443
        self.assertCmpByDirs(0, 'a/b/c', 'a/b/c')
 
444
        self.assertCmpByDirs(0, 'a/b/c/d', 'a/b/c/d')
 
445
        self.assertCmpByDirs(0, 'a/b/c/d/e', 'a/b/c/d/e')
447
446
 
448
447
    def test_simple_paths(self):
449
448
        """Compare strings that act like normal string comparison"""
450
 
        self.assertCmpByDirs(-1, b'a', b'b')
451
 
        self.assertCmpByDirs(-1, b'aa', b'ab')
452
 
        self.assertCmpByDirs(-1, b'ab', b'bb')
453
 
        self.assertCmpByDirs(-1, b'aaa', b'aab')
454
 
        self.assertCmpByDirs(-1, b'aab', b'abb')
455
 
        self.assertCmpByDirs(-1, b'abb', b'bbb')
456
 
        self.assertCmpByDirs(-1, b'aaaa', b'aaab')
457
 
        self.assertCmpByDirs(-1, b'aaab', b'aabb')
458
 
        self.assertCmpByDirs(-1, b'aabb', b'abbb')
459
 
        self.assertCmpByDirs(-1, b'abbb', b'bbbb')
460
 
        self.assertCmpByDirs(-1, b'aaaaa', b'aaaab')
461
 
        self.assertCmpByDirs(-1, b'a/a', b'a/b')
462
 
        self.assertCmpByDirs(-1, b'a/b', b'b/b')
463
 
        self.assertCmpByDirs(-1, b'a/a/a', b'a/a/b')
464
 
        self.assertCmpByDirs(-1, b'a/a/b', b'a/b/b')
465
 
        self.assertCmpByDirs(-1, b'a/b/b', b'b/b/b')
466
 
        self.assertCmpByDirs(-1, b'a/a/a/a', b'a/a/a/b')
467
 
        self.assertCmpByDirs(-1, b'a/a/a/b', b'a/a/b/b')
468
 
        self.assertCmpByDirs(-1, b'a/a/b/b', b'a/b/b/b')
469
 
        self.assertCmpByDirs(-1, b'a/b/b/b', b'b/b/b/b')
470
 
        self.assertCmpByDirs(-1, b'a/a/a/a/a', b'a/a/a/a/b')
 
449
        self.assertCmpByDirs(-1, 'a', 'b')
 
450
        self.assertCmpByDirs(-1, 'aa', 'ab')
 
451
        self.assertCmpByDirs(-1, 'ab', 'bb')
 
452
        self.assertCmpByDirs(-1, 'aaa', 'aab')
 
453
        self.assertCmpByDirs(-1, 'aab', 'abb')
 
454
        self.assertCmpByDirs(-1, 'abb', 'bbb')
 
455
        self.assertCmpByDirs(-1, 'aaaa', 'aaab')
 
456
        self.assertCmpByDirs(-1, 'aaab', 'aabb')
 
457
        self.assertCmpByDirs(-1, 'aabb', 'abbb')
 
458
        self.assertCmpByDirs(-1, 'abbb', 'bbbb')
 
459
        self.assertCmpByDirs(-1, 'aaaaa', 'aaaab')
 
460
        self.assertCmpByDirs(-1, 'a/a', 'a/b')
 
461
        self.assertCmpByDirs(-1, 'a/b', 'b/b')
 
462
        self.assertCmpByDirs(-1, 'a/a/a', 'a/a/b')
 
463
        self.assertCmpByDirs(-1, 'a/a/b', 'a/b/b')
 
464
        self.assertCmpByDirs(-1, 'a/b/b', 'b/b/b')
 
465
        self.assertCmpByDirs(-1, 'a/a/a/a', 'a/a/a/b')
 
466
        self.assertCmpByDirs(-1, 'a/a/a/b', 'a/a/b/b')
 
467
        self.assertCmpByDirs(-1, 'a/a/b/b', 'a/b/b/b')
 
468
        self.assertCmpByDirs(-1, 'a/b/b/b', 'b/b/b/b')
 
469
        self.assertCmpByDirs(-1, 'a/a/a/a/a', 'a/a/a/a/b')
471
470
 
472
471
    def test_tricky_paths(self):
473
 
        self.assertCmpByDirs(1, b'ab/cd/ef', b'ab/cc/ef')
474
 
        self.assertCmpByDirs(1, b'ab/cd/ef', b'ab/c/ef')
475
 
        self.assertCmpByDirs(-1, b'ab/cd/ef', b'ab/cd-ef')
476
 
        self.assertCmpByDirs(-1, b'ab/cd', b'ab/cd-')
477
 
        self.assertCmpByDirs(-1, b'ab/cd', b'ab-cd')
 
472
        self.assertCmpByDirs(1, 'ab/cd/ef', 'ab/cc/ef')
 
473
        self.assertCmpByDirs(1, 'ab/cd/ef', 'ab/c/ef')
 
474
        self.assertCmpByDirs(-1, 'ab/cd/ef', 'ab/cd-ef')
 
475
        self.assertCmpByDirs(-1, 'ab/cd', 'ab/cd-')
 
476
        self.assertCmpByDirs(-1, 'ab/cd', 'ab-cd')
478
477
 
479
478
    def test_cmp_unicode_not_allowed(self):
480
479
        lt_by_dirs = self.get_lt_by_dirs()
481
 
        self.assertRaises(TypeError, lt_by_dirs, u'Unicode', b'str')
482
 
        self.assertRaises(TypeError, lt_by_dirs, b'str', u'Unicode')
 
480
        self.assertRaises(TypeError, lt_by_dirs, u'Unicode', 'str')
 
481
        self.assertRaises(TypeError, lt_by_dirs, 'str', u'Unicode')
483
482
        self.assertRaises(TypeError, lt_by_dirs, u'Unicode', u'Unicode')
484
483
 
485
484
    def test_cmp_non_ascii(self):
486
 
        self.assertCmpByDirs(-1, b'\xc2\xb5', b'\xc3\xa5')  # u'\xb5', u'\xe5'
487
 
        self.assertCmpByDirs(-1, b'a', b'\xc3\xa5')  # u'a', u'\xe5'
488
 
        self.assertCmpByDirs(-1, b'b', b'\xc2\xb5')  # u'b', u'\xb5'
489
 
        self.assertCmpByDirs(-1, b'a/b', b'a/\xc3\xa5')  # u'a/b', u'a/\xe5'
490
 
        self.assertCmpByDirs(-1, b'b/a', b'b/\xc2\xb5')  # u'b/a', u'b/\xb5'
 
485
        self.assertCmpByDirs(-1, '\xc2\xb5', '\xc3\xa5') # u'\xb5', u'\xe5'
 
486
        self.assertCmpByDirs(-1, 'a', '\xc3\xa5') # u'a', u'\xe5'
 
487
        self.assertCmpByDirs(-1, 'b', '\xc2\xb5') # u'b', u'\xb5'
 
488
        self.assertCmpByDirs(-1, 'a/b', 'a/\xc3\xa5') # u'a/b', u'a/\xe5'
 
489
        self.assertCmpByDirs(-1, 'b/a', 'b/\xc2\xb5') # u'b/a', u'b/\xb5'
491
490
 
492
491
 
493
492
class TestCompiledLtByDirs(TestLtByDirs):
526
525
        # First, make sure the paths being passed in are correct
527
526
        def _key(p):
528
527
            dirname, basename = os.path.split(p)
529
 
            return dirname.split(b'/'), basename
 
528
            return dirname.split('/'), basename
530
529
        self.assertEqual(sorted(paths, key=_key), paths)
531
530
 
532
531
        lt_path_by_dirblock = self.get_lt_path_by_dirblock()
534
533
            for idx2, path2 in enumerate(paths):
535
534
                lt_result = lt_path_by_dirblock(path1, path2)
536
535
                self.assertEqual(idx1 < idx2, lt_result,
537
 
                                 '%s did not state that %r < %r, lt=%s'
538
 
                                 % (lt_path_by_dirblock.__name__,
539
 
                                    path1, path2, lt_result))
 
536
                        '%s did not state that %r < %r, lt=%s'
 
537
                        % (lt_path_by_dirblock.__name__,
 
538
                           path1, path2, lt_result))
540
539
 
541
540
    def test_cmp_simple_paths(self):
542
541
        """Compare against the empty string."""
543
 
        self.assertLtPathByDirblock(
544
 
            [b'', b'a', b'ab', b'abc', b'a/b/c', b'b/d/e'])
545
 
        self.assertLtPathByDirblock([b'kl', b'ab/cd', b'ab/ef', b'gh/ij'])
 
542
        self.assertLtPathByDirblock(['', 'a', 'ab', 'abc', 'a/b/c', 'b/d/e'])
 
543
        self.assertLtPathByDirblock(['kl', 'ab/cd', 'ab/ef', 'gh/ij'])
546
544
 
547
545
    def test_tricky_paths(self):
548
546
        self.assertLtPathByDirblock([
549
547
            # Contents of ''
550
 
            b'', b'a', b'a-a', b'a=a', b'b',
 
548
            '', 'a', 'a-a', 'a=a', 'b',
551
549
            # Contents of 'a'
552
 
            b'a/a', b'a/a-a', b'a/a=a', b'a/b',
 
550
            'a/a', 'a/a-a', 'a/a=a', 'a/b',
553
551
            # Contents of 'a/a'
554
 
            b'a/a/a', b'a/a/a-a', b'a/a/a=a',
 
552
            'a/a/a', 'a/a/a-a', 'a/a/a=a',
555
553
            # Contents of 'a/a/a'
556
 
            b'a/a/a/a', b'a/a/a/b',
 
554
            'a/a/a/a', 'a/a/a/b',
557
555
            # Contents of 'a/a/a-a',
558
 
            b'a/a/a-a/a', b'a/a/a-a/b',
 
556
            'a/a/a-a/a', 'a/a/a-a/b',
559
557
            # Contents of 'a/a/a=a',
560
 
            b'a/a/a=a/a', b'a/a/a=a/b',
 
558
            'a/a/a=a/a', 'a/a/a=a/b',
561
559
            # Contents of 'a/a-a'
562
 
            b'a/a-a/a',
 
560
            'a/a-a/a',
563
561
            # Contents of 'a/a-a/a'
564
 
            b'a/a-a/a/a', b'a/a-a/a/b',
 
562
            'a/a-a/a/a', 'a/a-a/a/b',
565
563
            # Contents of 'a/a=a'
566
 
            b'a/a=a/a',
 
564
            'a/a=a/a',
567
565
            # Contents of 'a/b'
568
 
            b'a/b/a', b'a/b/b',
 
566
            'a/b/a', 'a/b/b',
569
567
            # Contents of 'a-a',
570
 
            b'a-a/a', b'a-a/b',
 
568
            'a-a/a', 'a-a/b',
571
569
            # Contents of 'a=a',
572
 
            b'a=a/a', b'a=a/b',
 
570
            'a=a/a', 'a=a/b',
573
571
            # Contents of 'b',
574
 
            b'b/a', b'b/b',
 
572
            'b/a', 'b/b',
575
573
            ])
576
574
        self.assertLtPathByDirblock([
577
 
            # content of '/'
578
 
            b'', b'a', b'a-a', b'a-z', b'a=a', b'a=z',
 
575
                 # content of '/'
 
576
                 '', 'a', 'a-a', 'a-z', 'a=a', 'a=z',
579
577
                 # content of 'a/'
580
 
                 b'a/a', b'a/a-a', b'a/a-z',
581
 
                 b'a/a=a', b'a/a=z',
582
 
                 b'a/z', b'a/z-a', b'a/z-z',
583
 
                 b'a/z=a', b'a/z=z',
 
578
                 'a/a', 'a/a-a', 'a/a-z',
 
579
                 'a/a=a', 'a/a=z',
 
580
                 'a/z', 'a/z-a', 'a/z-z',
 
581
                 'a/z=a', 'a/z=z',
584
582
                 # content of 'a/a/'
585
 
                 b'a/a/a', b'a/a/z',
 
583
                 'a/a/a', 'a/a/z',
586
584
                 # content of 'a/a-a'
587
 
                 b'a/a-a/a',
 
585
                 'a/a-a/a',
588
586
                 # content of 'a/a-z'
589
 
                 b'a/a-z/z',
 
587
                 'a/a-z/z',
590
588
                 # content of 'a/a=a'
591
 
                 b'a/a=a/a',
 
589
                 'a/a=a/a',
592
590
                 # content of 'a/a=z'
593
 
                 b'a/a=z/z',
 
591
                 'a/a=z/z',
594
592
                 # content of 'a/z/'
595
 
                 b'a/z/a', b'a/z/z',
 
593
                 'a/z/a', 'a/z/z',
596
594
                 # content of 'a-a'
597
 
                 b'a-a/a',
 
595
                 'a-a/a',
598
596
                 # content of 'a-z'
599
 
                 b'a-z/z',
 
597
                 'a-z/z',
600
598
                 # content of 'a=a'
601
 
                 b'a=a/a',
 
599
                 'a=a/a',
602
600
                 # content of 'a=z'
603
 
                 b'a=z/z',
604
 
            ])
 
601
                 'a=z/z',
 
602
                ])
605
603
 
606
604
    def test_unicode_not_allowed(self):
607
605
        lt_path_by_dirblock = self.get_lt_path_by_dirblock()
615
613
    def test_nonascii(self):
616
614
        self.assertLtPathByDirblock([
617
615
            # content of '/'
618
 
            b'', b'a', b'\xc2\xb5', b'\xc3\xa5',
 
616
            '', 'a', '\xc2\xb5', '\xc3\xa5',
619
617
            # content of 'a'
620
 
            b'a/a', b'a/\xc2\xb5', b'a/\xc3\xa5',
 
618
            'a/a', 'a/\xc2\xb5', 'a/\xc3\xa5',
621
619
            # content of 'a/a'
622
 
            b'a/a/a', b'a/a/\xc2\xb5', b'a/a/\xc3\xa5',
 
620
            'a/a/a', 'a/a/\xc2\xb5', 'a/a/\xc3\xa5',
623
621
            # content of 'a/\xc2\xb5'
624
 
            b'a/\xc2\xb5/a', b'a/\xc2\xb5/\xc2\xb5', b'a/\xc2\xb5/\xc3\xa5',
 
622
            'a/\xc2\xb5/a', 'a/\xc2\xb5/\xc2\xb5', 'a/\xc2\xb5/\xc3\xa5',
625
623
            # content of 'a/\xc3\xa5'
626
 
            b'a/\xc3\xa5/a', b'a/\xc3\xa5/\xc2\xb5', b'a/\xc3\xa5/\xc3\xa5',
 
624
            'a/\xc3\xa5/a', 'a/\xc3\xa5/\xc2\xb5', 'a/\xc3\xa5/\xc3\xa5',
627
625
            # content of '\xc2\xb5'
628
 
            b'\xc2\xb5/a', b'\xc2\xb5/\xc2\xb5', b'\xc2\xb5/\xc3\xa5',
 
626
            '\xc2\xb5/a', '\xc2\xb5/\xc2\xb5', '\xc2\xb5/\xc3\xa5',
629
627
            # content of '\xc2\xe5'
630
 
            b'\xc3\xa5/a', b'\xc3\xa5/\xc2\xb5', b'\xc3\xa5/\xc3\xa5',
 
628
            '\xc3\xa5/a', '\xc3\xa5/\xc2\xb5', '\xc3\xa5/\xc3\xa5',
631
629
            ])
632
630
 
633
631
 
651
649
        self.assertEqual(expected, _py_memrchr(s, c))
652
650
 
653
651
    def test_missing(self):
654
 
        self.assertMemRChr(None, b'', b'a')
655
 
        self.assertMemRChr(None, b'', b'c')
656
 
        self.assertMemRChr(None, b'abcdefghijklm', b'q')
657
 
        self.assertMemRChr(None, b'aaaaaaaaaaaaaaaaaaaaaaa', b'b')
 
652
        self.assertMemRChr(None, '', 'a')
 
653
        self.assertMemRChr(None, '', 'c')
 
654
        self.assertMemRChr(None, 'abcdefghijklm', 'q')
 
655
        self.assertMemRChr(None, 'aaaaaaaaaaaaaaaaaaaaaaa', 'b')
658
656
 
659
657
    def test_single_entry(self):
660
 
        self.assertMemRChr(0, b'abcdefghijklm', b'a')
661
 
        self.assertMemRChr(1, b'abcdefghijklm', b'b')
662
 
        self.assertMemRChr(2, b'abcdefghijklm', b'c')
663
 
        self.assertMemRChr(10, b'abcdefghijklm', b'k')
664
 
        self.assertMemRChr(11, b'abcdefghijklm', b'l')
665
 
        self.assertMemRChr(12, b'abcdefghijklm', b'm')
 
658
        self.assertMemRChr(0, 'abcdefghijklm', 'a')
 
659
        self.assertMemRChr(1, 'abcdefghijklm', 'b')
 
660
        self.assertMemRChr(2, 'abcdefghijklm', 'c')
 
661
        self.assertMemRChr(10, 'abcdefghijklm', 'k')
 
662
        self.assertMemRChr(11, 'abcdefghijklm', 'l')
 
663
        self.assertMemRChr(12, 'abcdefghijklm', 'm')
666
664
 
667
665
    def test_multiple(self):
668
 
        self.assertMemRChr(10, b'abcdefjklmabcdefghijklm', b'a')
669
 
        self.assertMemRChr(11, b'abcdefjklmabcdefghijklm', b'b')
670
 
        self.assertMemRChr(12, b'abcdefjklmabcdefghijklm', b'c')
671
 
        self.assertMemRChr(20, b'abcdefjklmabcdefghijklm', b'k')
672
 
        self.assertMemRChr(21, b'abcdefjklmabcdefghijklm', b'l')
673
 
        self.assertMemRChr(22, b'abcdefjklmabcdefghijklm', b'm')
674
 
        self.assertMemRChr(22, b'aaaaaaaaaaaaaaaaaaaaaaa', b'a')
 
666
        self.assertMemRChr(10, 'abcdefjklmabcdefghijklm', 'a')
 
667
        self.assertMemRChr(11, 'abcdefjklmabcdefghijklm', 'b')
 
668
        self.assertMemRChr(12, 'abcdefjklmabcdefghijklm', 'c')
 
669
        self.assertMemRChr(20, 'abcdefjklmabcdefghijklm', 'k')
 
670
        self.assertMemRChr(21, 'abcdefjklmabcdefghijklm', 'l')
 
671
        self.assertMemRChr(22, 'abcdefjklmabcdefghijklm', 'm')
 
672
        self.assertMemRChr(22, 'aaaaaaaaaaaaaaaaaaaaaaa', 'a')
675
673
 
676
674
    def test_with_nulls(self):
677
 
        self.assertMemRChr(10, b'abc\0\0\0jklmabc\0\0\0ghijklm', b'a')
678
 
        self.assertMemRChr(11, b'abc\0\0\0jklmabc\0\0\0ghijklm', b'b')
679
 
        self.assertMemRChr(12, b'abc\0\0\0jklmabc\0\0\0ghijklm', b'c')
680
 
        self.assertMemRChr(20, b'abc\0\0\0jklmabc\0\0\0ghijklm', b'k')
681
 
        self.assertMemRChr(21, b'abc\0\0\0jklmabc\0\0\0ghijklm', b'l')
682
 
        self.assertMemRChr(22, b'abc\0\0\0jklmabc\0\0\0ghijklm', b'm')
683
 
        self.assertMemRChr(22, b'aaa\0\0\0aaaaaaa\0\0\0aaaaaaa', b'a')
684
 
        self.assertMemRChr(9, b'\0\0\0\0\0\0\0\0\0\0', b'\0')
 
675
        self.assertMemRChr(10, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'a')
 
676
        self.assertMemRChr(11, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'b')
 
677
        self.assertMemRChr(12, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'c')
 
678
        self.assertMemRChr(20, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'k')
 
679
        self.assertMemRChr(21, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'l')
 
680
        self.assertMemRChr(22, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'm')
 
681
        self.assertMemRChr(22, 'aaa\0\0\0aaaaaaa\0\0\0aaaaaaa', 'a')
 
682
        self.assertMemRChr(9, '\0\0\0\0\0\0\0\0\0\0', '\0')
685
683
 
686
684
 
687
685
class TestReadDirblocks(test_dirstate.TestCaseWithDirState):
721
719
        f = open('dirstate', 'ab')
722
720
        try:
723
721
            # Add bogus trailing garbage
724
 
            f.write(b'bogus\n')
 
722
            f.write('bogus\n')
725
723
        finally:
726
724
            f.close()
727
725
            state.lock_read()
817
815
        """Create a DirState tracking a single object named 'a'"""
818
816
        state = test_dirstate.InstrumentedDirState.initialize('dirstate')
819
817
        self.addCleanup(state.unlock)
820
 
        state.add('a', b'a-id', 'file', None, b'')
821
 
        entry = state._get_entry(0, path_utf8=b'a')
 
818
        state.add('a', b'a-id', 'file', None, '')
 
819
        entry = state._get_entry(0, path_utf8='a')
822
820
        return state, entry
823
821
 
824
822
    def test_observed_sha1_cachable(self):
830
828
        statvalue.st_mtime = statvalue.st_ctime = atime
831
829
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
832
830
                         state._dirblock_state)
833
 
        state._observed_sha1(entry, b"foo", statvalue)
834
 
        self.assertEqual(b'foo', entry[1][0][1])
 
831
        state._observed_sha1(entry, "foo", statvalue)
 
832
        self.assertEqual('foo', entry[1][0][1])
835
833
        packed_stat = dirstate.pack_stat(statvalue)
836
834
        self.assertEqual(packed_stat, entry[1][0][4])
837
835
        self.assertEqual(dirstate.DirState.IN_MEMORY_HASH_MODIFIED,
864
862
        state.set_parent_trees(
865
863
            [(empty_revid, tree.branch.repository.revision_tree(empty_revid))],
866
864
            [])
867
 
        entry = state._get_entry(0, path_utf8=b'a')
 
865
        entry = state._get_entry(0, path_utf8='a')
868
866
        self.build_tree(['a'])
869
867
        # Add one where we don't provide the stat or sha already
870
 
        self.assertEqual((b'', b'a', b'a-id'), entry[0])
871
 
        self.assertEqual((b'f', b'', 0, False, dirstate.DirState.NULLSTAT),
 
868
        self.assertEqual(('', 'a', 'a-id'), entry[0])
 
869
        self.assertEqual(('f', '', 0, False, dirstate.DirState.NULLSTAT),
872
870
                         entry[1][0])
873
871
        # Flush the buffers to disk
874
872
        state.save()
877
875
 
878
876
        stat_value = os.lstat('a')
879
877
        packed_stat = dirstate.pack_stat(stat_value)
880
 
        link_or_sha1 = self.update_entry(state, entry, abspath=b'a',
881
 
                                         stat_value=stat_value)
 
878
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
 
879
                                          stat_value=stat_value)
882
880
        self.assertEqual(None, link_or_sha1)
883
881
 
884
882
        # The dirblock entry should not have computed or cached the file's
885
883
        # sha1, but it did update the files' st_size. However, this is not
886
884
        # worth writing a dirstate file for, so we leave the state UNMODIFIED
887
 
        self.assertEqual((b'f', b'', 14, False, dirstate.DirState.NULLSTAT),
 
885
        self.assertEqual(('f', '', 14, False, dirstate.DirState.NULLSTAT),
888
886
                         entry[1][0])
889
887
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
890
888
                         state._dirblock_state)
900
898
        state.adjust_time(-10)
901
899
        del state._log[:]
902
900
 
903
 
        link_or_sha1 = self.update_entry(state, entry, abspath=b'a',
904
 
                                         stat_value=stat_value)
 
901
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
 
902
                                          stat_value=stat_value)
905
903
        self.assertEqual([('is_exec', mode, False)], state._log)
906
904
        self.assertEqual(None, link_or_sha1)
907
905
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
908
906
                         state._dirblock_state)
909
 
        self.assertEqual((b'f', b'', 14, False, dirstate.DirState.NULLSTAT),
 
907
        self.assertEqual(('f', '', 14, False, dirstate.DirState.NULLSTAT),
910
908
                         entry[1][0])
911
909
        state.save()
912
910
 
914
912
        # won't calculate the sha or cache it.
915
913
        state.adjust_time(+20)
916
914
        del state._log[:]
917
 
        link_or_sha1 = dirstate.update_entry(state, entry, abspath=b'a',
918
 
                                             stat_value=stat_value)
 
915
        link_or_sha1 = dirstate.update_entry(state, entry, abspath='a',
 
916
                                          stat_value=stat_value)
919
917
        self.assertEqual(None, link_or_sha1)
920
918
        self.assertEqual([('is_exec', mode, False)], state._log)
921
 
        self.assertEqual((b'f', b'', 14, False, dirstate.DirState.NULLSTAT),
 
919
        self.assertEqual(('f', '', 14, False, dirstate.DirState.NULLSTAT),
922
920
                         entry[1][0])
923
921
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
924
922
                         state._dirblock_state)
929
927
        state.set_parent_trees(
930
928
            [(with_a_id, tree.branch.repository.revision_tree(with_a_id))],
931
929
            [])
932
 
        entry = state._get_entry(0, path_utf8=b'a')
 
930
        entry = state._get_entry(0, path_utf8='a')
933
931
 
934
 
        link_or_sha1 = self.update_entry(state, entry, abspath=b'a',
935
 
                                         stat_value=stat_value)
936
 
        self.assertEqual(b'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
 
932
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
 
933
                                          stat_value=stat_value)
 
934
        self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
937
935
                         link_or_sha1)
938
 
        self.assertEqual([('is_exec', mode, False), ('sha1', b'a')],
939
 
                         state._log)
940
 
        self.assertEqual((b'f', link_or_sha1, 14, False, packed_stat),
 
936
        self.assertEqual([('is_exec', mode, False), ('sha1', 'a')],
 
937
                          state._log)
 
938
        self.assertEqual(('f', link_or_sha1, 14, False, packed_stat),
941
939
                         entry[1][0])
942
940
 
943
941
        # Subsequent calls will just return the cached value
944
942
        del state._log[:]
945
 
        link_or_sha1 = self.update_entry(state, entry, abspath=b'a',
946
 
                                         stat_value=stat_value)
947
 
        self.assertEqual(b'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
 
943
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
 
944
                                          stat_value=stat_value)
 
945
        self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
948
946
                         link_or_sha1)
949
947
        self.assertEqual([], state._log)
950
 
        self.assertEqual((b'f', link_or_sha1, 14, False, packed_stat),
 
948
        self.assertEqual(('f', link_or_sha1, 14, False, packed_stat),
951
949
                         entry[1][0])
952
950
 
953
951
    def test_update_entry_symlink(self):
959
957
                         state._dirblock_state)
960
958
        os.symlink('target', 'a')
961
959
 
962
 
        state.adjust_time(-10)  # Make the symlink look new
 
960
        state.adjust_time(-10) # Make the symlink look new
963
961
        stat_value = os.lstat('a')
964
962
        packed_stat = dirstate.pack_stat(stat_value)
965
 
        link_or_sha1 = self.update_entry(state, entry, abspath=b'a',
966
 
                                         stat_value=stat_value)
967
 
        self.assertEqual(b'target', link_or_sha1)
968
 
        self.assertEqual([('read_link', b'a', b'')], state._log)
 
963
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
 
964
                                          stat_value=stat_value)
 
965
        self.assertEqual('target', link_or_sha1)
 
966
        self.assertEqual([('read_link', 'a', '')], state._log)
969
967
        # Dirblock is not updated (the link is too new)
970
 
        self.assertEqual([(b'l', b'', 6, False, dirstate.DirState.NULLSTAT)],
 
968
        self.assertEqual([('l', '', 6, False, dirstate.DirState.NULLSTAT)],
971
969
                         entry[1])
972
970
        # The file entry turned into a symlink, that is considered
973
971
        # HASH modified worthy.
976
974
 
977
975
        # Because the stat_value looks new, we should re-read the target
978
976
        del state._log[:]
979
 
        link_or_sha1 = self.update_entry(state, entry, abspath=b'a',
980
 
                                         stat_value=stat_value)
981
 
        self.assertEqual(b'target', link_or_sha1)
982
 
        self.assertEqual([('read_link', b'a', b'')], state._log)
983
 
        self.assertEqual([(b'l', b'', 6, False, dirstate.DirState.NULLSTAT)],
 
977
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
 
978
                                          stat_value=stat_value)
 
979
        self.assertEqual('target', link_or_sha1)
 
980
        self.assertEqual([('read_link', 'a', '')], state._log)
 
981
        self.assertEqual([('l', '', 6, False, dirstate.DirState.NULLSTAT)],
984
982
                         entry[1])
985
983
        state.save()
986
 
        state.adjust_time(+20)  # Skip into the future, all files look old
 
984
        state.adjust_time(+20) # Skip into the future, all files look old
987
985
        del state._log[:]
988
 
        link_or_sha1 = self.update_entry(state, entry, abspath=b'a',
989
 
                                         stat_value=stat_value)
 
986
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
 
987
                                          stat_value=stat_value)
990
988
        # The symlink stayed a symlink. So while it is new enough to cache, we
991
989
        # don't bother setting the flag, because it is not really worth saving
992
990
        # (when we stat the symlink, we'll have paged in the target.)
993
991
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
994
992
                         state._dirblock_state)
995
 
        self.assertEqual(b'target', link_or_sha1)
 
993
        self.assertEqual('target', link_or_sha1)
996
994
        # We need to re-read the link because only now can we cache it
997
 
        self.assertEqual([('read_link', b'a', b'')], state._log)
998
 
        self.assertEqual([(b'l', b'target', 6, False, packed_stat)],
 
995
        self.assertEqual([('read_link', 'a', '')], state._log)
 
996
        self.assertEqual([('l', 'target', 6, False, packed_stat)],
999
997
                         entry[1])
1000
998
 
1001
999
        del state._log[:]
1002
1000
        # Another call won't re-read the link
1003
1001
        self.assertEqual([], state._log)
1004
 
        link_or_sha1 = self.update_entry(state, entry, abspath=b'a',
1005
 
                                         stat_value=stat_value)
1006
 
        self.assertEqual(b'target', link_or_sha1)
1007
 
        self.assertEqual([(b'l', b'target', 6, False, packed_stat)],
 
1002
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
 
1003
                                          stat_value=stat_value)
 
1004
        self.assertEqual('target', link_or_sha1)
 
1005
        self.assertEqual([('l', 'target', 6, False, packed_stat)],
1008
1006
                         entry[1])
1009
1007
 
1010
1008
    def do_update_entry(self, state, entry, abspath):
1014
1012
    def test_update_entry_dir(self):
1015
1013
        state, entry = self.get_state_with_a()
1016
1014
        self.build_tree(['a/'])
1017
 
        self.assertIs(None, self.do_update_entry(state, entry, b'a'))
 
1015
        self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1018
1016
 
1019
1017
    def test_update_entry_dir_unchanged(self):
1020
1018
        state, entry = self.get_state_with_a()
1021
1019
        self.build_tree(['a/'])
1022
1020
        state.adjust_time(+20)
1023
 
        self.assertIs(None, self.do_update_entry(state, entry, b'a'))
 
1021
        self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1024
1022
        # a/ used to be a file, but is now a directory, worth saving
1025
1023
        self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
1026
1024
                         state._dirblock_state)
1028
1026
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1029
1027
                         state._dirblock_state)
1030
1028
        # No changes to a/ means not worth saving.
1031
 
        self.assertIs(None, self.do_update_entry(state, entry, b'a'))
 
1029
        self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1032
1030
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1033
1031
                         state._dirblock_state)
1034
1032
        # Change the last-modified time for the directory
1039
1037
            # It looks like Win32 + FAT doesn't allow to change times on a dir.
1040
1038
            raise tests.TestSkipped("can't update mtime of a dir on FAT")
1041
1039
        saved_packed_stat = entry[1][0][-1]
1042
 
        self.assertIs(None, self.do_update_entry(state, entry, b'a'))
 
1040
        self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1043
1041
        # We *do* go ahead and update the information in the dirblocks, but we
1044
1042
        # don't bother setting IN_MEMORY_MODIFIED because it is trivial to
1045
1043
        # recompute.
1058
1056
        state.set_parent_trees(
1059
1057
            [(with_a_id, tree.branch.repository.revision_tree(with_a_id))],
1060
1058
            [])
1061
 
        entry = state._get_entry(0, path_utf8=b'a')
 
1059
        entry = state._get_entry(0, path_utf8='a')
1062
1060
        self.build_tree(['a'])
1063
 
        sha1sum = b'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
 
1061
        sha1sum = 'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
1064
1062
        state.adjust_time(+20)
1065
 
        self.assertEqual(sha1sum, self.do_update_entry(state, entry, b'a'))
 
1063
        self.assertEqual(sha1sum, self.do_update_entry(state, entry, 'a'))
1066
1064
        self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
1067
1065
                         state._dirblock_state)
1068
1066
        state.save()
1069
1067
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1070
1068
                         state._dirblock_state)
1071
 
        self.assertEqual(sha1sum, self.do_update_entry(state, entry, b'a'))
 
1069
        self.assertEqual(sha1sum, self.do_update_entry(state, entry, 'a'))
1072
1070
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1073
1071
                         state._dirblock_state)
1074
1072
 
1075
1073
    def test_update_entry_tree_reference(self):
1076
1074
        state = test_dirstate.InstrumentedDirState.initialize('dirstate')
1077
1075
        self.addCleanup(state.unlock)
1078
 
        state.add('r', b'r-id', 'tree-reference', None, b'')
 
1076
        state.add('r', b'r-id', 'tree-reference', None, '')
1079
1077
        self.build_tree(['r/'])
1080
 
        entry = state._get_entry(0, path_utf8=b'r')
 
1078
        entry = state._get_entry(0, path_utf8='r')
1081
1079
        self.do_update_entry(state, entry, 'r')
1082
 
        entry = state._get_entry(0, path_utf8=b'r')
1083
 
        self.assertEqual(b't', entry[1][0][0])
 
1080
        entry = state._get_entry(0, path_utf8='r')
 
1081
        self.assertEqual('t', entry[1][0][0])
1084
1082
 
1085
1083
    def create_and_test_file(self, state, entry):
1086
1084
        """Create a file at 'a' and verify the state finds it during update.
1094
1092
 
1095
1093
        link_or_sha1 = self.do_update_entry(state, entry, abspath='a')
1096
1094
        self.assertEqual(None, link_or_sha1)
1097
 
        self.assertEqual([(b'f', b'', 14, False, dirstate.DirState.NULLSTAT)],
 
1095
        self.assertEqual([('f', '', 14, False, dirstate.DirState.NULLSTAT)],
1098
1096
                         entry[1])
1099
1097
        return packed_stat
1100
1098
 
1108
1106
        stat_value = os.lstat('a')
1109
1107
        packed_stat = dirstate.pack_stat(stat_value)
1110
1108
 
1111
 
        link_or_sha1 = self.do_update_entry(state, entry, abspath=b'a')
 
1109
        link_or_sha1 = self.do_update_entry(state, entry, abspath='a')
1112
1110
        self.assertIs(None, link_or_sha1)
1113
 
        self.assertEqual([(b'd', b'', 0, False, packed_stat)], entry[1])
 
1111
        self.assertEqual([('d', '', 0, False, packed_stat)], entry[1])
1114
1112
 
1115
1113
        return packed_stat
1116
1114
 
1130
1128
        stat_value = os.lstat('a')
1131
1129
        packed_stat = dirstate.pack_stat(stat_value)
1132
1130
 
1133
 
        link_or_sha1 = self.do_update_entry(state, entry, abspath=b'a')
1134
 
        self.assertEqual(b'path/to/foo', link_or_sha1)
1135
 
        self.assertEqual([(b'l', b'path/to/foo', 11, False, packed_stat)],
 
1131
        link_or_sha1 = self.do_update_entry(state, entry, abspath='a')
 
1132
        self.assertEqual('path/to/foo', link_or_sha1)
 
1133
        self.assertEqual([('l', 'path/to/foo', 11, False, packed_stat)],
1136
1134
                         entry[1])
1137
1135
        return packed_stat
1138
1136
 
1200
1198
        state, entry = self.get_state_with_a()
1201
1199
        self.build_tree(['a'])
1202
1200
 
1203
 
        # Make sure we are using the version of _is_executable that doesn't
1204
 
        # check the filesystem mode.
1205
 
        state._use_filesystem_for_exec = False
 
1201
        # Make sure we are using the win32 implementation of _is_executable
 
1202
        state._is_executable = state._is_executable_win32
1206
1203
 
1207
1204
        # The file on disk is not executable, but we are marking it as though
1208
 
        # it is. With _use_filesystem_for_exec disabled we ignore what is on
1209
 
        # disk.
1210
 
        entry[1][0] = (b'f', b'', 0, True, dirstate.DirState.NULLSTAT)
 
1205
        # it is. With _is_executable_win32 we ignore what is on disk.
 
1206
        entry[1][0] = ('f', '', 0, True, dirstate.DirState.NULLSTAT)
1211
1207
 
1212
1208
        stat_value = os.lstat('a')
1213
1209
        packed_stat = dirstate.pack_stat(stat_value)
1214
1210
 
1215
 
        state.adjust_time(-10)  # Make sure everything is new
1216
 
        self.update_entry(state, entry, abspath=b'a', stat_value=stat_value)
 
1211
        state.adjust_time(-10) # Make sure everything is new
 
1212
        self.update_entry(state, entry, abspath='a', stat_value=stat_value)
1217
1213
 
1218
1214
        # The row is updated, but the executable bit stays set.
1219
 
        self.assertEqual([(b'f', b'', 14, True, dirstate.DirState.NULLSTAT)],
 
1215
        self.assertEqual([('f', '', 14, True, dirstate.DirState.NULLSTAT)],
1220
1216
                         entry[1])
1221
1217
 
1222
1218
        # Make the disk object look old enough to cache (but it won't cache the
1223
1219
        # sha as it is a new file).
1224
1220
        state.adjust_time(+20)
1225
 
        digest = b'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
1226
 
        self.update_entry(state, entry, abspath=b'a', stat_value=stat_value)
1227
 
        self.assertEqual([(b'f', b'', 14, True, dirstate.DirState.NULLSTAT)],
1228
 
                         entry[1])
 
1221
        digest = 'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
 
1222
        self.update_entry(state, entry, abspath='a', stat_value=stat_value)
 
1223
        self.assertEqual([('f', '', 14, True, dirstate.DirState.NULLSTAT)],
 
1224
            entry[1])
1229
1225
 
1230
1226
    def _prepare_tree(self):
1231
1227
        # Create a tree
1241
1237
    def test_sha1provider_sha1_used(self):
1242
1238
        tree, text = self._prepare_tree()
1243
1239
        state = dirstate.DirState.from_tree(tree, 'dirstate',
1244
 
                                            UppercaseSHA1Provider())
 
1240
            UppercaseSHA1Provider())
1245
1241
        self.addCleanup(state.unlock)
1246
 
        expected_sha = osutils.sha_string(text.upper() + b"foo")
1247
 
        entry = state._get_entry(0, path_utf8=b'a file')
1248
 
        self.assertNotEqual((None, None), entry)
 
1242
        expected_sha = osutils.sha_string(text.upper() + "foo")
 
1243
        entry = state._get_entry(0, path_utf8='a file')
1249
1244
        state._sha_cutoff_time()
1250
1245
        state._cutoff_time += 10
1251
1246
        sha1 = self.update_entry(state, entry, 'tree/a file',
1260
1255
        state._sha1_provider = UppercaseSHA1Provider()
1261
1256
        # If we used the standard provider, it would look like nothing has
1262
1257
        # changed
1263
 
        file_ids_changed = [change.file_id for change
 
1258
        file_ids_changed = [change[0] for change
1264
1259
                            in tree.iter_changes(tree.basis_tree())]
1265
 
        self.assertEqual([b'a-file-id'], file_ids_changed)
 
1260
        self.assertEqual(['a-file-id'], file_ids_changed)
1266
1261
 
1267
1262
 
1268
1263
class UppercaseSHA1Provider(dirstate.SHA1Provider):
1272
1267
        return self.stat_and_sha1(abspath)[1]
1273
1268
 
1274
1269
    def stat_and_sha1(self, abspath):
1275
 
        with open(abspath, 'rb') as file_obj:
 
1270
        file_obj = file(abspath, 'rb')
 
1271
        try:
1276
1272
            statvalue = os.fstat(file_obj.fileno())
1277
 
            text = b''.join(file_obj.readlines())
1278
 
            sha1 = osutils.sha_string(text.upper() + b"foo")
 
1273
            text = ''.join(file_obj.readlines())
 
1274
            sha1 = osutils.sha_string(text.upper() + "foo")
 
1275
        finally:
 
1276
            file_obj.close()
1279
1277
        return statvalue, sha1
1280
1278
 
1281
1279
 
1291
1289
        self.overrideAttr(dirstate, '_process_entry', self._process_entry)
1292
1290
 
1293
1291
    def assertChangedFileIds(self, expected, tree):
1294
 
        with tree.lock_read():
1295
 
            file_ids = [info.file_id for info
 
1292
        tree.lock_read()
 
1293
        try:
 
1294
            file_ids = [info[0] for info
1296
1295
                        in tree.iter_changes(tree.basis_tree())]
 
1296
        finally:
 
1297
            tree.unlock()
1297
1298
        self.assertEqual(sorted(expected), sorted(file_ids))
1298
1299
 
1299
1300
    def test_exceptions_raised(self):
1308
1309
        tree.lock_read()
1309
1310
        self.addCleanup(tree.unlock)
1310
1311
        basis_tree = tree.basis_tree()
1311
 
 
1312
1312
        def is_inside_raises(*args, **kwargs):
1313
1313
            raise RuntimeError('stop this')
1314
 
        self.overrideAttr(dirstate, 'is_inside', is_inside_raises)
1315
 
        try:
1316
 
            from breezy.bzr import _dirstate_helpers_pyx
1317
 
        except ImportError:
1318
 
            pass
1319
 
        else:
1320
 
            self.overrideAttr(_dirstate_helpers_pyx,
1321
 
                              'is_inside', is_inside_raises)
1322
1314
        self.overrideAttr(osutils, 'is_inside', is_inside_raises)
1323
1315
        self.assertListRaises(RuntimeError, tree.iter_changes, basis_tree)
1324
1316
 
1326
1318
        tree = self.make_branch_and_tree('tree')
1327
1319
        self.build_tree(['tree/file'])
1328
1320
        tree.add(['file'], [b'file-id'])
1329
 
        self.assertChangedFileIds([tree.path2id(''), b'file-id'], tree)
 
1321
        self.assertChangedFileIds([tree.get_root_id(), b'file-id'], tree)
1330
1322
        tree.commit('one')
1331
1323
        self.assertChangedFileIds([], tree)
1332
1324
 
1355
1347
        return _dirstate_helpers_py._unpack_stat(packed_string)[stat_field]
1356
1348
 
1357
1349
    def test_result(self):
1358
 
        self.assertEqual(b"AAAQAAAAABAAAAARAAAAAgAAAAEAAIHk",
1359
 
                         self.pack((33252, 1, 2, 0, 0, 0, 4096, 15.5, 16.5, 17.5)))
 
1350
        self.assertEqual("AAAQAAAAABAAAAARAAAAAgAAAAEAAIHk",
 
1351
            self.pack((33252, 1, 2, 0, 0, 0, 4096, 15.5, 16.5, 17.5)))
1360
1352
 
1361
1353
    def test_giant_inode(self):
1362
1354
        packed = self.pack((33252, 0xF80000ABC, 0, 0, 0, 0, 0, 0, 0, 0))