/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: 2017-06-08 23:30:31 UTC
  • mto: This revision was merged to the branch mainline in revision 6690.
  • Revision ID: jelmer@jelmer.uk-20170608233031-3qavls2o7a1pqllj
Update imports.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
import os
21
21
import time
22
22
 
23
 
from ... import (
 
23
from .. import (
 
24
    errors,
24
25
    osutils,
25
26
    tests,
26
27
    )
27
 
from .. import (
 
28
from ..bzr import (
28
29
    dirstate,
29
30
    _dirstate_helpers_py,
30
31
    )
31
32
from . import (
32
33
    test_dirstate,
33
34
    )
34
 
from ...tests.test_osutils import dir_reader_scenarios
35
 
from ...tests.scenarios import (
 
35
from .test_osutils import dir_reader_scenarios
 
36
from .scenarios import (
36
37
    load_tests_apply_scenarios,
37
38
    multiply_scenarios,
38
39
    )
39
 
from ...tests import (
 
40
from . import (
40
41
    features,
41
42
    )
42
43
 
45
46
 
46
47
 
47
48
compiled_dirstate_helpers_feature = features.ModuleAvailableFeature(
48
 
    'breezy.bzr._dirstate_helpers_pyx')
 
49
    'breezy._dirstate_helpers_pyx')
49
50
 
50
51
 
51
52
# FIXME: we should also parametrize against SHA1Provider !
52
53
 
53
54
ue_scenarios = [('dirstate_Python',
54
 
                 {'update_entry': dirstate.py_update_entry})]
 
55
    {'update_entry': dirstate.py_update_entry})]
55
56
if compiled_dirstate_helpers_feature.available():
56
57
    update_entry = compiled_dirstate_helpers_feature.module.update_entry
57
58
    ue_scenarios.append(('dirstate_Pyrex', {'update_entry': update_entry}))
58
59
 
59
60
pe_scenarios = [('dirstate_Python',
60
 
                 {'_process_entry': dirstate.ProcessEntryPython})]
 
61
    {'_process_entry': dirstate.ProcessEntryPython})]
61
62
if compiled_dirstate_helpers_feature.available():
62
63
    process_entry = compiled_dirstate_helpers_feature.module.ProcessEntryC
63
64
    pe_scenarios.append(('dirstate_Pyrex', {'_process_entry': process_entry}))
65
66
helper_scenarios = [('dirstate_Python', {'helpers': _dirstate_helpers_py})]
66
67
if compiled_dirstate_helpers_feature.available():
67
68
    helper_scenarios.append(('dirstate_Pyrex',
68
 
                             {'helpers': compiled_dirstate_helpers_feature.module}))
 
69
        {'helpers': compiled_dirstate_helpers_feature.module}))
69
70
 
70
71
 
71
72
class TestBisectPathMixin(object):
120
121
                            bisect_split_idx, bisect_path_idx, path)
121
122
                         )
122
123
        if exists:
123
 
            self.assertEqual(path, paths[bisect_path_idx + offset])
 
124
            self.assertEqual(path, paths[bisect_path_idx+offset])
124
125
 
125
126
    def split_for_dirblocks(self, paths):
126
127
        dir_split_paths = []
127
128
        for path in paths:
128
129
            dirname, basename = os.path.split(path)
129
 
            dir_split_paths.append((dirname.split(b'/'), basename))
 
130
            dir_split_paths.append((dirname.split('/'), basename))
130
131
        dir_split_paths.sort()
131
132
        return dir_split_paths
132
133
 
133
134
    def test_simple(self):
134
135
        """In the simple case it works just like bisect_left"""
135
 
        paths = [b'', b'a', b'b', b'c', b'd']
 
136
        paths = ['', 'a', 'b', 'c', 'd']
136
137
        split_paths = self.split_for_dirblocks(paths)
137
138
        for path in paths:
138
139
            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)
 
140
        self.assertBisect(paths, split_paths, '_', exists=False)
 
141
        self.assertBisect(paths, split_paths, 'aa', exists=False)
 
142
        self.assertBisect(paths, split_paths, 'bb', exists=False)
 
143
        self.assertBisect(paths, split_paths, 'cc', exists=False)
 
144
        self.assertBisect(paths, split_paths, 'dd', exists=False)
 
145
        self.assertBisect(paths, split_paths, 'a/a', exists=False)
 
146
        self.assertBisect(paths, split_paths, 'b/b', exists=False)
 
147
        self.assertBisect(paths, split_paths, 'c/c', exists=False)
 
148
        self.assertBisect(paths, split_paths, 'd/d', exists=False)
148
149
 
149
150
    def test_involved(self):
150
151
        """This is where bisect_path_* diverges slightly."""
181
182
        # children are mentioned.
182
183
        # So all the root-directory paths, then all the
183
184
        # first sub directory, etc.
184
 
        paths = [  # content of '/'
185
 
            b'', b'a', b'a-a', b'a-z', b'a=a', b'a=z',
 
185
        paths = [# content of '/'
 
186
                 '', 'a', 'a-a', 'a-z', 'a=a', 'a=z',
186
187
                 # 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',
 
188
                 'a/a', 'a/a-a', 'a/a-z',
 
189
                 'a/a=a', 'a/a=z',
 
190
                 'a/z', 'a/z-a', 'a/z-z',
 
191
                 'a/z=a', 'a/z=z',
191
192
                 # content of 'a/a/'
192
 
                 b'a/a/a', b'a/a/z',
 
193
                 'a/a/a', 'a/a/z',
193
194
                 # content of 'a/a-a'
194
 
                 b'a/a-a/a',
 
195
                 'a/a-a/a',
195
196
                 # content of 'a/a-z'
196
 
                 b'a/a-z/z',
 
197
                 'a/a-z/z',
197
198
                 # content of 'a/a=a'
198
 
                 b'a/a=a/a',
 
199
                 'a/a=a/a',
199
200
                 # content of 'a/a=z'
200
 
                 b'a/a=z/z',
 
201
                 'a/a=z/z',
201
202
                 # content of 'a/z/'
202
 
                 b'a/z/a', b'a/z/z',
 
203
                 'a/z/a', 'a/z/z',
203
204
                 # content of 'a-a'
204
 
                 b'a-a/a',
 
205
                 'a-a/a',
205
206
                 # content of 'a-z'
206
 
                 b'a-z/z',
 
207
                 'a-z/z',
207
208
                 # content of 'a=a'
208
 
                 b'a=a/a',
 
209
                 'a=a/a',
209
210
                 # content of 'a=z'
210
 
                 b'a=z/z',
211
 
            ]
 
211
                 'a=z/z',
 
212
                ]
212
213
        split_paths = self.split_for_dirblocks(paths)
213
214
        sorted_paths = []
214
215
        for dir_parts, basename in split_paths:
215
 
            if dir_parts == [b'']:
 
216
            if dir_parts == ['']:
216
217
                sorted_paths.append(basename)
217
218
            else:
218
 
                sorted_paths.append(b'/'.join(dir_parts + [basename]))
 
219
                sorted_paths.append('/'.join(dir_parts + [basename]))
219
220
 
220
221
        self.assertEqual(sorted_paths, paths)
221
222
 
227
228
    """Run all Bisect Path tests against _bisect_path_left."""
228
229
 
229
230
    def get_bisect_path(self):
230
 
        from .._dirstate_helpers_py import _bisect_path_left
 
231
        from breezy._dirstate_helpers_py import _bisect_path_left
231
232
        return _bisect_path_left
232
233
 
233
234
    def get_bisect(self):
240
241
    _test_needs_features = [compiled_dirstate_helpers_feature]
241
242
 
242
243
    def get_bisect_path(self):
243
 
        from .._dirstate_helpers_pyx import _bisect_path_left
 
244
        from breezy._dirstate_helpers_pyx import _bisect_path_left
244
245
        return _bisect_path_left
245
246
 
246
247
 
248
249
    """Run all Bisect Path tests against _bisect_path_right"""
249
250
 
250
251
    def get_bisect_path(self):
251
 
        from .._dirstate_helpers_py import _bisect_path_right
 
252
        from breezy._dirstate_helpers_py import _bisect_path_right
252
253
        return _bisect_path_right
