65
def vary_by_conflicts():
66
for conflict in example_conflicts:
67
yield (conflict.__class__.__name__, {"conflict": conflict})
79
70
class TestConflicts(tests.TestCaseWithTransport):
81
def test_conflicts(self):
82
"""Conflicts are detected properly"""
83
# Use BzrDirFormat6 so we can fake conflicts
84
tree = self.make_branch_and_tree('.', format=bzrdir.BzrDirFormat6())
85
self.build_tree_contents([('hello', 'hello world4'),
86
('hello.THIS', 'hello world2'),
87
('hello.BASE', 'hello world1'),
88
('hello.OTHER', 'hello world3'),
89
('hello.sploo.BASE', 'yellowworld'),
90
('hello.sploo.OTHER', 'yellowworld2'),
93
self.assertLength(6, list(tree.list_files()))
95
tree_conflicts = tree.conflicts()
96
self.assertLength(2, tree_conflicts)
97
self.assertTrue('hello' in tree_conflicts[0].path)
98
self.assertTrue('hello.sploo' in tree_conflicts[1].path)
99
conflicts.restore('hello')
100
conflicts.restore('hello.sploo')
101
self.assertLength(0, tree.conflicts())
102
self.assertFileEqual('hello world2', 'hello')
103
self.assertFalse(os.path.lexists('hello.sploo'))
104
self.assertRaises(errors.NotConflicted, conflicts.restore, 'hello')
105
self.assertRaises(errors.NotConflicted,
106
conflicts.restore, 'hello.sploo')
108
72
def test_resolve_conflict_dir(self):
109
73
tree = self.make_branch_and_tree('.')
110
self.build_tree_contents([('hello', 'hello world4'),
111
('hello.THIS', 'hello world2'),
112
('hello.BASE', 'hello world1'),
74
self.build_tree_contents([('hello', b'hello world4'),
75
('hello.THIS', b'hello world2'),
76
('hello.BASE', b'hello world1'),
114
78
os.mkdir('hello.OTHER')
115
tree.add('hello', 'q')
79
tree.add('hello', b'q')
116
80
l = conflicts.ConflictList([conflicts.TextConflict('hello')])
117
81
l.remove_files(tree)
161
125
self.assertEqual(conflicts.ConflictList([]), tree.conflicts())
164
class TestConflictStanzas(tests.TestCase):
128
class TestPerConflict(tests.TestCase):
130
scenarios = scenarios.multiply_scenarios(vary_by_conflicts())
132
def test_stringification(self):
133
text = text_type(self.conflict)
134
self.assertContainsString(text, self.conflict.path)
135
self.assertContainsString(text.lower(), "conflict")
136
self.assertContainsString(repr(self.conflict),
137
self.conflict.__class__.__name__)
166
139
def test_stanza_roundtrip(self):
167
# write and read our example stanza.
168
stanza_iter = example_conflicts.to_stanzas()
169
processed = conflicts.ConflictList.from_stanzas(stanza_iter)
170
for o, p in zip(processed, example_conflicts):
171
self.assertEqual(o, p)
173
self.assertIsInstance(o.path, unicode)
175
if o.file_id is not None:
176
self.assertIsInstance(o.file_id, str)
178
conflict_path = getattr(o, 'conflict_path', None)
179
if conflict_path is not None:
180
self.assertIsInstance(conflict_path, unicode)
182
conflict_file_id = getattr(o, 'conflict_file_id', None)
183
if conflict_file_id is not None:
184
self.assertIsInstance(conflict_file_id, str)
141
o = conflicts.Conflict.factory(**p.as_stanza().as_dict())
142
self.assertEqual(o, p)
144
self.assertIsInstance(o.path, text_type)
146
if o.file_id is not None:
147
self.assertIsInstance(o.file_id, bytes)
149
conflict_path = getattr(o, 'conflict_path', None)
150
if conflict_path is not None:
151
self.assertIsInstance(conflict_path, text_type)
153
conflict_file_id = getattr(o, 'conflict_file_id', None)
154
if conflict_file_id is not None:
155
self.assertIsInstance(conflict_file_id, bytes)
186
157
def test_stanzification(self):
187
for stanza in example_conflicts.to_stanzas():
188
if 'file_id' in stanza:
189
# In Stanza form, the file_id has to be unicode.
190
self.assertStartsWith(stanza['file_id'], u'\xeed')
191
self.assertStartsWith(stanza['path'], u'p\xe5th')
192
if 'conflict_path' in stanza:
193
self.assertStartsWith(stanza['conflict_path'], u'p\xe5th')
194
if 'conflict_file_id' in stanza:
195
self.assertStartsWith(stanza['conflict_file_id'], u'\xeed')
158
stanza = self.conflict.as_stanza()
159
if 'file_id' in stanza:
160
# In Stanza form, the file_id has to be unicode.
161
self.assertStartsWith(stanza['file_id'], u'\xeed')
162
self.assertStartsWith(stanza['path'], u'p\xe5th')
163
if 'conflict_path' in stanza:
164
self.assertStartsWith(stanza['conflict_path'], u'p\xe5th')
165
if 'conflict_file_id' in stanza:
166
self.assertStartsWith(stanza['conflict_file_id'], u'\xeed')
169
class TestConflictList(tests.TestCase):
171
def test_stanzas_roundtrip(self):
172
stanzas_iter = example_conflicts.to_stanzas()
173
processed = conflicts.ConflictList.from_stanzas(stanzas_iter)
174
self.assertEqual(example_conflicts, processed)
176
def test_stringification(self):
177
for text, o in zip(example_conflicts.to_strings(), example_conflicts):
178
self.assertEqual(text, text_type(o))
198
181
# FIXME: The shell-like tests should be converted to real whitebox tests... or
298
"""Return the scenario list for the conflict type defined by the class.
300
Each scenario is of the form:
301
(common, (left_name, left_dict), (right_name, right_dict))
305
* left_name and right_name are the scenario names that will be combined
307
* left_dict and right_dict are the attributes specific to each half of
308
the scenario. They should include at least 'actions' and 'check' and
309
will be available as '_this' and '_other' test instance attributes.
311
Daughters classes are free to add their specific attributes as they see
312
fit in any of the three dicts.
314
This is a class method so that load_tests can find it.
316
'_base_actions' in the common dict, 'actions' and 'check' in the left
317
and right dicts use names that map to methods in the test classes. Some
318
prefixes are added to these names to get the correspong methods (see
319
_get_actions() and _get_check()). The motivation here is to avoid
320
collisions in the class namespace.
322
# Only concrete classes return actual scenarios
275
"""The scenario list for the conflict type defined by the class.
277
Each scenario is of the form:
278
(common, (left_name, left_dict), (right_name, right_dict))
282
* left_name and right_name are the scenario names that will be combined
284
* left_dict and right_dict are the attributes specific to each half of
285
the scenario. They should include at least 'actions' and 'check' and
286
will be available as '_this' and '_other' test instance attributes.
288
Daughters classes are free to add their specific attributes as they see
289
fit in any of the three dicts.
291
This is a class method so that load_tests can find it.
293
'_base_actions' in the common dict, 'actions' and 'check' in the left
294
and right dicts use names that map to methods in the test classes. Some
295
prefixes are added to these names to get the correspong methods (see
296
_get_actions() and _get_check()). The motivation here is to avoid
297
collisions in the class namespace.
326
301
super(TestParametrizedResolveConflicts, self).setUp()
328
303
builder.start_series()
330
305
# Create an empty trunk
331
builder.build_snapshot('start', None, [
332
('add', ('', 'root-id', 'directory', ''))])
306
builder.build_snapshot(None, [
307
('add', (u'', b'root-id', 'directory', ''))],
308
revision_id=b'start')
333
309
# Add a minimal base content
334
310
base_actions = self._get_actions(self._base_actions)()
335
builder.build_snapshot('base', ['start'], base_actions)
311
builder.build_snapshot([b'start'], base_actions, revision_id=b'base')
336
312
# Modify the base content in branch
337
313
actions_other = self._get_actions(self._other['actions'])()
338
builder.build_snapshot('other', ['base'], actions_other)
314
builder.build_snapshot([b'base'], actions_other, revision_id=b'other')
339
315
# Modify the base content in trunk
340
316
actions_this = self._get_actions(self._this['actions'])()
341
builder.build_snapshot('this', ['base'], actions_this)
317
builder.build_snapshot([b'base'], actions_this, revision_id=b'this')
342
318
# builder.get_branch() tip is now 'this'
344
320
builder.finish_series()
367
class TestResolveTextConflicts(TestParametrizedResolveConflicts):
369
_conflict_type = conflicts.TextConflict
371
# Set by the scenarios
372
# path and file-id for the file involved in the conflict
376
scenarios = mirror_scenarios(
378
# File modified on both sides
379
(dict(_base_actions='create_file',
380
_path='file', _file_id=b'file-id'),
382
dict(actions='modify_file_A', check='file_has_content_A')),
384
dict(actions='modify_file_B', check='file_has_content_B')),),
385
# File modified on both sides in dir
386
(dict(_base_actions='create_file_in_dir',
387
_path='dir/file', _file_id=b'file-id'),
388
('filed_modified_A_in_dir',
389
dict(actions='modify_file_A_in_dir',
390
check='file_in_dir_has_content_A')),
392
dict(actions='modify_file_B_in_dir',
393
check='file_in_dir_has_content_B')),),
396
def do_create_file(self, path='file'):
397
return [('add', (path, b'file-id', 'file', b'trunk content\n'))]
399
def do_modify_file_A(self):
400
return [('modify', ('file', b'trunk content\nfeature A\n'))]
402
def do_modify_file_B(self):
403
return [('modify', ('file', b'trunk content\nfeature B\n'))]
405
def do_modify_file_A_in_dir(self):
406
return [('modify', ('dir/file', b'trunk content\nfeature A\n'))]
408
def do_modify_file_B_in_dir(self):
409
return [('modify', ('dir/file', b'trunk content\nfeature B\n'))]
411
def check_file_has_content_A(self, path='file'):
412
self.assertFileEqual(b'trunk content\nfeature A\n',
413
osutils.pathjoin('branch', path))
415
def check_file_has_content_B(self, path='file'):
416
self.assertFileEqual(b'trunk content\nfeature B\n',
417
osutils.pathjoin('branch', path))
419
def do_create_file_in_dir(self):
420
return [('add', ('dir', b'dir-id', 'directory', '')),
421
] + self.do_create_file('dir/file')
423
def check_file_in_dir_has_content_A(self):
424
self.check_file_has_content_A('dir/file')
426
def check_file_in_dir_has_content_B(self):
427
self.check_file_has_content_B('dir/file')
429
def _get_resolve_path_arg(self, wt, action):
432
def assertTextConflict(self, wt, c):
433
self.assertEqual(self._file_id, c.file_id)
434
self.assertEqual(self._path, c.path)
435
_assert_conflict = assertTextConflict
391
438
class TestResolveContentsConflict(TestParametrizedResolveConflicts):
393
_conflict_type = conflicts.ContentsConflict,
440
_conflict_type = conflicts.ContentsConflict
395
# Set by load_tests from scenarios()
442
# Set by the scenarios
396
443
# path and file-id for the file involved in the conflict
447
scenarios = mirror_scenarios(
403
449
# File modified/deleted
404
450
(dict(_base_actions='create_file',
405
_path='file', _file_id='file-id'),
451
_path='file', _file_id=b'file-id'),
406
452
('file_modified',
407
453
dict(actions='modify_file', check='file_has_more_content')),
409
455
dict(actions='delete_file', check='file_doesnt_exist')),),
411
return mirror_scenarios(base_scenarios)
456
# File renamed-modified/deleted
457
(dict(_base_actions='create_file',
458
_path='new-file', _file_id=b'file-id'),
459
('file_renamed_and_modified',
460
dict(actions='modify_and_rename_file',
461
check='file_renamed_and_more_content')),
463
dict(actions='delete_file', check='file_doesnt_exist')),),
464
# File modified/deleted in dir
465
(dict(_base_actions='create_file_in_dir',
466
_path='dir/file', _file_id=b'file-id'),
467
('file_modified_in_dir',
468
dict(actions='modify_file_in_dir',
469
check='file_in_dir_has_more_content')),
470
('file_deleted_in_dir',
471
dict(actions='delete_file_in_dir',
472
check='file_in_dir_doesnt_exist')),),
413
475
def do_create_file(self):
414
return [('add', ('file', 'file-id', 'file', 'trunk content\n'))]
476
return [('add', ('file', b'file-id', 'file', b'trunk content\n'))]
416
478
def do_modify_file(self):
417
return [('modify', ('file-id', 'trunk content\nmore content\n'))]
479
return [('modify', ('file', b'trunk content\nmore content\n'))]
481
def do_modify_and_rename_file(self):
482
return [('modify', ('new-file', b'trunk content\nmore content\n')),
483
('rename', ('file', 'new-file'))]
419
485
def check_file_has_more_content(self):
420
self.assertFileEqual('trunk content\nmore content\n', 'branch/file')
486
self.assertFileEqual(b'trunk content\nmore content\n', 'branch/file')
488
def check_file_renamed_and_more_content(self):
489
self.assertFileEqual(b'trunk content\nmore content\n', 'branch/new-file')
422
491
def do_delete_file(self):
423
return [('unversion', 'file-id')]
492
return [('unversion', 'file')]
494
def do_delete_file_in_dir(self):
495
return [('unversion', 'dir/file')]
425
497
def check_file_doesnt_exist(self):
426
self.failIfExists('branch/file')
498
self.assertPathDoesNotExist('branch/file')
500
def do_create_file_in_dir(self):
501
return [('add', ('dir', b'dir-id', 'directory', '')),
502
('add', ('dir/file', b'file-id', 'file', b'trunk content\n'))]
504
def do_modify_file_in_dir(self):
505
return [('modify', ('dir/file', b'trunk content\nmore content\n'))]
507
def check_file_in_dir_has_more_content(self):
508
self.assertFileEqual(b'trunk content\nmore content\n', 'branch/dir/file')
510
def check_file_in_dir_doesnt_exist(self):
511
self.assertPathDoesNotExist('branch/dir/file')
428
513
def _get_resolve_path_arg(self, wt, action):
429
514
return self._path
437
522
class TestResolvePathConflict(TestParametrizedResolveConflicts):
439
_conflict_type = conflicts.PathConflict,
524
_conflict_type = conflicts.PathConflict
441
526
def do_nothing(self):
446
# Each side dict additionally defines:
447
# - path path involved (can be '<deleted>')
529
# Each side dict additionally defines:
530
# - path path involved (can be '<deleted>')
532
scenarios = mirror_scenarios(
450
534
# File renamed/deleted
451
535
(dict(_base_actions='create_file'),
453
537
dict(actions='rename_file', check='file_renamed',
454
path='new-file', file_id='file-id')),
538
path='new-file', file_id=b'file-id')),
456
540
dict(actions='delete_file', check='file_doesnt_exist',
457
541
# PathConflicts deletion handling requires a special
458
542
# hard-coded value
459
path='<deleted>', file_id='file-id')),),
543
path='<deleted>', file_id=b'file-id')),),
544
# File renamed/deleted in dir
545
(dict(_base_actions='create_file_in_dir'),
546
('file_renamed_in_dir',
547
dict(actions='rename_file_in_dir', check='file_in_dir_renamed',
548
path='dir/new-file', file_id=b'file-id')),
550
dict(actions='delete_file_in_dir', check='file_in_dir_doesnt_exist',
551
# PathConflicts deletion handling requires a special
553
path='<deleted>', file_id=b'file-id')),),
460
554
# File renamed/renamed differently
461
555
(dict(_base_actions='create_file'),
463
557
dict(actions='rename_file', check='file_renamed',
464
path='new-file', file_id='file-id')),
558
path='new-file', file_id=b'file-id')),
465
559
('file_renamed2',
466
560
dict(actions='rename_file2', check='file_renamed2',
467
path='new-file2', file_id='file-id')),),
561
path='new-file2', file_id=b'file-id')),),
468
562
# Dir renamed/deleted
469
563
(dict(_base_actions='create_dir'),
471
565
dict(actions='rename_dir', check='dir_renamed',
472
path='new-dir', file_id='dir-id')),
566
path='new-dir', file_id=b'dir-id')),
474
568
dict(actions='delete_dir', check='dir_doesnt_exist',
475
569
# PathConflicts deletion handling requires a special
476
570
# hard-coded value
477
path='<deleted>', file_id='dir-id')),),
571
path='<deleted>', file_id=b'dir-id')),),
478
572
# Dir renamed/renamed differently
479
573
(dict(_base_actions='create_dir'),
481
575
dict(actions='rename_dir', check='dir_renamed',
482
path='new-dir', file_id='dir-id')),
576
path='new-dir', file_id=b'dir-id')),
484
578
dict(actions='rename_dir2', check='dir_renamed2',
485
path='new-dir2', file_id='dir-id')),),
487
return mirror_scenarios(base_scenarios)
579
path='new-dir2', file_id=b'dir-id')),),
489
582
def do_create_file(self):
490
return [('add', ('file', 'file-id', 'file', 'trunk content\n'))]
583
return [('add', ('file', b'file-id', 'file', b'trunk content\n'))]
492
585
def do_create_dir(self):
493
return [('add', ('dir', 'dir-id', 'directory', ''))]
586
return [('add', ('dir', b'dir-id', 'directory', ''))]
495
588
def do_rename_file(self):
496
589
return [('rename', ('file', 'new-file'))]
498
591
def check_file_renamed(self):
499
self.failIfExists('branch/file')
500
self.failUnlessExists('branch/new-file')
592
self.assertPathDoesNotExist('branch/file')
593
self.assertPathExists('branch/new-file')
502
595
def do_rename_file2(self):
503
596
return [('rename', ('file', 'new-file2'))]
505
598
def check_file_renamed2(self):
506
self.failIfExists('branch/file')
507
self.failUnlessExists('branch/new-file2')
599
self.assertPathDoesNotExist('branch/file')
600
self.assertPathExists('branch/new-file2')
509
602
def do_rename_dir(self):
510
603
return [('rename', ('dir', 'new-dir'))]
512
605
def check_dir_renamed(self):
513
self.failIfExists('branch/dir')
514
self.failUnlessExists('branch/new-dir')
606
self.assertPathDoesNotExist('branch/dir')
607
self.assertPathExists('branch/new-dir')
516
609
def do_rename_dir2(self):
517
610
return [('rename', ('dir', 'new-dir2'))]
519
612
def check_dir_renamed2(self):
520
self.failIfExists('branch/dir')
521
self.failUnlessExists('branch/new-dir2')
613
self.assertPathDoesNotExist('branch/dir')
614
self.assertPathExists('branch/new-dir2')
523
616
def do_delete_file(self):
524
return [('unversion', 'file-id')]
617
return [('unversion', 'file')]
619
def do_delete_file_in_dir(self):
620
return [('unversion', 'dir/file')]
526
622
def check_file_doesnt_exist(self):
527
self.failIfExists('branch/file')
623
self.assertPathDoesNotExist('branch/file')
529
625
def do_delete_dir(self):
530
return [('unversion', 'dir-id')]
626
return [('unversion', 'dir')]
532
628
def check_dir_doesnt_exist(self):
533
self.failIfExists('branch/dir')
629
self.assertPathDoesNotExist('branch/dir')
631
def do_create_file_in_dir(self):
632
return [('add', ('dir', b'dir-id', 'directory', '')),
633
('add', ('dir/file', b'file-id', 'file', b'trunk content\n'))]
635
def do_rename_file_in_dir(self):
636
return [('rename', ('dir/file', 'dir/new-file'))]
638
def check_file_in_dir_renamed(self):
639
self.assertPathDoesNotExist('branch/dir/file')
640
self.assertPathExists('branch/dir/new-file')
642
def check_file_in_dir_doesnt_exist(self):
643
self.assertPathDoesNotExist('branch/dir/file')
535
645
def _get_resolve_path_arg(self, wt, action):
536
646
tpath = self._this['path']
569
679
class TestResolveDuplicateEntry(TestParametrizedResolveConflicts):
571
_conflict_type = conflicts.DuplicateEntry,
681
_conflict_type = conflicts.DuplicateEntry
575
# Each side dict additionally defines:
683
scenarios = mirror_scenarios(
579
685
# File created with different file-ids
580
686
(dict(_base_actions='nothing'),
581
687
('filea_created',
582
688
dict(actions='create_file_a', check='file_content_a',
583
path='file', file_id='file-a-id')),
689
path='file', file_id=b'file-a-id')),
584
690
('fileb_created',
585
691
dict(actions='create_file_b', check='file_content_b',
586
path='file', file_id='file-b-id')),),
588
return mirror_scenarios(base_scenarios)
692
path='file', file_id=b'file-b-id')),),
693
# File created with different file-ids but deleted on one side
694
(dict(_base_actions='create_file_a'),
696
dict(actions='replace_file_a_by_b', check='file_content_b',
697
path='file', file_id=b'file-b-id')),
699
dict(actions='modify_file_a', check='file_new_content',
700
path='file', file_id=b'file-a-id')),),
590
703
def do_nothing(self):
593
706
def do_create_file_a(self):
594
return [('add', ('file', 'file-a-id', 'file', 'file a content\n'))]
707
return [('add', ('file', b'file-a-id', 'file', b'file a content\n'))]
596
709
def check_file_content_a(self):
597
self.assertFileEqual('file a content\n', 'branch/file')
710
self.assertFileEqual(b'file a content\n', 'branch/file')
599
712
def do_create_file_b(self):
600
return [('add', ('file', 'file-b-id', 'file', 'file b content\n'))]
713
return [('add', ('file', b'file-b-id', 'file', b'file b content\n'))]
602
715
def check_file_content_b(self):
603
self.assertFileEqual('file b content\n', 'branch/file')
716
self.assertFileEqual(b'file b content\n', 'branch/file')
718
def do_replace_file_a_by_b(self):
719
return [('unversion', 'file'),
720
('add', ('file', b'file-b-id', 'file', b'file b content\n'))]
722
def do_modify_file_a(self):
723
return [('modify', ('file', b'new content\n'))]
725
def check_file_new_content(self):
726
self.assertFileEqual(b'new content\n', 'branch/file')
605
728
def _get_resolve_path_arg(self, wt, action):
606
729
return self._this['path']
692
813
def test_keep_them_all(self):
693
814
self.run_script("""
695
$ bzr commit --strict -m 'No more conflicts nor unknown files'
816
2>2 conflicts resolved, 0 remaining
817
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
698
820
def test_adopt_child(self):
699
821
self.run_script("""
700
$ bzr mv dir/file2 file2
703
$ bzr commit --strict -m 'No more conflicts nor unknown files'
822
$ brz mv -q dir/file2 file2
823
$ brz rm -q dir --no-backup
825
2>2 conflicts resolved, 0 remaining
826
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
706
829
def test_kill_them_all(self):
707
830
self.run_script("""
710
$ bzr commit --strict -m 'No more conflicts nor unknown files'
831
$ brz rm -q dir --no-backup
833
2>2 conflicts resolved, 0 remaining
834
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
713
837
def test_resolve_taking_this(self):
714
838
self.run_script("""
715
$ bzr resolve --take-this dir
716
$ bzr commit --strict -m 'No more conflicts nor unknown files'
839
$ brz resolve --take-this dir
841
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
719
844
def test_resolve_taking_other(self):
720
845
self.run_script("""
721
$ bzr resolve --take-other dir
722
$ bzr commit --strict -m 'No more conflicts nor unknown files'
846
$ brz resolve --take-other dir
848
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
726
852
class TestResolveDeletingParent(TestResolveConflicts):
732
859
$ echo 'trunk content' >dir/file
734
$ bzr commit -m 'Create trunk'
736
$ bzr rm dir/file --force
738
$ bzr commit -m 'Remove dir/file'
740
$ bzr branch . -r 1 ../branch
861
$ brz commit -m 'Create trunk' -q
862
$ brz rm -q dir/file --no-backup
863
$ brz rm -q dir --no-backup
864
$ brz commit -q -m 'Remove dir/file'
865
$ brz branch -q . -r 1 ../branch
742
867
$ echo 'branch content' >dir/file2
744
$ bzr commit -m 'Add dir/file2 in branch'
868
$ brz add -q dir/file2
869
$ brz commit -q -m 'Add dir/file2 in branch'
748
872
2>Conflict: can't delete dir because it is not empty. Not deleting.
749
873
2>Conflict because dir is not versioned, but has versioned children. Versioned directory.
753
877
def test_keep_them_all(self):
754
878
self.run_script("""
756
$ bzr commit --strict -m 'No more conflicts nor unknown files'
880
2>2 conflicts resolved, 0 remaining
881
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
759
884
def test_adopt_child(self):
760
885
self.run_script("""
761
$ bzr mv dir/file2 file2
764
$ bzr commit --strict -m 'No more conflicts nor unknown files'
886
$ brz mv -q dir/file2 file2
887
$ brz rm -q dir --no-backup
889
2>2 conflicts resolved, 0 remaining
890
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
767
893
def test_kill_them_all(self):
768
894
self.run_script("""
771
$ bzr commit --strict -m 'No more conflicts nor unknown files'
895
$ brz rm -q dir --no-backup
897
2>2 conflicts resolved, 0 remaining
898
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
774
901
def test_resolve_taking_this(self):
775
902
self.run_script("""
776
$ bzr resolve --take-this dir
777
$ bzr commit --strict -m 'No more conflicts nor unknown files'
903
$ brz resolve --take-this dir
904
2>2 conflicts resolved, 0 remaining
905
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
780
908
def test_resolve_taking_other(self):
781
909
self.run_script("""
782
$ bzr resolve --take-other dir
783
$ bzr commit --strict -m 'No more conflicts nor unknown files'
910
$ brz resolve --take-other dir
913
2>2 conflicts resolved, 0 remaining
914
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
787
918
class TestResolveParentLoop(TestParametrizedResolveConflicts):
789
_conflict_type = conflicts.ParentLoop,
920
_conflict_type = conflicts.ParentLoop
791
922
_this_args = None
792
923
_other_args = None
796
# Each side dict additionally defines:
797
# - dir_id: the directory being moved
798
# - target_id: The target directory
799
# - xfail: whether the test is expected to fail if the action is
800
# involved as 'other'
925
# Each side dict additionally defines:
926
# - dir_id: the directory being moved
927
# - target_id: The target directory
928
# - xfail: whether the test is expected to fail if the action is
929
# involved as 'other'
930
scenarios = mirror_scenarios(
802
932
# Dirs moved into each other
803
933
(dict(_base_actions='create_dir1_dir2'),
804
934
('dir1_into_dir2',
805
935
dict(actions='move_dir1_into_dir2', check='dir1_moved',
806
dir_id='dir1-id', target_id='dir2-id', xfail=False)),
936
dir_id=b'dir1-id', target_id='dir2-id', xfail=False)),
807
937
('dir2_into_dir1',
808
938
dict(actions='move_dir2_into_dir1', check='dir2_moved',
809
dir_id='dir2-id', target_id='dir1-id', xfail=False))),
939
dir_id=b'dir2-id', target_id='dir1-id', xfail=False))),
810
940
# Subdirs moved into each other
811
941
(dict(_base_actions='create_dir1_4'),
812
942
('dir1_into_dir4',
813
943
dict(actions='move_dir1_into_dir4', check='dir1_2_moved',
814
dir_id='dir1-id', target_id='dir4-id', xfail=True)),
944
dir_id=b'dir1-id', target_id='dir4-id', xfail=True)),
815
945
('dir3_into_dir2',
816
946
dict(actions='move_dir3_into_dir2', check='dir3_4_moved',
817
dir_id='dir3-id', target_id='dir2-id', xfail=True))),
819
return mirror_scenarios(base_scenarios)
947
dir_id=b'dir3-id', target_id='dir2-id', xfail=True))),
821
950
def do_create_dir1_dir2(self):
822
return [('add', ('dir1', 'dir1-id', 'directory', '')),
823
('add', ('dir2', 'dir2-id', 'directory', '')),]
951
return [('add', ('dir1', b'dir1-id', 'directory', '')),
952
('add', ('dir2', b'dir2-id', 'directory', '')),]
825
954
def do_move_dir1_into_dir2(self):
826
955
return [('rename', ('dir1', 'dir2/dir1'))]
828
957
def check_dir1_moved(self):
829
self.failIfExists('branch/dir1')
830
self.failUnlessExists('branch/dir2/dir1')
958
self.assertPathDoesNotExist('branch/dir1')
959
self.assertPathExists('branch/dir2/dir1')
832
961
def do_move_dir2_into_dir1(self):
833
962
return [('rename', ('dir2', 'dir1/dir2'))]
835
964
def check_dir2_moved(self):
836
self.failIfExists('branch/dir2')
837
self.failUnlessExists('branch/dir1/dir2')
965
self.assertPathDoesNotExist('branch/dir2')
966
self.assertPathExists('branch/dir1/dir2')
839
968
def do_create_dir1_4(self):
840
return [('add', ('dir1', 'dir1-id', 'directory', '')),
841
('add', ('dir1/dir2', 'dir2-id', 'directory', '')),
842
('add', ('dir3', 'dir3-id', 'directory', '')),
843
('add', ('dir3/dir4', 'dir4-id', 'directory', '')),]
969
return [('add', ('dir1', b'dir1-id', 'directory', '')),
970
('add', ('dir1/dir2', b'dir2-id', 'directory', '')),
971
('add', ('dir3', b'dir3-id', 'directory', '')),
972
('add', ('dir3/dir4', b'dir4-id', 'directory', '')),]
845
974
def do_move_dir1_into_dir4(self):
846
975
return [('rename', ('dir1', 'dir3/dir4/dir1'))]
848
977
def check_dir1_2_moved(self):
849
self.failIfExists('branch/dir1')
850
self.failUnlessExists('branch/dir3/dir4/dir1')
851
self.failUnlessExists('branch/dir3/dir4/dir1/dir2')
978
self.assertPathDoesNotExist('branch/dir1')
979
self.assertPathExists('branch/dir3/dir4/dir1')
980
self.assertPathExists('branch/dir3/dir4/dir1/dir2')
853
982
def do_move_dir3_into_dir2(self):
854
983
return [('rename', ('dir3', 'dir1/dir2/dir3'))]
856
985
def check_dir3_4_moved(self):
857
self.failIfExists('branch/dir3')
858
self.failUnlessExists('branch/dir1/dir2/dir3')
859
self.failUnlessExists('branch/dir1/dir2/dir3/dir4')
986
self.assertPathDoesNotExist('branch/dir3')
987
self.assertPathExists('branch/dir1/dir2/dir3')
988
self.assertPathExists('branch/dir1/dir2/dir3/dir4')
861
990
def _get_resolve_path_arg(self, wt, action):
862
991
# ParentLoop says: moving <conflict_path> into <path>. Cancelled move.
941
1074
# This is nearly like TestResolveNonDirectoryParent but with branch and
942
1075
# trunk switched. As such it should certainly produce the same
1077
self.assertRaises(errors.MalformedTransform,
1078
self.run_script, """
948
$ bzr commit -m 'Create trunk'
1084
$ brz commit -m 'Create trunk' -q
950
1086
$ echo "Boo!" >foo
951
$ bzr commit -m 'foo is now a file'
953
$ bzr branch . -r 1 ../branch
1087
$ brz commit -m 'foo is now a file' -q
1088
$ brz branch -q . -r 1 ../branch -q
955
1090
$ echo "Boing" >foo/bar
957
$ bzr commit -m 'Add foo/bar'
960
2>bzr: ERROR: Tree transform is malformed [('unversioned executability', 'new-1')]
1091
$ brz add -q foo/bar -q
1092
$ brz commit -m 'Add foo/bar' -q
1093
$ brz merge ../trunk
1094
2>brz: ERROR: Tree transform is malformed [('unversioned executability', 'new-1')]
1098
class TestNoFinalPath(script.TestCaseWithTransportAndScript):
1100
def test_bug_805809(self):
1103
Created a standalone tree (format: 2a)
1108
$ brz commit -m 'create file on trunk'
1109
2>Committing to: .../trunk/
1111
2>Committed revision 1.
1112
# Create a debian branch based on trunk
1114
$ brz branch trunk -r 1 debian
1115
2>Branched 1 revision.
1122
$ brz commit -m 'rename file to dir/file for debian'
1123
2>Committing to: .../debian/
1125
2>renamed file => dir/file
1126
2>Committed revision 2.
1127
# Create an experimental branch with a new root-id
1129
$ brz init experimental
1130
Created a standalone tree (format: 2a)
1132
# Work around merging into empty branch not being supported
1133
# (http://pad.lv/308562)
1134
$ echo something >not-empty
1137
$ brz commit -m 'Add some content in experimental'
1138
2>Committing to: .../experimental/
1140
2>Committed revision 1.
1141
# merge debian even without a common ancestor
1142
$ brz merge ../debian -r0..2
1145
2>All changes applied successfully.
1146
$ brz commit -m 'merging debian into experimental'
1147
2>Committing to: .../experimental/
1150
2>Committed revision 2.
1151
# Create an ubuntu branch with yet another root-id
1154
Created a standalone tree (format: 2a)
1156
# Work around merging into empty branch not being supported
1157
# (http://pad.lv/308562)
1158
$ echo something >not-empty-ubuntu
1160
adding not-empty-ubuntu
1161
$ brz commit -m 'Add some content in experimental'
1162
2>Committing to: .../ubuntu/
1163
2>added not-empty-ubuntu
1164
2>Committed revision 1.
1166
$ brz merge ../debian -r0..2
1169
2>All changes applied successfully.
1170
$ brz commit -m 'merging debian'
1171
2>Committing to: .../ubuntu/
1174
2>Committed revision 2.
1175
# Now try to merge experimental
1176
$ brz merge ../experimental
1178
2>Path conflict: dir / dir
1179
2>1 conflicts encountered.