43
42
# '\xc3\xae' == u'\xee' == i with hat
44
43
# So these are u'path' and 'id' only with a circle and a hat. (shappo?)
45
44
example_conflicts = conflicts.ConflictList(
46
[conflicts.MissingParent('Not deleting', u'p\xe5thg', b'\xc3\xaedg'),
47
conflicts.ContentsConflict(u'p\xe5tha', None, b'\xc3\xaeda'),
45
[conflicts.MissingParent('Not deleting', u'p\xe5thg', '\xc3\xaedg'),
46
conflicts.ContentsConflict(u'p\xe5tha', None, '\xc3\xaeda'),
48
47
conflicts.TextConflict(u'p\xe5tha'),
49
conflicts.PathConflict(u'p\xe5thb', u'p\xe5thc', b'\xc3\xaedb'),
48
conflicts.PathConflict(u'p\xe5thb', u'p\xe5thc', '\xc3\xaedb'),
50
49
conflicts.DuplicateID('Unversioned existing file',
51
50
u'p\xe5thc', u'p\xe5thc2',
52
b'\xc3\xaedc', b'\xc3\xaedc'),
53
conflicts.DuplicateEntry('Moved existing file to',
54
u'p\xe5thdd.moved', u'p\xe5thd',
56
conflicts.ParentLoop('Cancelled move', u'p\xe5the', u'p\xe5th2e',
57
None, b'\xc3\xaed2e'),
58
conflicts.UnversionedParent('Versioned directory',
59
u'p\xe5thf', b'\xc3\xaedf'),
60
conflicts.NonDirectoryParent('Created directory',
61
u'p\xe5thg', b'\xc3\xaedg'),
51
'\xc3\xaedc', '\xc3\xaedc'),
52
conflicts.DuplicateEntry('Moved existing file to',
53
u'p\xe5thdd.moved', u'p\xe5thd',
55
conflicts.ParentLoop('Cancelled move', u'p\xe5the', u'p\xe5th2e',
57
conflicts.UnversionedParent('Versioned directory',
58
u'p\xe5thf', '\xc3\xaedf'),
59
conflicts.NonDirectoryParent('Created directory',
60
u'p\xe5thg', '\xc3\xaedg'),
65
64
def vary_by_conflicts():
109
108
check_select(clist(), tree_conflicts,
110
109
['foo'], ignore_misses=True, recurse=True)
111
check_select(tree_conflicts, clist(), ['foo'], ignore_misses=True)
110
check_select (tree_conflicts, clist(), ['foo'], ignore_misses=True)
113
112
def test_resolve_conflicts_recursive(self):
114
113
tree = self.make_branch_and_tree('.')
115
114
self.build_tree(['dir/', 'dir/hello'])
116
115
tree.add(['dir', 'dir/hello'])
118
dirhello = conflicts.ConflictList(
119
[conflicts.TextConflict('dir/hello')])
117
dirhello = conflicts.ConflictList([conflicts.TextConflict('dir/hello')])
120
118
tree.set_conflicts(dirhello)
122
120
conflicts.resolve(tree, ['dir'], recursive=False, ignore_misses=True)
131
129
scenarios = scenarios.multiply_scenarios(vary_by_conflicts())
133
131
def test_stringification(self):
134
text = text_type(self.conflict)
132
text = unicode(self.conflict)
135
133
self.assertContainsString(text, self.conflict.path)
136
134
self.assertContainsString(text.lower(), "conflict")
137
135
self.assertContainsString(repr(self.conflict),
138
self.conflict.__class__.__name__)
136
self.conflict.__class__.__name__)
140
138
def test_stanza_roundtrip(self):
141
139
p = self.conflict
142
140
o = conflicts.Conflict.factory(**p.as_stanza().as_dict())
143
141
self.assertEqual(o, p)
145
self.assertIsInstance(o.path, text_type)
143
self.assertIsInstance(o.path, unicode)
147
145
if o.file_id is not None:
148
self.assertIsInstance(o.file_id, bytes)
146
self.assertIsInstance(o.file_id, str)
150
148
conflict_path = getattr(o, 'conflict_path', None)
151
149
if conflict_path is not None:
152
self.assertIsInstance(conflict_path, text_type)
150
self.assertIsInstance(conflict_path, unicode)
154
152
conflict_file_id = getattr(o, 'conflict_file_id', None)
155
153
if conflict_file_id is not None:
156
self.assertIsInstance(conflict_file_id, bytes)
154
self.assertIsInstance(conflict_file_id, str)
158
156
def test_stanzification(self):
159
157
stanza = self.conflict.as_stanza()
306
304
# Create an empty trunk
307
305
builder.build_snapshot(None, [
308
('add', (u'', b'root-id', 'directory', ''))],
309
revision_id=b'start')
306
('add', ('', 'root-id', 'directory', ''))],
310
308
# Add a minimal base content
311
309
base_actions = self._get_actions(self._base_actions)()
312
builder.build_snapshot([b'start'], base_actions, revision_id=b'base')
310
builder.build_snapshot(['start'], base_actions, revision_id='base')
313
311
# Modify the base content in branch
314
312
actions_other = self._get_actions(self._other['actions'])()
315
builder.build_snapshot([b'base'], actions_other, revision_id=b'other')
313
builder.build_snapshot(['base'], actions_other, revision_id='other')
316
314
# Modify the base content in trunk
317
315
actions_this = self._get_actions(self._this['actions'])()
318
builder.build_snapshot([b'base'], actions_this, revision_id=b'this')
316
builder.build_snapshot(['base'], actions_this, revision_id='this')
319
317
# builder.get_branch() tip is now 'this'
321
319
builder.finish_series()
379
377
# File modified on both sides
380
378
(dict(_base_actions='create_file',
381
_path='file', _file_id=b'file-id'),
379
_path='file', _file_id='file-id'),
382
380
('filed_modified_A',
383
381
dict(actions='modify_file_A', check='file_has_content_A')),
384
382
('file_modified_B',
385
383
dict(actions='modify_file_B', check='file_has_content_B')),),
386
384
# File modified on both sides in dir
387
385
(dict(_base_actions='create_file_in_dir',
388
_path='dir/file', _file_id=b'file-id'),
386
_path='dir/file', _file_id='file-id'),
389
387
('filed_modified_A_in_dir',
390
388
dict(actions='modify_file_A_in_dir',
391
389
check='file_in_dir_has_content_A')),
397
395
def do_create_file(self, path='file'):
398
return [('add', (path, b'file-id', 'file', b'trunk content\n'))]
396
return [('add', (path, 'file-id', 'file', 'trunk content\n'))]
400
398
def do_modify_file_A(self):
401
return [('modify', ('file', b'trunk content\nfeature A\n'))]
399
return [('modify', ('file', 'trunk content\nfeature A\n'))]
403
401
def do_modify_file_B(self):
404
return [('modify', ('file', b'trunk content\nfeature B\n'))]
402
return [('modify', ('file', 'trunk content\nfeature B\n'))]
406
404
def do_modify_file_A_in_dir(self):
407
return [('modify', ('dir/file', b'trunk content\nfeature A\n'))]
405
return [('modify', ('dir/file', 'trunk content\nfeature A\n'))]
409
407
def do_modify_file_B_in_dir(self):
410
return [('modify', ('dir/file', b'trunk content\nfeature B\n'))]
408
return [('modify', ('dir/file', 'trunk content\nfeature B\n'))]
412
410
def check_file_has_content_A(self, path='file'):
413
self.assertFileEqual(b'trunk content\nfeature A\n',
411
self.assertFileEqual('trunk content\nfeature A\n',
414
412
osutils.pathjoin('branch', path))
416
414
def check_file_has_content_B(self, path='file'):
417
self.assertFileEqual(b'trunk content\nfeature B\n',
415
self.assertFileEqual('trunk content\nfeature B\n',
418
416
osutils.pathjoin('branch', path))
420
418
def do_create_file_in_dir(self):
421
return [('add', ('dir', b'dir-id', 'directory', '')),
422
] + self.do_create_file('dir/file')
419
return [('add', ('dir', 'dir-id', 'directory', '')),
420
] + self.do_create_file('dir/file')
424
422
def check_file_in_dir_has_content_A(self):
425
423
self.check_file_has_content_A('dir/file')
450
448
# File modified/deleted
451
449
(dict(_base_actions='create_file',
452
_path='file', _file_id=b'file-id'),
450
_path='file', _file_id='file-id'),
453
451
('file_modified',
454
452
dict(actions='modify_file', check='file_has_more_content')),
456
454
dict(actions='delete_file', check='file_doesnt_exist')),),
457
455
# File renamed-modified/deleted
458
456
(dict(_base_actions='create_file',
459
_path='new-file', _file_id=b'file-id'),
457
_path='new-file', _file_id='file-id'),
460
458
('file_renamed_and_modified',
461
459
dict(actions='modify_and_rename_file',
462
460
check='file_renamed_and_more_content')),
476
474
def do_create_file(self):
477
return [('add', ('file', b'file-id', 'file', b'trunk content\n'))]
475
return [('add', ('file', 'file-id', 'file', 'trunk content\n'))]
479
477
def do_modify_file(self):
480
return [('modify', ('file', b'trunk content\nmore content\n'))]
478
return [('modify', ('file', 'trunk content\nmore content\n'))]
482
480
def do_modify_and_rename_file(self):
483
return [('modify', ('new-file', b'trunk content\nmore content\n')),
481
return [('modify', ('new-file', 'trunk content\nmore content\n')),
484
482
('rename', ('file', 'new-file'))]
486
484
def check_file_has_more_content(self):
487
self.assertFileEqual(b'trunk content\nmore content\n', 'branch/file')
485
self.assertFileEqual('trunk content\nmore content\n', 'branch/file')
489
487
def check_file_renamed_and_more_content(self):
490
self.assertFileEqual(
491
b'trunk content\nmore content\n', 'branch/new-file')
488
self.assertFileEqual('trunk content\nmore content\n', 'branch/new-file')
493
490
def do_delete_file(self):
494
491
return [('unversion', 'file')]
500
497
self.assertPathDoesNotExist('branch/file')
502
499
def do_create_file_in_dir(self):
503
return [('add', ('dir', b'dir-id', 'directory', '')),
504
('add', ('dir/file', b'file-id', 'file', b'trunk content\n'))]
500
return [('add', ('dir', 'dir-id', 'directory', '')),
501
('add', ('dir/file', 'file-id', 'file', 'trunk content\n'))]
506
503
def do_modify_file_in_dir(self):
507
return [('modify', ('dir/file', b'trunk content\nmore content\n'))]
504
return [('modify', ('dir/file', 'trunk content\nmore content\n'))]
509
506
def check_file_in_dir_has_more_content(self):
510
self.assertFileEqual(
511
b'trunk content\nmore content\n', 'branch/dir/file')
507
self.assertFileEqual('trunk content\nmore content\n', 'branch/dir/file')
513
509
def check_file_in_dir_doesnt_exist(self):
514
510
self.assertPathDoesNotExist('branch/dir/file')
538
534
(dict(_base_actions='create_file'),
540
536
dict(actions='rename_file', check='file_renamed',
541
path='new-file', file_id=b'file-id')),
537
path='new-file', file_id='file-id')),
543
539
dict(actions='delete_file', check='file_doesnt_exist',
544
540
# PathConflicts deletion handling requires a special
545
541
# hard-coded value
546
path='<deleted>', file_id=b'file-id')),),
542
path='<deleted>', file_id='file-id')),),
547
543
# File renamed/deleted in dir
548
544
(dict(_base_actions='create_file_in_dir'),
549
545
('file_renamed_in_dir',
550
546
dict(actions='rename_file_in_dir', check='file_in_dir_renamed',
551
path='dir/new-file', file_id=b'file-id')),
547
path='dir/new-file', file_id='file-id')),
553
549
dict(actions='delete_file_in_dir', check='file_in_dir_doesnt_exist',
554
550
# PathConflicts deletion handling requires a special
555
551
# hard-coded value
556
path='<deleted>', file_id=b'file-id')),),
552
path='<deleted>', file_id='file-id')),),
557
553
# File renamed/renamed differently
558
554
(dict(_base_actions='create_file'),
560
556
dict(actions='rename_file', check='file_renamed',
561
path='new-file', file_id=b'file-id')),
557
path='new-file', file_id='file-id')),
562
558
('file_renamed2',
563
559
dict(actions='rename_file2', check='file_renamed2',
564
path='new-file2', file_id=b'file-id')),),
560
path='new-file2', file_id='file-id')),),
565
561
# Dir renamed/deleted
566
562
(dict(_base_actions='create_dir'),
568
564
dict(actions='rename_dir', check='dir_renamed',
569
path='new-dir', file_id=b'dir-id')),
565
path='new-dir', file_id='dir-id')),
571
567
dict(actions='delete_dir', check='dir_doesnt_exist',
572
568
# PathConflicts deletion handling requires a special
573
569
# hard-coded value
574
path='<deleted>', file_id=b'dir-id')),),
570
path='<deleted>', file_id='dir-id')),),
575
571
# Dir renamed/renamed differently
576
572
(dict(_base_actions='create_dir'),
578
574
dict(actions='rename_dir', check='dir_renamed',
579
path='new-dir', file_id=b'dir-id')),
575
path='new-dir', file_id='dir-id')),
581
577
dict(actions='rename_dir2', check='dir_renamed2',
582
path='new-dir2', file_id=b'dir-id')),),
578
path='new-dir2', file_id='dir-id')),),
585
581
def do_create_file(self):
586
return [('add', ('file', b'file-id', 'file', b'trunk content\n'))]
582
return [('add', ('file', 'file-id', 'file', 'trunk content\n'))]
588
584
def do_create_dir(self):
589
return [('add', ('dir', b'dir-id', 'directory', ''))]
585
return [('add', ('dir', 'dir-id', 'directory', ''))]
591
587
def do_rename_file(self):
592
588
return [('rename', ('file', 'new-file'))]
632
628
self.assertPathDoesNotExist('branch/dir')
634
630
def do_create_file_in_dir(self):
635
return [('add', ('dir', b'dir-id', 'directory', '')),
636
('add', ('dir/file', b'file-id', 'file', b'trunk content\n'))]
631
return [('add', ('dir', 'dir-id', 'directory', '')),
632
('add', ('dir/file', 'file-id', 'file', 'trunk content\n'))]
638
634
def do_rename_file_in_dir(self):
639
635
return [('rename', ('dir/file', 'dir/new-file'))]
689
685
(dict(_base_actions='nothing'),
690
686
('filea_created',
691
687
dict(actions='create_file_a', check='file_content_a',
692
path='file', file_id=b'file-a-id')),
688
path='file', file_id='file-a-id')),
693
689
('fileb_created',
694
690
dict(actions='create_file_b', check='file_content_b',
695
path='file', file_id=b'file-b-id')),),
691
path='file', file_id='file-b-id')),),
696
692
# File created with different file-ids but deleted on one side
697
693
(dict(_base_actions='create_file_a'),
698
694
('filea_replaced',
699
695
dict(actions='replace_file_a_by_b', check='file_content_b',
700
path='file', file_id=b'file-b-id')),
696
path='file', file_id='file-b-id')),
701
697
('filea_modified',
702
698
dict(actions='modify_file_a', check='file_new_content',
703
path='file', file_id=b'file-a-id')),),
699
path='file', file_id='file-a-id')),),
706
702
def do_nothing(self):
709
705
def do_create_file_a(self):
710
return [('add', ('file', b'file-a-id', 'file', b'file a content\n'))]
706
return [('add', ('file', 'file-a-id', 'file', 'file a content\n'))]
712
708
def check_file_content_a(self):
713
self.assertFileEqual(b'file a content\n', 'branch/file')
709
self.assertFileEqual('file a content\n', 'branch/file')
715
711
def do_create_file_b(self):
716
return [('add', ('file', b'file-b-id', 'file', b'file b content\n'))]
712
return [('add', ('file', 'file-b-id', 'file', 'file b content\n'))]
718
714
def check_file_content_b(self):
719
self.assertFileEqual(b'file b content\n', 'branch/file')
715
self.assertFileEqual('file b content\n', 'branch/file')
721
717
def do_replace_file_a_by_b(self):
722
718
return [('unversion', 'file'),
723
('add', ('file', b'file-b-id', 'file', b'file b content\n'))]
719
('add', ('file', 'file-b-id', 'file', 'file b content\n'))]
725
721
def do_modify_file_a(self):
726
return [('modify', ('file', b'new content\n'))]
722
return [('modify', ('file', 'new content\n'))]
728
724
def check_file_new_content(self):
729
self.assertFileEqual(b'new content\n', 'branch/file')
725
self.assertFileEqual('new content\n', 'branch/file')
731
727
def _get_resolve_path_arg(self, wt, action):
732
728
return self._this['path']
936
932
(dict(_base_actions='create_dir1_dir2'),
937
933
('dir1_into_dir2',
938
934
dict(actions='move_dir1_into_dir2', check='dir1_moved',
939
dir_id=b'dir1-id', target_id=b'dir2-id', xfail=False)),
935
dir_id='dir1-id', target_id='dir2-id', xfail=False)),
940
936
('dir2_into_dir1',
941
937
dict(actions='move_dir2_into_dir1', check='dir2_moved',
942
dir_id=b'dir2-id', target_id=b'dir1-id', xfail=False))),
938
dir_id='dir2-id', target_id='dir1-id', xfail=False))),
943
939
# Subdirs moved into each other
944
940
(dict(_base_actions='create_dir1_4'),
945
941
('dir1_into_dir4',
946
942
dict(actions='move_dir1_into_dir4', check='dir1_2_moved',
947
dir_id=b'dir1-id', target_id=b'dir4-id', xfail=True)),
943
dir_id='dir1-id', target_id='dir4-id', xfail=True)),
948
944
('dir3_into_dir2',
949
945
dict(actions='move_dir3_into_dir2', check='dir3_4_moved',
950
dir_id=b'dir3-id', target_id=b'dir2-id', xfail=True))),
946
dir_id='dir3-id', target_id='dir2-id', xfail=True))),
953
949
def do_create_dir1_dir2(self):
954
return [('add', ('dir1', b'dir1-id', 'directory', '')),
955
('add', ('dir2', b'dir2-id', 'directory', '')), ]
950
return [('add', ('dir1', 'dir1-id', 'directory', '')),
951
('add', ('dir2', 'dir2-id', 'directory', '')),]
957
953
def do_move_dir1_into_dir2(self):
958
954
return [('rename', ('dir1', 'dir2/dir1'))]
969
965
self.assertPathExists('branch/dir1/dir2')
971
967
def do_create_dir1_4(self):
972
return [('add', ('dir1', b'dir1-id', 'directory', '')),
973
('add', ('dir1/dir2', b'dir2-id', 'directory', '')),
974
('add', ('dir3', b'dir3-id', 'directory', '')),
975
('add', ('dir3/dir4', b'dir4-id', 'directory', '')), ]
968
return [('add', ('dir1', 'dir1-id', 'directory', '')),
969
('add', ('dir1/dir2', 'dir2-id', 'directory', '')),
970
('add', ('dir3', 'dir3-id', 'directory', '')),
971
('add', ('dir3/dir4', 'dir4-id', 'directory', '')),]
977
973
def do_move_dir1_into_dir4(self):
978
974
return [('rename', ('dir1', 'dir3/dir4/dir1'))]