253
254
 
254
255
    def get_bisect(self):
261
262
    _test_needs_features = [compiled_dirstate_helpers_feature]
262
263
 
263
264
    def get_bisect_path(self):
264
 
        from .._dirstate_helpers_pyx import _bisect_path_right
 
265
        from breezy._dirstate_helpers_pyx import _bisect_path_right
265
266
        return _bisect_path_right
266
267
 
267
268
 
279
280
 
280
281
    def get_bisect_dirblock(self):
281
282
        """Return an implementation of bisect_dirblock"""
282
 
        from .._dirstate_helpers_py import bisect_dirblock
 
283
        from breezy._dirstate_helpers_py import bisect_dirblock
283
284
        return bisect_dirblock
284
285
 
285
286
    def assertBisect(self, dirblocks, split_dirblocks, path, *args, **kwargs):
294
295
        bisect_dirblock = self.get_bisect_dirblock()
295
296
        self.assertIsInstance(dirblocks, list)
296
297
        bisect_split_idx = bisect_dirblock(dirblocks, path, *args, **kwargs)
297
 
        split_dirblock = (path.split(b'/'), [])
 
298
        split_dirblock = (path.split('/'), [])
298
299
        bisect_left_idx = bisect.bisect_left(split_dirblocks, split_dirblock,
299
300
                                             *args)
300
301
        self.assertEqual(bisect_left_idx, bisect_split_idx,
309
310
        Also, ensure that the paths are in proper sorted order.
310
311
        """
311
312
        dirblocks = [(path, []) for path in paths]
312
 
        split_dirblocks = [(path.split(b'/'), []) for path in paths]
 
313
        split_dirblocks = [(path.split('/'), []) for path in paths]
313
314
        self.assertEqual(sorted(split_dirblocks), split_dirblocks)
314
315
        return dirblocks, split_dirblocks
315
316
 
316
317
    def test_simple(self):
317
318
        """In the simple case it works just like bisect_left"""
318
 
        paths = [b'', b'a', b'b', b'c', b'd']
 
319
        paths = ['', 'a', 'b', 'c', 'd']
319
320
        dirblocks, split_dirblocks = self.paths_to_dirblocks(paths)
320
321
        for path in paths:
321
322
            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')
 
323
        self.assertBisect(dirblocks, split_dirblocks, '_')
 
324
        self.assertBisect(dirblocks, split_dirblocks, 'aa')
 
325
        self.assertBisect(dirblocks, split_dirblocks, 'bb')
 
326
        self.assertBisect(dirblocks, split_dirblocks, 'cc')
 
327
        self.assertBisect(dirblocks, split_dirblocks, 'dd')
 
328
        self.assertBisect(dirblocks, split_dirblocks, 'a/a')
 
329
        self.assertBisect(dirblocks, split_dirblocks, 'b/b')
 
330
        self.assertBisect(dirblocks, split_dirblocks, 'c/c')
 
331
        self.assertBisect(dirblocks, split_dirblocks, 'd/d')
331
332
 
332
333
    def test_involved(self):
333
334
        """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
 
                 ]
 
335
        paths = ['', 'a',
 
336
                 'a/a', 'a/a/a', 'a/a/z', 'a/a-a', 'a/a-z',
 
337
                 'a/z', 'a/z/a', 'a/z/z', 'a/z-a', 'a/z-z',
 
338
                 'a-a', 'a-z',
 
339
                 'z', 'z/a/a', 'z/a/z', 'z/a-a', 'z/a-z',
 
340
                 'z/z', 'z/z/a', 'z/z/z', 'z/z-a', 'z/z-z',
 
341
                 'z-a', 'z-z',
 
342
                ]
342
343
        dirblocks, split_dirblocks = self.paths_to_dirblocks(paths)
343
344
        for path in paths:
344
345
            self.assertBisect(dirblocks, split_dirblocks, path)
345
346
 
346
347
    def test_involved_cached(self):
347
348
        """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
 
                 ]
 
349
        paths = ['', 'a',
 
350
                 'a/a', 'a/a/a', 'a/a/z', 'a/a-a', 'a/a-z',
 
351
                 'a/z', 'a/z/a', 'a/z/z', 'a/z-a', 'a/z-z',
 
352
                 'a-a', 'a-z',
 
353
                 'z', 'z/a/a', 'z/a/z', 'z/a-a', 'z/a-z',
 
354
                 'z/z', 'z/z/a', 'z/z/z', 'z/z-a', 'z/z-z',
 
355
                 'z-a', 'z-z',
 
356
                ]
356
357
        cache = {}
357
358
        dirblocks, split_dirblocks = self.paths_to_dirblocks(paths)
358
359
        for path in paths:
373
374
    _test_needs_features = [compiled_dirstate_helpers_feature]
374
375
 
375
376
    def get_bisect_dirblock(self):
376
 
        from .._dirstate_helpers_pyx import bisect_dirblock
 
377
        from breezy._dirstate_helpers_pyx import bisect_dirblock
377
378
        return bisect_dirblock
378
379
 
379
380
 
380
 
class TestLtByDirs(tests.TestCase):
381
 
    """Test an implementation of lt_by_dirs()
 
381
class TestCmpByDirs(tests.TestCase):
 
382
    """Test an implementation of cmp_by_dirs()
382
383
 
383
 
    lt_by_dirs() compares 2 paths by their directory sections, rather than as
 
384
    cmp_by_dirs() compares 2 paths by their directory sections, rather than as
384
385
    plain strings.
385
386
 
386
 
    Child test cases can override ``get_lt_by_dirs`` to test a specific
 
387
    Child test cases can override ``get_cmp_by_dirs`` to test a specific
387
388
    implementation.
388
389
    """
389
390
 
390
 
    def get_lt_by_dirs(self):
391
 
        """Get a specific implementation of lt_by_dirs."""
392
 
        from .._dirstate_helpers_py import lt_by_dirs
393
 
        return lt_by_dirs
 
391
    def get_cmp_by_dirs(self):
 
392
        """Get a specific implementation of cmp_by_dirs."""
 
393
        from breezy._dirstate_helpers_py import cmp_by_dirs
 
394
        return cmp_by_dirs
394
395
 
395
396
    def assertCmpByDirs(self, expected, str1, str2):
396
397
        """Compare the two strings, in both directions.
400
401
        :param str1: string to compare
401
402
        :param str2: string to compare
402
403
        """
403
 
        lt_by_dirs = self.get_lt_by_dirs()
 
404
        cmp_by_dirs = self.get_cmp_by_dirs()
404
405
        if expected == 0:
405
406
            self.assertEqual(str1, str2)
406
 
            self.assertFalse(lt_by_dirs(str1, str2))
407
 
            self.assertFalse(lt_by_dirs(str2, str1))
 
407
            self.assertEqual(0, cmp_by_dirs(str1, str2))
 
408
            self.assertEqual(0, cmp_by_dirs(str2, str1))
408
409
        elif expected > 0:
409
 
            self.assertFalse(lt_by_dirs(str1, str2))
410
 
            self.assertTrue(lt_by_dirs(str2, str1))
 
410
            self.assertPositive(cmp_by_dirs(str1, str2))
 
411
            self.assertNegative(cmp_by_dirs(str2, str1))
411
412
        else:
412
 
            self.assertTrue(lt_by_dirs(str1, str2))
413
 
            self.assertFalse(lt_by_dirs(str2, str1))
 
413
            self.assertNegative(cmp_by_dirs(str1, str2))
 
414
            self.assertPositive(cmp_by_dirs(str2, str1))
414
415
 
415
416
    def test_cmp_empty(self):
416
417
        """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'')
 
418
        self.assertCmpByDirs(0, '', '')
 
419
        self.assertCmpByDirs(1, 'a', '')
 
420
        self.assertCmpByDirs(1, 'ab', '')
 
421
        self.assertCmpByDirs(1, 'abc', '')
 
422
        self.assertCmpByDirs(1, 'abcd', '')
 
423
        self.assertCmpByDirs(1, 'abcde', '')
 
424
        self.assertCmpByDirs(1, 'abcdef', '')
 
425
        self.assertCmpByDirs(1, 'abcdefg', '')
 
426
        self.assertCmpByDirs(1, 'abcdefgh', '')
 
427
        self.assertCmpByDirs(1, 'abcdefghi', '')
 
428
        self.assertCmpByDirs(1, 'test/ing/a/path/', '')
428
429
 
429
430
    def test_cmp_same_str(self):
430
431
        """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')
 
