120
121
bisect_split_idx, bisect_path_idx, path)
123
self.assertEqual(path, paths[bisect_path_idx + offset])
124
self.assertEqual(path, paths[bisect_path_idx+offset])
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
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)
149
150
def test_involved(self):
150
151
"""This is where bisect_path_* diverges slightly."""
309
310
Also, ensure that the paths are in proper sorted order.
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
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')
332
333
def test_involved(self):
333
334
"""This is where bisect_left diverges slightly."""
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',
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',
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',
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',
342
343
dirblocks, split_dirblocks = self.paths_to_dirblocks(paths)
343
344
for path in paths:
344
345
self.assertBisect(dirblocks, split_dirblocks, path)
346
347
def test_involved_cached(self):
347
348
"""This is where bisect_left diverges slightly."""
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',
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',
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',
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',
357
358
dirblocks, split_dirblocks = self.paths_to_dirblocks(paths)
358
359
for path in paths:
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/', '')
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')
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')
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')
479
479
def test_cmp_unicode_not_allowed(self):
480
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')
481
self.assertRaises(TypeError, lt_by_dirs, u'Unicode', 'str')
482
self.assertRaises(TypeError, lt_by_dirs, 'str', u'Unicode')
483
483
self.assertRaises(TypeError, lt_by_dirs, u'Unicode', u'Unicode')
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'
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'
493
493
class TestCompiledLtByDirs(TestLtByDirs):
534
534
for idx2, path2 in enumerate(paths):
535
535
lt_result = lt_path_by_dirblock(path1, path2)
536
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))
537
'%s did not state that %r < %r, lt=%s'
538
% (lt_path_by_dirblock.__name__,
539
path1, path2, lt_result))
541
541
def test_cmp_simple_paths(self):
542
542
"""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'])
543
self.assertLtPathByDirblock(['', 'a', 'ab', 'abc', 'a/b/c', 'b/d/e'])
544
self.assertLtPathByDirblock(['kl', 'ab/cd', 'ab/ef', 'gh/ij'])
547
546
def test_tricky_paths(self):
548
547
self.assertLtPathByDirblock([
550
b'', b'a', b'a-a', b'a=a', b'b',
549
'', 'a', 'a-a', 'a=a', 'b',
551
550
# Contents of 'a'
552
b'a/a', b'a/a-a', b'a/a=a', b'a/b',
551
'a/a', 'a/a-a', 'a/a=a', 'a/b',
553
552
# Contents of 'a/a'
554
b'a/a/a', b'a/a/a-a', b'a/a/a=a',
553
'a/a/a', 'a/a/a-a', 'a/a/a=a',
555
554
# Contents of 'a/a/a'
556
b'a/a/a/a', b'a/a/a/b',
555
'a/a/a/a', 'a/a/a/b',
557
556
# Contents of 'a/a/a-a',
558
b'a/a/a-a/a', b'a/a/a-a/b',
557
'a/a/a-a/a', 'a/a/a-a/b',
559
558
# Contents of 'a/a/a=a',
560
b'a/a/a=a/a', b'a/a/a=a/b',
559
'a/a/a=a/a', 'a/a/a=a/b',
561
560
# Contents of 'a/a-a'
563
562
# Contents of 'a/a-a/a'
564
b'a/a-a/a/a', b'a/a-a/a/b',
563
'a/a-a/a/a', 'a/a-a/a/b',
565
564
# Contents of 'a/a=a'
567
566
# Contents of 'a/b'
569
568
# Contents of 'a-a',
571
570
# Contents of 'a=a',
573
572
# Contents of 'b',
576
575
self.assertLtPathByDirblock([
578
b'', b'a', b'a-a', b'a-z', b'a=a', b'a=z',
577
'', 'a', 'a-a', 'a-z', 'a=a', 'a=z',
579
578
# content of 'a/'
580
b'a/a', b'a/a-a', b'a/a-z',
582
b'a/z', b'a/z-a', b'a/z-z',
579
'a/a', 'a/a-a', 'a/a-z',
581
'a/z', 'a/z-a', 'a/z-z',
584
583
# content of 'a/a/'
586
585
# content of 'a/a-a'
588
587
# content of 'a/a-z'
590
589
# content of 'a/a=a'
592
591
# content of 'a/a=z'
594
593
# content of 'a/z/'
596
595
# content of 'a-a'
598
597
# content of 'a-z'
600
599
# content of 'a=a'
602
601
# content of 'a=z'
606
605
def test_unicode_not_allowed(self):
607
606
lt_path_by_dirblock = self.get_lt_path_by_dirblock()
647
646
_test_needs_features = [compiled_dirstate_helpers_feature]
649
648
def assertMemRChr(self, expected, s, c):
650
from .._dirstate_helpers_pyx import _py_memrchr
649
from breezy.bzr._dirstate_helpers_pyx import _py_memrchr
651
650
self.assertEqual(expected, _py_memrchr(s, c))
653
652
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')
653
self.assertMemRChr(None, '', 'a')
654
self.assertMemRChr(None, '', 'c')
655
self.assertMemRChr(None, 'abcdefghijklm', 'q')
656
self.assertMemRChr(None, 'aaaaaaaaaaaaaaaaaaaaaaa', 'b')
659
658
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')
659
self.assertMemRChr(0, 'abcdefghijklm', 'a')
660
self.assertMemRChr(1, 'abcdefghijklm', 'b')
661
self.assertMemRChr(2, 'abcdefghijklm', 'c')
662
self.assertMemRChr(10, 'abcdefghijklm', 'k')
663
self.assertMemRChr(11, 'abcdefghijklm', 'l')
664
self.assertMemRChr(12, 'abcdefghijklm', 'm')
667
666
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')
667
self.assertMemRChr(10, 'abcdefjklmabcdefghijklm', 'a')
668
self.assertMemRChr(11, 'abcdefjklmabcdefghijklm', 'b')
669
self.assertMemRChr(12, 'abcdefjklmabcdefghijklm', 'c')
670
self.assertMemRChr(20, 'abcdefjklmabcdefghijklm', 'k')
671
self.assertMemRChr(21, 'abcdefjklmabcdefghijklm', 'l')
672
self.assertMemRChr(22, 'abcdefjklmabcdefghijklm', 'm')
673
self.assertMemRChr(22, 'aaaaaaaaaaaaaaaaaaaaaaa', 'a')
676
675
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')
676
self.assertMemRChr(10, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'a')
677
self.assertMemRChr(11, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'b')
678
self.assertMemRChr(12, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'c')
679
self.assertMemRChr(20, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'k')
680
self.assertMemRChr(21, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'l')
681
self.assertMemRChr(22, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'm')
682
self.assertMemRChr(22, 'aaa\0\0\0aaaaaaa\0\0\0aaaaaaa', 'a')
683
self.assertMemRChr(9, '\0\0\0\0\0\0\0\0\0\0', '\0')
687
686
class TestReadDirblocks(test_dirstate.TestCaseWithDirState):
752
751
def test_bisect_dirblock(self):
753
752
if compiled_dirstate_helpers_feature.available():
754
from .._dirstate_helpers_pyx import bisect_dirblock
753
from breezy.bzr._dirstate_helpers_pyx import bisect_dirblock
756
from .._dirstate_helpers_py import bisect_dirblock
755
from breezy.bzr._dirstate_helpers_py import bisect_dirblock
757
756
self.assertIs(bisect_dirblock, dirstate.bisect_dirblock)
759
758
def test__bisect_path_left(self):
760
759
if compiled_dirstate_helpers_feature.available():
761
from .._dirstate_helpers_pyx import _bisect_path_left
760
from breezy.bzr._dirstate_helpers_pyx import _bisect_path_left
763
from .._dirstate_helpers_py import _bisect_path_left
762
from breezy.bzr._dirstate_helpers_py import _bisect_path_left
764
763
self.assertIs(_bisect_path_left, dirstate._bisect_path_left)
766
765
def test__bisect_path_right(self):
767
766
if compiled_dirstate_helpers_feature.available():
768
from .._dirstate_helpers_pyx import _bisect_path_right
767
from breezy.bzr._dirstate_helpers_pyx import _bisect_path_right
770
from .._dirstate_helpers_py import _bisect_path_right
769
from breezy.bzr._dirstate_helpers_py import _bisect_path_right
771
770
self.assertIs(_bisect_path_right, dirstate._bisect_path_right)
773
772
def test_lt_by_dirs(self):
774
773
if compiled_dirstate_helpers_feature.available():
775
from .._dirstate_helpers_pyx import lt_by_dirs
774
from ..bzr._dirstate_helpers_pyx import lt_by_dirs
777
from .._dirstate_helpers_py import lt_by_dirs
776
from ..bzr._dirstate_helpers_py import lt_by_dirs
778
777
self.assertIs(lt_by_dirs, dirstate.lt_by_dirs)
780
779
def test__read_dirblocks(self):
781
780
if compiled_dirstate_helpers_feature.available():
782
from .._dirstate_helpers_pyx import _read_dirblocks
781
from breezy.bzr._dirstate_helpers_pyx import _read_dirblocks
784
from .._dirstate_helpers_py import _read_dirblocks
783
from breezy.bzr._dirstate_helpers_py import _read_dirblocks
785
784
self.assertIs(_read_dirblocks, dirstate._read_dirblocks)
787
786
def test_update_entry(self):
788
787
if compiled_dirstate_helpers_feature.available():
789
from .._dirstate_helpers_pyx import update_entry
788
from breezy.bzr._dirstate_helpers_pyx import update_entry
791
from ..dirstate import update_entry
790
from breezy.bzr.dirstate import update_entry
792
791
self.assertIs(update_entry, dirstate.update_entry)
794
793
def test_process_entry(self):
795
794
if compiled_dirstate_helpers_feature.available():
796
from .._dirstate_helpers_pyx import ProcessEntryC
795
from breezy.bzr._dirstate_helpers_pyx import ProcessEntryC
797
796
self.assertIs(ProcessEntryC, dirstate._process_entry)
799
from ..dirstate import ProcessEntryPython
798
from breezy.bzr.dirstate import ProcessEntryPython
800
799
self.assertIs(ProcessEntryPython, dirstate._process_entry)
977
976
# Because the stat_value looks new, we should re-read the target
978
977
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)],
978
link_or_sha1 = self.update_entry(state, entry, abspath='a',
979
stat_value=stat_value)
980
self.assertEqual('target', link_or_sha1)
981
self.assertEqual([('read_link', 'a', '')], state._log)
982
self.assertEqual([('l', '', 6, False, dirstate.DirState.NULLSTAT)],
986
state.adjust_time(+20) # Skip into the future, all files look old
985
state.adjust_time(+20) # Skip into the future, all files look old
987
986
del state._log[:]
988
link_or_sha1 = self.update_entry(state, entry, abspath=b'a',
989
stat_value=stat_value)
987
link_or_sha1 = self.update_entry(state, entry, abspath='a',
988
stat_value=stat_value)
990
989
# The symlink stayed a symlink. So while it is new enough to cache, we
991
990
# don't bother setting the flag, because it is not really worth saving
992
991
# (when we stat the symlink, we'll have paged in the target.)
993
992
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
994
993
state._dirblock_state)
995
self.assertEqual(b'target', link_or_sha1)
994
self.assertEqual('target', link_or_sha1)
996
995
# 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)],
996
self.assertEqual([('read_link', 'a', '')], state._log)
997
self.assertEqual([('l', 'target', 6, False, packed_stat)],
1001
1000
del state._log[:]
1002
1001
# Another call won't re-read the link
1003
1002
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)],
1003
link_or_sha1 = self.update_entry(state, entry, abspath='a',
1004
stat_value=stat_value)
1005
self.assertEqual('target', link_or_sha1)
1006
self.assertEqual([('l', 'target', 6, False, packed_stat)],
1010
1009
def do_update_entry(self, state, entry, abspath):
1052
1051
tree = self.make_branch_and_tree('tree')
1053
1052
tree.lock_write()
1054
1053
self.build_tree(['tree/a'])
1055
tree.add(['a'], [b'a-id'])
1054
tree.add(['a'], ['a-id'])
1056
1055
with_a_id = tree.commit('witha')
1057
1056
self.addCleanup(tree.unlock)
1058
1057
state.set_parent_trees(
1059
1058
[(with_a_id, tree.branch.repository.revision_tree(with_a_id))],
1061
entry = state._get_entry(0, path_utf8=b'a')
1060
entry = state._get_entry(0, path_utf8='a')
1062
1061
self.build_tree(['a'])
1063
sha1sum = b'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
1062
sha1sum = 'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
1064
1063
state.adjust_time(+20)
1065
self.assertEqual(sha1sum, self.do_update_entry(state, entry, b'a'))
1064
self.assertEqual(sha1sum, self.do_update_entry(state, entry, 'a'))
1066
1065
self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
1067
1066
state._dirblock_state)
1069
1068
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1070
1069
state._dirblock_state)
1071
self.assertEqual(sha1sum, self.do_update_entry(state, entry, b'a'))
1070
self.assertEqual(sha1sum, self.do_update_entry(state, entry, 'a'))
1072
1071
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1073
1072
state._dirblock_state)
1075
1074
def test_update_entry_tree_reference(self):
1076
1075
state = test_dirstate.InstrumentedDirState.initialize('dirstate')
1077
1076
self.addCleanup(state.unlock)
1078
state.add('r', b'r-id', 'tree-reference', None, b'')
1077
state.add('r', 'r-id', 'tree-reference', None, '')
1079
1078
self.build_tree(['r/'])
1080
entry = state._get_entry(0, path_utf8=b'r')
1079
entry = state._get_entry(0, path_utf8='r')
1081
1080
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])
1081
entry = state._get_entry(0, path_utf8='r')
1082
self.assertEqual('t', entry[1][0][0])
1085
1084
def create_and_test_file(self, state, entry):
1086
1085
"""Create a file at 'a' and verify the state finds it during update.
1200
1199
state, entry = self.get_state_with_a()
1201
1200
self.build_tree(['a'])
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
1202
# Make sure we are using the win32 implementation of _is_executable
1203
state._is_executable = state._is_executable_win32
1207
1205
# 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
1210
entry[1][0] = (b'f', b'', 0, True, dirstate.DirState.NULLSTAT)
1206
# it is. With _is_executable_win32 we ignore what is on disk.
1207
entry[1][0] = ('f', '', 0, True, dirstate.DirState.NULLSTAT)
1212
1209
stat_value = os.lstat('a')
1213
1210
packed_stat = dirstate.pack_stat(stat_value)
1215
state.adjust_time(-10) # Make sure everything is new
1216
self.update_entry(state, entry, abspath=b'a', stat_value=stat_value)
1212
state.adjust_time(-10) # Make sure everything is new
1213
self.update_entry(state, entry, abspath='a', stat_value=stat_value)
1218
1215
# The row is updated, but the executable bit stays set.
1219
self.assertEqual([(b'f', b'', 14, True, dirstate.DirState.NULLSTAT)],
1216
self.assertEqual([('f', '', 14, True, dirstate.DirState.NULLSTAT)],
1222
1219
# Make the disk object look old enough to cache (but it won't cache the
1223
1220
# sha as it is a new file).
1224
1221
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)],
1222
digest = 'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
1223
self.update_entry(state, entry, abspath='a', stat_value=stat_value)
1224
self.assertEqual([('f', '', 14, True, dirstate.DirState.NULLSTAT)],
1230
1227
def _prepare_tree(self):
1231
1228
# Create a tree
1232
text = b'Hello World\n'
1229
text = 'Hello World\n'
1233
1230
tree = self.make_branch_and_tree('tree')
1234
1231
self.build_tree_contents([('tree/a file', text)])
1235
tree.add('a file', b'a-file-id')
1232
tree.add('a file', 'a-file-id')
1236
1233
# Note: dirstate does not sha prior to the first commit
1237
1234
# so commit now in order for the test to work
1238
1235
tree.commit('first')