432
        self.assertCmpByDirs(0, 'a', 'a')
 
433
        self.assertCmpByDirs(0, 'ab', 'ab')
 
434
        self.assertCmpByDirs(0, 'abc', 'abc')
 
435
        self.assertCmpByDirs(0, 'abcd', 'abcd')
 
436
        self.assertCmpByDirs(0, 'abcde', 'abcde')
 
437
        self.assertCmpByDirs(0, 'abcdef', 'abcdef')
 
438
        self.assertCmpByDirs(0, 'abcdefg', 'abcdefg')
 
439
        self.assertCmpByDirs(0, 'abcdefgh', 'abcdefgh')
 
440
        self.assertCmpByDirs(0, 'abcdefghi', 'abcdefghi')
 
441
        self.assertCmpByDirs(0, 'testing a long string', 'testing a long string')
 
442
        self.assertCmpByDirs(0, 'x'*10000, 'x'*10000)
 
443
        self.assertCmpByDirs(0, 'a/b', 'a/b')
 
444
        self.assertCmpByDirs(0, 'a/b/c', 'a/b/c')
 
445
        self.assertCmpByDirs(0, 'a/b/c/d', 'a/b/c/d')
 
446
        self.assertCmpByDirs(0, 'a/b/c/d/e', 'a/b/c/d/e')
447
447
 
448
448
    def test_simple_paths(self):
449
449
        """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')
 
450
        self.assertCmpByDirs(-1, 'a', 'b')
 
451
        self.assertCmpByDirs(-1, 'aa', 'ab')
 
452
        self.assertCmpByDirs(-1, 'ab', 'bb')
 
453
        self.assertCmpByDirs(-1, 'aaa', 'aab')
 
454
        self.assertCmpByDirs(-1, 'aab', 'abb')
 
455
        self.assertCmpByDirs(-1, 'abb', 'bbb')
 
456
        self.assertCmpByDirs(-1, 'aaaa', 'aaab')
 
457
        self.assertCmpByDirs(-1, 'aaab', 'aabb')
 
458
        self.assertCmpByDirs(-1, 'aabb', 'abbb')
 
459
        self.assertCmpByDirs(-1, 'abbb', 'bbbb')
 
460
        self.assertCmpByDirs(-1, 'aaaaa', 'aaaab')
 
461
        self.assertCmpByDirs(-1, 'a/a', 'a/b')
 
462
        self.assertCmpByDirs(-1, 'a/b', 'b/b')
 
463
        self.assertCmpByDirs(-1, 'a/a/a', 'a/a/b')
 
464
        self.assertCmpByDirs(-1, 'a/a/b', 'a/b/b')
 
465
        self.assertCmpByDirs(-1, 'a/b/b', 'b/b/b')
 
466
        self.assertCmpByDirs(-1, 'a/a/a/a', 'a/a/a/b')
 
467
        self.assertCmpByDirs(-1, 'a/a/a/b', 'a/a/b/b')
 
468
        self.assertCmpByDirs(-1, 'a/a/b/b', 'a/b/b/b')
 
469
        self.assertCmpByDirs(-1, 'a/b/b/b', 'b/b/b/b')
 
470
        self.assertCmpByDirs(-1, 'a/a/a/a/a', 'a/a/a/a/b')
471
471
 
472
472
    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')
 
473
        self.assertCmpByDirs(1, 'ab/cd/ef', 'ab/cc/ef')
 
474
        self.assertCmpByDirs(1, 'ab/cd/ef', 'ab/c/ef')
 
475
        self.assertCmpByDirs(-1, 'ab/cd/ef', 'ab/cd-ef')
 
476
        self.assertCmpByDirs(-1, 'ab/cd', 'ab/cd-')
 
477
        self.assertCmpByDirs(-1, 'ab/cd', 'ab-cd')
478
478
 
479
479
    def test_cmp_unicode_not_allowed(self):
480
 
        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')
483
 
        self.assertRaises(TypeError, lt_by_dirs, u'Unicode', u'Unicode')
 
480
        cmp_by_dirs = self.get_cmp_by_dirs()
 
481
        self.assertRaises(TypeError, cmp_by_dirs, u'Unicode', 'str')
 
482
        self.assertRaises(TypeError, cmp_by_dirs, 'str', u'Unicode')
 
483
        self.assertRaises(TypeError, cmp_by_dirs, u'Unicode', u'Unicode')
484
484
 
485
485
    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'
491
 
 
492
 
 
493
 
class TestCompiledLtByDirs(TestLtByDirs):
494
 
    """Test the pyrex implementation of lt_by_dirs"""
 
486
        self.assertCmpByDirs(-1, '\xc2\xb5', '\xc3\xa5') # u'\xb5', u'\xe5'
 
487
        self.assertCmpByDirs(-1, 'a', '\xc3\xa5') # u'a', u'\xe5'
 
488
        self.assertCmpByDirs(-1, 'b', '\xc2\xb5') # u'b', u'\xb5'
 
489
        self.assertCmpByDirs(-1, 'a/b', 'a/\xc3\xa5') # u'a/b', u'a/\xe5'
 
490
        self.assertCmpByDirs(-1, 'b/a', 'b/\xc2\xb5') # u'b/a', u'b/\xb5'
 
491
 
 
492
 
 
493
class TestCompiledCmpByDirs(TestCmpByDirs):
 
494
    """Test the pyrex implementation of cmp_by_dirs"""
495
495
 
496
496
    _test_needs_features = [compiled_dirstate_helpers_feature]
497
497
 
498
 
    def get_lt_by_dirs(self):
499
 
        from .._dirstate_helpers_pyx import lt_by_dirs
500
 
        return lt_by_dirs
501
 
 
502
 
 
503
 
class TestLtPathByDirblock(tests.TestCase):
504
 
    """Test an implementation of _lt_path_by_dirblock()
505
 
 
506
 
    _lt_path_by_dirblock() compares two paths using the sort order used by
 
498
    def get_cmp_by_dirs(self):
 
499
        from breezy._dirstate_helpers_pyx import cmp_by_dirs
 
500
        return cmp_by_dirs
 
501
 
 
502
 
 
503
class TestCmpPathByDirblock(tests.TestCase):
 
504
    """Test an implementation of _cmp_path_by_dirblock()
 
505
 
 
506
    _cmp_path_by_dirblock() compares two paths using the sort order used by
507
507
    DirState. All paths in the same directory are sorted together.
508
508
 
509
 
    Child test cases can override ``get_lt_path_by_dirblock`` to test a specific
 
509
    Child test cases can override ``get_cmp_path_by_dirblock`` to test a specific
510
510
    implementation.
511
511
    """
512
512
 
513
 
    def get_lt_path_by_dirblock(self):
514
 
        """Get a specific implementation of _lt_path_by_dirblock."""
515
 
        from .._dirstate_helpers_py import _lt_path_by_dirblock
516
 
        return _lt_path_by_dirblock
 
513
    def get_cmp_path_by_dirblock(self):
 
514
        """Get a specific implementation of _cmp_path_by_dirblock."""
 
515
        from breezy._dirstate_helpers_py import _cmp_path_by_dirblock
 
516
        return _cmp_path_by_dirblock
517
517
 
518
 
    def assertLtPathByDirblock(self, paths):
 
518
    def assertCmpPathByDirblock(self, paths):
519
519
        """Compare all paths and make sure they evaluate to the correct order.
520
520
 
521
521
        This does N^2 comparisons. It is assumed that ``paths`` is properly
526
526
        # First, make sure the paths being passed in are correct
527
527
        def _key(p):
528
528
            dirname, basename = os.path.split(p)
529
 
            return dirname.split(b'/'), basename
 
529
            return dirname.split('/'), basename
530
530
        self.assertEqual(sorted(paths, key=_key), paths)
531
531
 
532
 
        lt_path_by_dirblock = self.get_lt_path_by_dirblock()
 
532
        cmp_path_by_dirblock = self.get_cmp_path_by_dirblock()
533
533
        for idx1, path1 in enumerate(paths):
534
534
            for idx2, path2 in enumerate(paths):
535
 
                lt_result = lt_path_by_dirblock(path1, path2)
536
 
                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))
 
535
                cmp_val = cmp_path_by_dirblock(path1, path2)
 
536
                if idx1 < idx2:
 
537
                    self.assertTrue(cmp_val < 0,
 
538
                        '%s did not state that %r came before %r, cmp=%s'
 
539
                        % (cmp_path_by_dirblock.__name__,
 
540
                           path1, path2, cmp_val))
 
541
                elif idx1 > idx2:
 
542
                    self.assertTrue(cmp_val > 0,
 
543
                        '%s did not state that %r came after %r, cmp=%s'
 
544
                        % (cmp_path_by_dirblock.__name__,
 
545
                           path1, path2, cmp_val))
 
546
                else: # idx1 == idx2
 
547
                    self.assertTrue(cmp_val == 0,
 
548
                        '%s did not state that %r == %r, cmp=%s'
 
549
                        % (cmp_path_by_dirblock.__name__,
 
550
                           path1, path2, cmp_val))
540
551
 
541
552
    def test_cmp_simple_paths(self):
542
553
        """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'])
 
554
        self.assertCmpPathByDirblock(['', 'a', 'ab', 'abc', 'a/b/c', 'b/d/e'])
 
555
        self.assertCmpPathByDirblock(['kl', 'ab/cd', 'ab/ef', 'gh/ij'])
546
556
 
547
557
    def test_tricky_paths(self):
548
 
        self.assertLtPathByDirblock([
 
558
        self.assertCmpPathByDirblock([
549
559
            # Contents of ''
550
 
            b'', b'a', b'a-a', b'a=a', b'b',
 
560
            '', 'a', 'a-a', 'a=a', 'b',
551
561
            # Contents of 'a'
552
 
            b'a/a', b'a/a-a', b'a/a=a', b'a/b',
 
562
            'a/a', 'a/a-a', 'a/a=a', 'a/b',
553
563
            # Contents of 'a/a'
554
 
            b'a/a/a', b'a/a/a-a', b'a/a/a=a',
 
564
            'a/a/a', 'a/a/a-a', 'a/a/a=a',
555
565
            # Contents of 'a/a/a'
556
 
            b'a/a/a/a', b'a/a/a/b',
 
566
            'a/a/a/a', 'a/a/a/b',
557
567
            # Contents of 'a/a/a-a',
558
 
            b'a/a/a-a/a', b'a/a/a-a/b',
 
568
            'a/a/a-a/a', 'a/a/a-a/b',
559
569
            # Contents of 'a/a/a=a',
560
 
            b'a/a/a=a/a', b'a/a/a=a/b',
 
570
            'a/a/a=a/a', 'a/a/a=a/b',
561
571
            # Contents of 'a/a-a'
562
 
            b'a/a-a/a',
 
572
            'a/a-a/a',
563
573
            # Contents of 'a/a-a/a'
564
 
            b'a/a-a/a/a', b'a/a-a/a/b',
 
574
            'a/a-a/a/a', 'a/a-a/a/b',
565
575
            # Contents of 'a/a=a'
566
 
            b'a/a=a/a',
 
576
            'a/a=a/a',
567
577
            # Contents of 'a/b'
568
 
            b'a/b/a', b'a/b/b',
 
578
            'a/b/a', 'a/b/b',
569
579
            # Contents of 'a-a',
570
 
            b'a-a/a', b'a-a/b',
 
580
            'a-a/a', 'a-a/b',
571
581
            # Contents of 'a=a',
572
 
            b'a=a/a', b'a=a/b',
 
582
            'a=a/a', 'a=a/b',
573
583
            # Contents of 'b',
574
 
            b'b/a', b'b/b',
 
584
            'b/a', 'b/b',
575
585
            ])
576
 
        self.assertLtPathByDirblock([
577
 
            # content of '/'
578
 
            b'', b'a', b'a-a', b'a-z', b'a=a', b'a=z',
 
586
        self.assertCmpPathByDirblock([
 
587
                 # content of '/'
 
588
                 '', 'a', 'a-a', 'a-z', 'a=a', 'a=z',
579
589
                 # 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',
 
590
                 'a/a', 'a/a-a', 'a/a-z',
 
591
                 'a/a=a', 'a/a=z',
 
592
                 'a/z', 'a/z-a', 'a/z-z',
 
593
                 'a/z=a', 'a/z=z',
584
594
                 # content of 'a/a/'
585
 
                 b'a/a/a', b'a/a/z',
 
595
                 'a/a/a', 'a/a/z',
586
596
                 # content of 'a/a-a'
587
 
                 b'a/a-a/a',
 
597
                 'a/a-a/a',
588
598
                 # content of 'a/a-z'
589
 
                 b'a/a-z/z',
 
599
                 'a/a-z/z',
590
600
                 # content of 'a/a=a'
591
 
                 b'a/a=a/a',
 
601
                 'a/a=a/a',
592
602
                 # content of 'a/a=z'
593
 
                 b'a/a=z/z',
 
603
                 'a/a=z/z',
594
604
                 # content of 'a/z/'
595
 
                 b'a/z/a', b'a/z/z',
 
605
                 'a/z/a', 'a/z/z',
596
606
                 # content of 'a-a'
597
 
                 b'a-a/a',
 
607
                 'a-a/a',
598
608
                 # content of 'a-z'
599
 
                 b'a-z/z',
 
609
                 'a-z/z',
600
610
                 # content of 'a=a'
601
 
                 b'a=a/a',
 
611
                 'a=a/a',
602
612
                 # content of 'a=z'
603
 
                 b'a=z/z',
604
 
            ])
 
613
                 'a=z/z',
 
614
                ])
605
615
 
606
616
    def test_unicode_not_allowed(self):
607
 
        lt_path_by_dirblock = self.get_lt_path_by_dirblock()
608
 
        self.assertRaises(TypeError, lt_path_by_dirblock, u'Uni', 'str')
609
 
        self.assertRaises(TypeError, lt_path_by_dirblock, 'str', u'Uni')
610
 
        self.assertRaises(TypeError, lt_path_by_dirblock, u'Uni', u'Uni')
611
 
        self.assertRaises(TypeError, lt_path_by_dirblock, u'x/Uni', 'x/str')
612
 
        self.assertRaises(TypeError, lt_path_by_dirblock, 'x/str', u'x/Uni')
613
 
        self.assertRaises(TypeError, lt_path_by_dirblock, u'x/Uni', u'x/Uni')
 
617
        cmp_path_by_dirblock = self.get_cmp_path_by_dirblock()
 
618
        self.assertRaises(TypeError, cmp_path_by_dirblock, u'Uni', 'str')
 
619
        self.assertRaises(TypeError, cmp_path_by_dirblock, 'str', u'Uni')
 
620
        self.assertRaises(TypeError, cmp_path_by_dirblock, u'Uni', u'Uni')
 
621
        self.assertRaises(TypeError, cmp_path_by_dirblock, u'x/Uni', 'x/str')
 
622
        self.assertRaises(TypeError, cmp_path_by_dirblock, 'x/str', u'x/Uni')
 
623
        self.assertRaises(TypeError, cmp_path_by_dirblock, u'x/Uni', u'x/Uni')
614
624
 
615
625
    def test_nonascii(self):
616
 
        self.assertLtPathByDirblock([
 
626
        self.assertCmpPathByDirblock([
617
627
            # content of '/'
618
 
            b'', b'a', b'\xc2\xb5', b'\xc3\xa5',
 
628
            '', 'a', '\xc2\xb5', '\xc3\xa5',
619
629
            # content of 'a'
620
 
            b'a/a', b'a/\xc2\xb5', b'a/\xc3\xa5',
 
630
            'a/a', 'a/\xc2\xb5', 'a/\xc3\xa5',
621
631
            # content of 'a/a'
622
 
            b'a/a/a', b'a/a/\xc2\xb5', b'a/a/\xc3\xa5',
 
632
            'a/a/a', 'a/a/\xc2\xb5', 'a/a/\xc3\xa5',
623
633
            # content of 'a/\xc2\xb5'
624
 
            b'a/\xc2\xb5/a', b'a/\xc2\xb5/\xc2\xb5', b'a/\xc2\xb5/\xc3\xa5',
 
634
            'a/\xc2\xb5/a', 'a/\xc2\xb5/\xc2\xb5', 'a/\xc2\xb5/\xc3\xa5',
625
635
            # content of 'a/\xc3\xa5'
626
 
            b'a/\xc3\xa5/a', b'a/\xc3\xa5/\xc2\xb5', b'a/\xc3\xa5/\xc3\xa5',
 
636
            'a/\xc3\xa5/a', 'a/\xc3\xa5/\xc2\xb5', 'a/\xc3\xa5/\xc3\xa5',
627
637
            # content of '\xc2\xb5'
628
 
            b'\xc2\xb5/a', b'\xc2\xb5/\xc2\xb5', b'\xc2\xb5/\xc3\xa5',
 
638
            '\xc2\xb5/a', '\xc2\xb5/\xc2\xb5', '\xc2\xb5/\xc3\xa5',
629
639
            # content of '\xc2\xe5'
630
 
            b'\xc3\xa5/a', b'\xc3\xa5/\xc2\xb5', b'\xc3\xa5/\xc3\xa5',
 
640
            '\xc3\xa5/a', '\xc3\xa5/\xc2\xb5', '\xc3\xa5/\xc3\xa5',
631
641
            ])
632
642
 
633
643
 
634
 
class TestCompiledLtPathByDirblock(TestLtPathByDirblock):
635
 
    """Test the pyrex implementation of _lt_path_by_dirblock"""
 
644
class TestCompiledCmpPathByDirblock(TestCmpPathByDirblock):
 
645
    """Test the pyrex implementation of _cmp_path_by_dirblock"""
636
646
 
637
647
    _test_needs_features = [compiled_dirstate_helpers_feature]
638
648
 
639
 
    def get_lt_path_by_dirblock(self):
640
 
        from .._dirstate_helpers_pyx import _lt_path_by_dirblock
641
 
        return _lt_path_by_dirblock
 
649
    def get_cmp_by_dirs(self):
 
650
        from breezy._dirstate_helpers_pyx import _cmp_path_by_dirblock
 
651
        return _cmp_path_by_dirblock
642
652
 
643
653
 
644
654
class TestMemRChr(tests.TestCase):
647
657
    _test_needs_features = [compiled_dirstate_helpers_feature]
648
658
 
649
659
    def assertMemRChr(self, expected, s, c):
650
 
        from .._dirstate_helpers_pyx import _py_memrchr
 
660
        from breezy._dirstate_helpers_pyx import _py_memrchr
651
661
        self.assertEqual(expected, _py_memrchr(s, c))
652
662
 
653
663
    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')
 
664
        self.assertMemRChr(None, '', 'a')
 
665
        self.assertMemRChr(None, '', 'c')
 
666
        self.assertMemRChr(None, 'abcdefghijklm', 'q')
 
667
        self.assertMemRChr(None, 'aaaaaaaaaaaaaaaaaaaaaaa', 'b')
658
668
 
659
669
    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')
 
670
        self.assertMemRChr(0, 'abcdefghijklm', 'a')
 
671
        self.assertMemRChr(1, 'abcdefghijklm', 'b')
 
672
        self.assertMemRChr(2, 'abcdefghijklm', 'c')
 
673
        self.assertMemRChr(10, 'abcdefghijklm', 'k')
 
674
        self.assertMemRChr(11, 'abcdefghijklm', 'l')
 
675
        self.assertMemRChr(12, 'abcdefghijklm', 'm')
666
676
 
667
677
    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')
 
678
        self.assertMemRChr(10, 'abcdefjklmabcdefghijklm', 'a')
 
679
        self.assertMemRChr(11, 'abcdefjklmabcdefghijklm', 'b')
 
680
        self.assertMemRChr(12, 'abcdefjklmabcdefghijklm', 'c')
 
681
        self.assertMemRChr(20, 'abcdefjklmabcdefghijklm', 'k')
 
682
        self.assertMemRChr(21, 'abcdefjklmabcdefghijklm', 'l')
 
683
        self.assertMemRChr(22, 'abcdefjklmabcdefghijklm', 'm')
 
684
        self.assertMemRChr(22, 'aaaaaaaaaaaaaaaaaaaaaaa', 'a')
675
685
 
676
686
    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')
 
687
        self.assertMemRChr(10, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'a')
 
688
        self.assertMemRChr(11, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'b')
 
689
        self.assertMemRChr(12, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'c')
 
690
        self.assertMemRChr(20, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'k')
 
691
        self.assertMemRChr(21, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'l')
 
692
        self.assertMemRChr(22, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'm')
 
693
        self.assertMemRChr(22, 'aaa\0\0\0aaaaaaa\0\0\0aaaaaaa', 'a')
 
694
        self.assertMemRChr(9, '\0\0\0\0\0\0\0\0\0\0', '\0')
685
695
 
686
696
 
687
697
class TestReadDirblocks(test_dirstate.TestCaseWithDirState):
697
707
    # inherits scenarios from test_dirstate
698
708
 
699
709
    def get_read_dirblocks(self):
700
 
        from .._dirstate_helpers_py import _read_dirblocks
 
710
        from breezy._dirstate_helpers_py import _read_dirblocks
701
711
        return _read_dirblocks
702
712
 
703
713
    def test_smoketest(self):
721
731
        f = open('dirstate', 'ab')
722
732
        try:
723
733
            # Add bogus trailing garbage
724
 
            f.write(b'bogus\n')
 
734
            f.write('bogus\n')
725
735
        finally:
726
736
            f.close()
727
737
            state.lock_read()
728
 
        e = self.assertRaises(dirstate.DirstateCorrupt,
 
738
        e = self.assertRaises(errors.DirstateCorrupt,
729
739
                              state._read_dirblocks_if_needed)
730
740
        # Make sure we mention the bogus characters in the error
731
741
        self.assertContainsRe(str(e), 'bogus')
737
747
    _test_needs_features = [compiled_dirstate_helpers_feature]
738
748
 
739
749
    def get_read_dirblocks(self):
740
 
        from .._dirstate_helpers_pyx import _read_dirblocks
 
750
        from breezy._dirstate_helpers_pyx import _read_dirblocks
741
751
        return _read_dirblocks
742
752
 
743
753
 
751
761
 
752
762
    def test_bisect_dirblock(self):
753
763
        if compiled_dirstate_helpers_feature.available():
754
 
            from .._dirstate_helpers_pyx import bisect_dirblock
 
764
            from breezy._dirstate_helpers_pyx import bisect_dirblock
755
765
        else:
756
 
            from .._dirstate_helpers_py import bisect_dirblock
 
766
            from breezy._dirstate_helpers_py import bisect_dirblock
757
767
        self.assertIs(bisect_dirblock, dirstate.bisect_dirblock)
758
768
 
759
769
    def test__bisect_path_left(self):
760
770
        if compiled_dirstate_helpers_feature.available():
761
 
            from .._dirstate_helpers_pyx import _bisect_path_left
 
771
            from breezy._dirstate_helpers_pyx import _bisect_path_left
762
772
        else:
763
 
            from .._dirstate_helpers_py import _bisect_path_left
 
773
            from breezy._dirstate_helpers_py import _bisect_path_left
764
774
        self.assertIs(_bisect_path_left, dirstate._bisect_path_left)
765
775
 
766
776
    def test__bisect_path_right(self):
767
777
        if compiled_dirstate_helpers_feature.available():
768
 
            from .._dirstate_helpers_pyx import _bisect_path_right
 
778
            from breezy._dirstate_helpers_pyx import _bisect_path_right
769
779
        else:
770
 
            from .._dirstate_helpers_py import _bisect_path_right
 
780
            from breezy._dirstate_helpers_py import _bisect_path_right
771
781
        self.assertIs(_bisect_path_right, dirstate._bisect_path_right)
772
782
 
773
 
    def test_lt_by_dirs(self):
 
783
    def test_cmp_by_dirs(self):
774
784
        if compiled_dirstate_helpers_feature.available():
775
 
            from .._dirstate_helpers_pyx import lt_by_dirs
 
785
            from breezy._dirstate_helpers_pyx import cmp_by_dirs
776
786
        else:
777
 
            from .._dirstate_helpers_py import lt_by_dirs
778
 
        self.assertIs(lt_by_dirs, dirstate.lt_by_dirs)
 
787
            from breezy._dirstate_helpers_py import cmp_by_dirs
 
788
        self.assertIs(cmp_by_dirs, dirstate.cmp_by_dirs)
779
789
 
780
790
    def test__read_dirblocks(self):
781
791
        if compiled_dirstate_helpers_feature.available():
782
 
            from .._dirstate_helpers_pyx import _read_dirblocks
 
792
            from breezy._dirstate_helpers_pyx import _read_dirblocks
783
793
        else:
784
 
            from .._dirstate_helpers_py import _read_dirblocks
 
794
            from breezy._dirstate_helpers_py import _read_dirblocks
785
795
        self.assertIs(_read_dirblocks, dirstate._read_dirblocks)
786
796
 
787
797
    def test_update_entry(self):
788
798
        if compiled_dirstate_helpers_feature.available():
789
 
            from .._dirstate_helpers_pyx import update_entry
 
799
            from breezy._dirstate_helpers_pyx import update_entry
790
800
        else:
791
 
            from ..dirstate import update_entry
 
801
            from breezy.dirstate import update_entry
792
802
        self.assertIs(update_entry, dirstate.update_entry)
793
803
 
794
804
    def test_process_entry(self):
795
805
        if compiled_dirstate_helpers_feature.available():
796
 
            from .._dirstate_helpers_pyx import ProcessEntryC
 
806
            from breezy._dirstate_helpers_pyx import ProcessEntryC
797
807
            self.assertIs(ProcessEntryC, dirstate._process_entry)
798
808
        else:
799
 
            from ..dirstate import ProcessEntryPython
 
809
            from breezy.dirstate import ProcessEntryPython
800
810
            self.assertIs(ProcessEntryPython, dirstate._process_entry)
801
811
 
802
812
 
817
827
        """Create a DirState tracking a single object named 'a'"""
818
828
        state = test_dirstate.InstrumentedDirState.initialize('dirstate')
819
829
        self.addCleanup(state.unlock)
820
 
        state.add('a', b'a-id', 'file', None, b'')
821
 
        entry = state._get_entry(0, path_utf8=b'a')
 
830
        state.add('a', 'a-id', 'file', None, '')
 
831
        entry = state._get_entry(0, path_utf8='a')
822
832
        return state, entry
823
833
 
824
834
    def test_observed_sha1_cachable(self):
830
840
        statvalue.st_mtime = statvalue.st_ctime = atime
831
841
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
832
842
                         state._dirblock_state)
833
 
        state._observed_sha1(entry, b"foo", statvalue)
834
 
        self.assertEqual(b'foo', entry[1][0][1])
 
843
        state._observed_sha1(entry, "foo", statvalue)
 
844
        self.assertEqual('foo', entry[1][0][1])
835
845
        packed_stat = dirstate.pack_stat(statvalue)
836
846
        self.assertEqual(packed_stat, entry[1][0][4])
837
847
        self.assertEqual(dirstate.DirState.IN_MEMORY_HASH_MODIFIED,
858
868
        tree.lock_write()
859
869
        empty_revid = tree.commit('empty')
860
870
        self.build_tree(['tree/a'])
861
 
        tree.add(['a'], [b'a-id'])
 
871
        tree.add(['a'], ['a-id'])
862
872
        with_a_id = tree.commit('with_a')
863
873
        self.addCleanup(tree.unlock)
864
874
        state.set_parent_trees(
865
875
            [(empty_revid, tree.branch.repository.revision_tree(empty_revid))],
866
876
            [])
867
 
        entry = state._get_entry(0, path_utf8=b'a')
 
877
        entry = state._get_entry(0, path_utf8='a')
868
878
        self.build_tree(['a'])
869
879
        # 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),
 
880
        self.assertEqual(('', 'a', 'a-id'), entry[0])
 
881
        self.assertEqual(('f', '', 0, False, dirstate.DirState.NULLSTAT),
872
882
                         entry[1][0])
873
883
        # Flush the buffers to disk
874
884
        state.save()
877
887
 
878
888
        stat_value = os.lstat('a')
879
889
        packed_stat = dirstate.pack_stat(stat_value)
880
 
        link_or_sha1 = self.update_entry(state, entry, abspath=b'a',
881
 
                                         stat_value=stat_value)
 
890
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
 
891
                                          stat_value=stat_value)
882
892
        self.assertEqual(None, link_or_sha1)
883
893
 
884
894
        # The dirblock entry should not have computed or cached the file's
885
895
        # sha1, but it did update the files' st_size. However, this is not
886
896
        # worth writing a dirstate file for, so we leave the state UNMODIFIED
887
 
        self.assertEqual((b'f', b'', 14, False, dirstate.DirState.NULLSTAT),
 
897
        self.assertEqual(('f', '', 14, False, dirstate.DirState.NULLSTAT),
888
898
                         entry[1][0])
889
899
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
890
900
                         state._dirblock_state)
900
910
        state.adjust_time(-10)
901
911
        del state._log[:]
902
912
 
903
 
        link_or_sha1 = self.update_entry(state, entry, abspath=b'a',
904
 
                                         stat_value=stat_value)
 
913
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
 
914
                                          stat_value=stat_value)
905
915
        self.assertEqual([('is_exec', mode, False)], state._log)
906
916
        self.assertEqual(None, link_or_sha1)
907
917
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
908
918
                         state._dirblock_state)
909
 
        self.assertEqual((b'f', b'', 14, False, dirstate.DirState.NULLSTAT),
 
919
        self.assertEqual(('f', '', 14, False, dirstate.DirState.NULLSTAT),
910
920
                         entry[1][0])
911
921
        state.save()
912
922
 
914
924
        # won't calculate the sha or cache it.
915
925
        state.adjust_time(+20)
916
926
        del state._log[:]
917
 
        link_or_sha1 = dirstate.update_entry(state, entry, abspath=b'a',
918
 
                                             stat_value=stat_value)
 
927
        link_or_sha1 = dirstate.update_entry(state, entry, abspath='a',
 
928
                                          stat_value=stat_value)
919
929
        self.assertEqual(None, link_or_sha1)
920
930
        self.assertEqual([('is_exec', mode, False)], state._log)
921
 
        self.assertEqual((b'f', b'', 14, False, dirstate.DirState.NULLSTAT),
 
931
        self.assertEqual(('f', '', 14, False, dirstate.DirState.NULLSTAT),
922
932
                         entry[1][0])
923
933
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
924
934
                         state._dirblock_state)
929
939
        state.set_parent_trees(
930
940
            [(with_a_id, tree.branch.repository.revision_tree(with_a_id))],
931
941
            [])
932
 
        entry = state._get_entry(0, path_utf8=b'a')
 
942
        entry = state._get_entry(0, path_utf8='a')
933
943
 
934
 
        link_or_sha1 = self.update_entry(state, entry, abspath=b'a',
935
 
                                         stat_value=stat_value)
936
 
        self.assertEqual(b'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
 
944
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
 
945
                                          stat_value=stat_value)
 
946
        self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
937
947
                         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),
 
948
        self.assertEqual([('is_exec', mode, False), ('sha1', 'a')],
 
949
                          state._log)
 
950
        self.assertEqual(('f', link_or_sha1, 14, False, packed_stat),
941
951
                         entry[1][0])
942
952
 
943
953
        # Subsequent calls will just return the cached value
944
954
        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',
 
955
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
 
956
                                          stat_value=stat_value)
 
957
        self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
948
958
                         link_or_sha1)
949
959
        self.assertEqual([], state._log)
950
 
        self.assertEqual((b'f', link_or_sha1, 14, False, packed_stat),
 
960
        self.assertEqual(('f', link_or_sha1, 14, False, packed_stat),
951
961
                         entry[1][0])
952
962
 
953
963
    def test_update_entry_symlink(self):
959
969
                         state._dirblock_state)
960
970
        os.symlink('target', 'a')
961
971
 
962
 
        state.adjust_time(-10)  # Make the symlink look new
 
972
        state.adjust_time(-10) # Make the symlink look new
963
973
        stat_value = os.lstat('a')
964
974
        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)
 
975
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
 
976
                                          stat_value=stat_value)
 
977
        self.assertEqual('target', link_or_sha1)
 
978
        self.assertEqual([('read_link', 'a', '')], state._log)
969
979
        # Dirblock is not updated (the link is too new)
970
 
        self.assertEqual([(b'l', b'', 6, False, dirstate.DirState.NULLSTAT)],
 
980
        self.assertEqual([('l', '', 6, False, dirstate.DirState.NULLSTAT)],
971
981
                         entry[1])
972
982
        # The file entry turned into a symlink, that is considered
973
983
        # HASH modified worthy.
976
986
 
977
987
        # Because the stat_value looks new, we should re-read the target
978
988
        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)],
 
989
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
 
990
                                          stat_value=stat_value)
 
991
        self.assertEqual('target', link_or_sha1)
 
992
        self.assertEqual([('read_link', 'a', '')], state._log)
 
993
        self.assertEqual([('l', '', 6, False, dirstate.DirState.NULLSTAT)],
984
994
                         entry[1])
985
995
        state.save()
986
 
        state.adjust_time(+20)  # Skip into the future, all files look old
 
996
        state.adjust_time(+20) # Skip into the future, all files look old
987
997
        del state._log[:]
988
 
        link_or_sha1 = self.update_entry(state, entry, abspath=b'a',
989
 
                                         stat_value=stat_value)
 
998
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
 
999
                                          stat_value=stat_value)
990
1000
        # The symlink stayed a symlink. So while it is new enough to cache, we
991
1001
        # don't bother setting the flag, because it is not really worth saving
992
1002
        # (when we stat the symlink, we'll have paged in the target.)
993
1003
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
994
1004
                         state._dirblock_state)
995
 
        self.assertEqual(b'target', link_or_sha1)
 
1005
        self.assertEqual('target', link_or_sha1)
996
1006
        # 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)],
 
1007
        self.assertEqual([('read_link', 'a', '')], state._log)
 
1008
        self.assertEqual([('l', 'target', 6, False, packed_stat)],
999
1009
                         entry[1])
1000
1010
 
1001
1011
        del state._log[:]
1002
1012
        # Another call won't re-read the link
1003
1013
        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)],
 
1014
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
 
1015
                                          stat_value=stat_value)
 
1016
        self.assertEqual('target', link_or_sha1)
 
1017
        self.assertEqual([('l', 'target', 6, False, packed_stat)],
1008
1018
                         entry[1])
1009
1019
 
1010
1020
    def do_update_entry(self, state, entry, abspath):
1014
1024
    def test_update_entry_dir(self):
1015
1025
        state, entry = self.get_state_with_a()
1016
1026
        self.build_tree(['a/'])
1017
 
        self.assertIs(None, self.do_update_entry(state, entry, b'a'))
 
1027
        self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1018
1028
 
1019
1029
    def test_update_entry_dir_unchanged(self):
1020
1030
        state, entry = self.get_state_with_a()
1021
1031
        self.build_tree(['a/'])
1022
1032
        state.adjust_time(+20)
1023
 
        self.assertIs(None, self.do_update_entry(state, entry, b'a'))
 
1033
        self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1024
1034
        # a/ used to be a file, but is now a directory, worth saving
1025
1035
        self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
1026
1036
                         state._dirblock_state)
1028
1038
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1029
1039
                         state._dirblock_state)
1030
1040
        # No changes to a/ means not worth saving.
1031
 
        self.assertIs(None, self.do_update_entry(state, entry, b'a'))
 
1041
        self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1032
1042
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1033
1043
                         state._dirblock_state)
1034
1044
        # Change the last-modified time for the directory
1039
1049
            # It looks like Win32 + FAT doesn't allow to change times on a dir.
1040
1050
            raise tests.TestSkipped("can't update mtime of a dir on FAT")
1041
1051
        saved_packed_stat = entry[1][0][-1]
1042
 
        self.assertIs(None, self.do_update_entry(state, entry, b'a'))
 
1052
        self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1043
1053
        # We *do* go ahead and update the information in the dirblocks, but we
1044
1054
        # don't bother setting IN_MEMORY_MODIFIED because it is trivial to
1045
1055
        # recompute.
1052
1062
        tree = self.make_branch_and_tree('tree')
1053
1063
        tree.lock_write()
1054
1064
        self.build_tree(['tree/a'])
1055
 
        tree.add(['a'], [b'a-id'])
 
1065
        tree.add(['a'], ['a-id'])
1056
1066
        with_a_id = tree.commit('witha')
1057
1067
        self.addCleanup(tree.unlock)
1058
1068
        state.set_parent_trees(
1059
1069
            [(with_a_id, tree.branch.repository.revision_tree(with_a_id))],
1060
1070
            [])
1061
 
        entry = state._get_entry(0, path_utf8=b'a')
 
1071
        entry = state._get_entry(0, path_utf8='a')
1062
1072
        self.build_tree(['a'])
1063
 
        sha1sum = b'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
 
1073
        sha1sum = 'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
1064
1074
        state.adjust_time(+20)
1065
 
        self.assertEqual(sha1sum, self.do_update_entry(state, entry, b'a'))
 
1075
        self.assertEqual(sha1sum, self.do_update_entry(state, entry, 'a'))
1066
1076
        self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
1067
1077
                         state._dirblock_state)
1068
1078
        state.save()
1069
1079
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1070
1080
                         state._dirblock_state)
1071
 
        self.assertEqual(sha1sum, self.do_update_entry(state, entry, b'a'))
 
1081
        self.assertEqual(sha1sum, self.do_update_entry(state, entry, 'a'))
1072
1082
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1073
1083
                         state._dirblock_state)
1074
1084
 
1075
1085
    def test_update_entry_tree_reference(self):
1076
1086
        state = test_dirstate.InstrumentedDirState.initialize('dirstate')
1077
1087
        self.addCleanup(state.unlock)
1078
 
        state.add('r', b'r-id', 'tree-reference', None, b'')
 
1088
        state.add('r', 'r-id', 'tree-reference', None, '')
1079
1089
        self.build_tree(['r/'])
1080
 
        entry = state._get_entry(0, path_utf8=b'r')
 
1090
        entry = state._get_entry(0, path_utf8='r')
1081
1091
        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])
 
1092
        entry = state._get_entry(0, path_utf8='r')
 
1093
        self.assertEqual('t', entry[1][0][0])
1084
1094
 
1085
1095
    def create_and_test_file(self, state, entry):
1086
1096
        """Create a file at 'a' and verify the state finds it during update.
1094
1104
 
1095
1105
        link_or_sha1 = self.do_update_entry(state, entry, abspath='a')
1096
1106
        self.assertEqual(None, link_or_sha1)
1097
 
        self.assertEqual([(b'f', b'', 14, False, dirstate.DirState.NULLSTAT)],
 
1107
        self.assertEqual([('f', '', 14, False, dirstate.DirState.NULLSTAT)],
1098
1108
                         entry[1])
1099
1109
        return packed_stat
1100
1110
 
1108
1118
        stat_value = os.lstat('a')
1109
1119
        packed_stat = dirstate.pack_stat(stat_value)
1110
1120
 
1111
 
        link_or_sha1 = self.do_update_entry(state, entry, abspath=b'a')
 
1121
        link_or_sha1 = self.do_update_entry(state, entry, abspath='a')
1112
1122
        self.assertIs(None, link_or_sha1)
1113
 
        self.assertEqual([(b'd', b'', 0, False, packed_stat)], entry[1])
 
1123
        self.assertEqual([('d', '', 0, False, packed_stat)], entry[1])
1114
1124
 
1115
1125
        return packed_stat
1116
1126
 
1130
1140
        stat_value = os.lstat('a')
1131
1141
        packed_stat = dirstate.pack_stat(stat_value)
1132
1142
 
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)],
 
1143
        link_or_sha1 = self.do_update_entry(state, entry, abspath='a')
 
1144
        self.assertEqual('path/to/foo', link_or_sha1)
 
1145
        self.assertEqual([('l', 'path/to/foo', 11, False, packed_stat)],
1136
1146
                         entry[1])
1137
1147
        return packed_stat
1138
1148
 
1200
1210
        state, entry = self.get_state_with_a()
1201
1211
        self.build_tree(['a'])
1202
1212
 
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
 
1213
        # Make sure we are using the win32 implementation of _is_executable
 
1214
        state._is_executable = state._is_executable_win32
1206
1215
 
1207
1216
        # 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)
 
1217
        # it is. With _is_executable_win32 we ignore what is on disk.
 
1218
        entry[1][0] = ('f', '', 0, True, dirstate.DirState.NULLSTAT)
1211
1219
 
1212
1220
        stat_value = os.lstat('a')
1213
1221
        packed_stat = dirstate.pack_stat(stat_value)
1214
1222
 
1215
 
        state.adjust_time(-10)  # Make sure everything is new
1216
 
        self.update_entry(state, entry, abspath=b'a', stat_value=stat_value)
 
1223
        state.adjust_time(-10) # Make sure everything is new
 
1224
        self.update_entry(state, entry, abspath='a', stat_value=stat_value)
1217
1225
 
1218
1226
        # The row is updated, but the executable bit stays set.
1219
 
        self.assertEqual([(b'f', b'', 14, True, dirstate.DirState.NULLSTAT)],
 
1227
        self.assertEqual([('f', '', 14, True, dirstate.DirState.NULLSTAT)],
1220
1228
                         entry[1])
1221
1229
 
1222
1230
        # Make the disk object look old enough to cache (but it won't cache the
1223
1231
        # sha as it is a new file).
1224
1232
        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])
 
1233
        digest = 'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
 
1234
        self.update_entry(state, entry, abspath='a', stat_value=stat_value)
 
1235
        self.assertEqual([('f', '', 14, True, dirstate.DirState.NULLSTAT)],
 
1236
            entry[1])
1229
1237
 
1230
1238
    def _prepare_tree(self):
1231
1239
        # Create a tree
1232
 
        text = b'Hello World\n'
 
1240
        text = 'Hello World\n'
1233
1241
        tree = self.make_branch_and_tree('tree')
1234
1242
        self.build_tree_contents([('tree/a file', text)])
1235
 
        tree.add('a file', b'a-file-id')
 
1243
        tree.add('a file', 'a-file-id')
1236
1244
        # Note: dirstate does not sha prior to the first commit
1237
1245
        # so commit now in order for the test to work
1238
1246
        tree.commit('first')
1241
1249
    def test_sha1provider_sha1_used(self):
1242
1250
        tree, text = self._prepare_tree()
1243
1251
        state = dirstate.DirState.from_tree(tree, 'dirstate',
1244
 
                                            UppercaseSHA1Provider())
 
1252
            UppercaseSHA1Provider())
1245
1253
        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)
 
1254
        expected_sha = osutils.sha_string(text.upper() + "foo")
 
1255
        entry = state._get_entry(0, path_utf8='a file')
1249
1256
        state._sha_cutoff_time()
1250
1257
        state._cutoff_time += 10
1251
1258
        sha1 = self.update_entry(state, entry, 'tree/a file',
1260
1267
        state._sha1_provider = UppercaseSHA1Provider()
1261
1268
        # If we used the standard provider, it would look like nothing has
1262
1269
        # changed
1263
 
        file_ids_changed = [change.file_id for change
 
1270
        file_ids_changed = [change[0] for change
1264
1271
                            in tree.iter_changes(tree.basis_tree())]
1265
 
        self.assertEqual([b'a-file-id'], file_ids_changed)
 
1272
        self.assertEqual(['a-file-id'], file_ids_changed)
1266
1273
 
1267
1274
 
1268
1275
class UppercaseSHA1Provider(dirstate.SHA1Provider):
1272
1279
        return self.stat_and_sha1(abspath)[1]
1273
1280
 
1274
1281
    def stat_and_sha1(self, abspath):
1275
 
        with open(abspath, 'rb') as file_obj:
 
1282
        file_obj = file(abspath, 'rb')
 
1283
        try:
1276
1284
            statvalue = os.fstat(file_obj.fileno())
1277
 
            text = b''.join(file_obj.readlines())
1278
 
            sha1 = osutils.sha_string(text.upper() + b"foo")
 
1285
            text = ''.join(file_obj.readlines())
 
1286
            sha1 = osutils.sha_string(text.upper() + "foo")
 
1287
        finally:
 
1288
            file_obj.close()
1279
1289
        return statvalue, sha1
1280
1290
 
1281
1291
 
1291
1301
        self.overrideAttr(dirstate, '_process_entry', self._process_entry)
1292
1302
 
1293
1303
    def assertChangedFileIds(self, expected, tree):
1294
 
        with tree.lock_read():
1295
 
            file_ids = [info.file_id for info
 
1304
        tree.lock_read()
 
1305
        try:
 
1306
            file_ids = [info[0] for info
1296
1307
                        in tree.iter_changes(tree.basis_tree())]
 
1308
        finally:
 
1309
            tree.unlock()
1297
1310
        self.assertEqual(sorted(expected), sorted(file_ids))
1298
1311
 
1299
1312
    def test_exceptions_raised(self):
1308
1321
        tree.lock_read()
1309
1322
        self.addCleanup(tree.unlock)
1310
1323
        basis_tree = tree.basis_tree()
1311
 
 
1312
1324
        def is_inside_raises(*args, **kwargs):
1313
1325
            raise RuntimeError('stop this')
1314
 
        self.overrideAttr(dirstate, 'is_inside', is_inside_raises)
1315
 
        try:
1316
 
            from .. import _dirstate_helpers_pyx
1317
 
        except ImportError:
1318
 
            pass
1319
 
        else:
1320
 
            self.overrideAttr(_dirstate_helpers_pyx,
1321
 
                              'is_inside', is_inside_raises)
1322
1326
        self.overrideAttr(osutils, 'is_inside', is_inside_raises)
1323
1327
        self.assertListRaises(RuntimeError, tree.iter_changes, basis_tree)
1324
1328
 
1325
1329
    def test_simple_changes(self):
1326
1330
        tree = self.make_branch_and_tree('tree')
1327
1331
        self.build_tree(['tree/file'])
1328
 
        tree.add(['file'], [b'file-id'])
1329
 
        self.assertChangedFileIds([tree.path2id(''), b'file-id'], tree)
 
1332
        tree.add(['file'], ['file-id'])
 
1333
        self.assertChangedFileIds([tree.get_root_id(), 'file-id'], tree)
1330
1334
        tree.commit('one')
1331
1335
        self.assertChangedFileIds([], tree)
1332
1336
 
1333
1337
    def test_sha1provider_stat_and_sha1_used(self):
1334
1338
        tree = self.make_branch_and_tree('tree')
1335
1339
        self.build_tree(['tree/file'])
1336
 
        tree.add(['file'], [b'file-id'])
 
1340
        tree.add(['file'], ['file-id'])
1337
1341
        tree.commit('one')
1338
1342
        tree.lock_write()
1339
1343
        self.addCleanup(tree.unlock)
1340
1344
        state = tree._current_dirstate()
1341
1345
        state._sha1_provider = UppercaseSHA1Provider()
1342
 
        self.assertChangedFileIds([b'file-id'], tree)
 
1346
        self.assertChangedFileIds(['file-id'], tree)
1343
1347
 
1344
1348
 
1345
1349
class TestPackStat(tests.TestCase):
1355
1359
        return _dirstate_helpers_py._unpack_stat(packed_string)[stat_field]
1356
1360
 
1357
1361
    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)))
 
1362
        self.assertEqual("AAAQAAAAABAAAAARAAAAAgAAAAEAAIHk",
 
1363
            self.pack((33252, 1, 2, 0, 0, 0, 4096, 15.5, 16.5, 17.5)))
1360
1364
 
1361
1365
    def test_giant_inode(self):
1362
1366
        packed = self.pack((33252, 0xF80000ABC, 0, 0, 0, 0, 0, 0, 0, 0))