57
44
# '\xc3\xae' == u'\xee' == i with hat
58
45
# So these are u'path' and 'id' only with a circle and a hat. (shappo?)
59
46
example_conflicts = conflicts.ConflictList(
60
[conflicts.MissingParent('Not deleting', u'p\xe5thg', '\xc3\xaedg'),
61
conflicts.ContentsConflict(u'p\xe5tha', None, '\xc3\xaeda'),
47
[conflicts.MissingParent('Not deleting', u'p\xe5thg', b'\xc3\xaedg'),
48
conflicts.ContentsConflict(u'p\xe5tha', None, b'\xc3\xaeda'),
62
49
conflicts.TextConflict(u'p\xe5tha'),
63
conflicts.PathConflict(u'p\xe5thb', u'p\xe5thc', '\xc3\xaedb'),
50
conflicts.PathConflict(u'p\xe5thb', u'p\xe5thc', b'\xc3\xaedb'),
64
51
conflicts.DuplicateID('Unversioned existing file',
65
52
u'p\xe5thc', u'p\xe5thc2',
66
'\xc3\xaedc', '\xc3\xaedc'),
67
conflicts.DuplicateEntry('Moved existing file to',
68
u'p\xe5thdd.moved', u'p\xe5thd',
70
conflicts.ParentLoop('Cancelled move', u'p\xe5the', u'p\xe5th2e',
72
conflicts.UnversionedParent('Versioned directory',
73
u'p\xe5thf', '\xc3\xaedf'),
74
conflicts.NonDirectoryParent('Created directory',
75
u'p\xe5thg', '\xc3\xaedg'),
53
b'\xc3\xaedc', b'\xc3\xaedc'),
54
conflicts.DuplicateEntry('Moved existing file to',
55
u'p\xe5thdd.moved', u'p\xe5thd',
57
conflicts.ParentLoop('Cancelled move', u'p\xe5the', u'p\xe5th2e',
58
None, b'\xc3\xaed2e'),
59
conflicts.UnversionedParent('Versioned directory',
60
u'p\xe5thf', b'\xc3\xaedf'),
61
conflicts.NonDirectoryParent('Created directory',
62
u'p\xe5thg', b'\xc3\xaedg'),
66
def vary_by_conflicts():
67
for conflict in example_conflicts:
68
yield (conflict.__class__.__name__, {"conflict": conflict})
79
71
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
73
def test_resolve_conflict_dir(self):
109
74
tree = self.make_branch_and_tree('.')
110
self.build_tree_contents([('hello', 'hello world4'),
111
('hello.THIS', 'hello world2'),
112
('hello.BASE', 'hello world1'),
75
self.build_tree_contents([('hello', b'hello world4'),
76
('hello.THIS', b'hello world2'),
77
('hello.BASE', b'hello world1'),
114
79
os.mkdir('hello.OTHER')
115
tree.add('hello', 'q')
80
tree.add('hello', b'q')
116
81
l = conflicts.ConflictList([conflicts.TextConflict('hello')])
117
82
l.remove_files(tree)
161
127
self.assertEqual(conflicts.ConflictList([]), tree.conflicts())
164
class TestConflictStanzas(tests.TestCase):
130
class TestPerConflict(tests.TestCase):
132
scenarios = scenarios.multiply_scenarios(vary_by_conflicts())
134
def test_stringification(self):
135
text = text_type(self.conflict)
136
self.assertContainsString(text, self.conflict.path)
137
self.assertContainsString(text.lower(), "conflict")
138
self.assertContainsString(repr(self.conflict),
139
self.conflict.__class__.__name__)
166
141
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)
143
o = conflicts.Conflict.factory(**p.as_stanza().as_dict())
144
self.assertEqual(o, p)
146
self.assertIsInstance(o.path, text_type)
148
if o.file_id is not None:
149
self.assertIsInstance(o.file_id, bytes)
151
conflict_path = getattr(o, 'conflict_path', None)
152
if conflict_path is not None:
153
self.assertIsInstance(conflict_path, text_type)
155
conflict_file_id = getattr(o, 'conflict_file_id', None)
156
if conflict_file_id is not None:
157
self.assertIsInstance(conflict_file_id, bytes)
186
159
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')
160
stanza = self.conflict.as_stanza()
161
if 'file_id' in stanza:
162
# In Stanza form, the file_id has to be unicode.
163
self.assertStartsWith(stanza['file_id'], u'\xeed')
164
self.assertStartsWith(stanza['path'], u'p\xe5th')
165
if 'conflict_path' in stanza:
166
self.assertStartsWith(stanza['conflict_path'], u'p\xe5th')
167
if 'conflict_file_id' in stanza:
168
self.assertStartsWith(stanza['conflict_file_id'], u'\xeed')
171
class TestConflictList(tests.TestCase):
173
def test_stanzas_roundtrip(self):
174
stanzas_iter = example_conflicts.to_stanzas()
175
processed = conflicts.ConflictList.from_stanzas(stanzas_iter)
176
self.assertEqual(example_conflicts, processed)
178
def test_stringification(self):
179
for text, o in zip(example_conflicts.to_strings(), example_conflicts):
180
self.assertEqual(text, text_type(o))
198
183
# 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
277
"""The scenario list for the conflict type defined by the class.
279
Each scenario is of the form:
280
(common, (left_name, left_dict), (right_name, right_dict))
284
* left_name and right_name are the scenario names that will be combined
286
* left_dict and right_dict are the attributes specific to each half of
287
the scenario. They should include at least 'actions' and 'check' and
288
will be available as '_this' and '_other' test instance attributes.
290
Daughters classes are free to add their specific attributes as they see
291
fit in any of the three dicts.
293
This is a class method so that load_tests can find it.
295
'_base_actions' in the common dict, 'actions' and 'check' in the left
296
and right dicts use names that map to methods in the test classes. Some
297
prefixes are added to these names to get the correspong methods (see
298
_get_actions() and _get_check()). The motivation here is to avoid
299
collisions in the class namespace.
326
303
super(TestParametrizedResolveConflicts, self).setUp()
328
305
builder.start_series()
330
307
# Create an empty trunk
331
builder.build_snapshot('start', None, [
332
('add', ('', 'root-id', 'directory', ''))])
308
builder.build_snapshot(None, [
309
('add', (u'', b'root-id', 'directory', ''))],
310
revision_id=b'start')
333
311
# Add a minimal base content
334
312
base_actions = self._get_actions(self._base_actions)()
335
builder.build_snapshot('base', ['start'], base_actions)
313
builder.build_snapshot([b'start'], base_actions, revision_id=b'base')
336
314
# Modify the base content in branch
337
315
actions_other = self._get_actions(self._other['actions'])()
338
builder.build_snapshot('other', ['base'], actions_other)
316
builder.build_snapshot([b'base'], actions_other, revision_id=b'other')
339
317
# Modify the base content in trunk
340
318
actions_this = self._get_actions(self._this['actions'])()
341
builder.build_snapshot('this', ['base'], actions_this)
319
builder.build_snapshot([b'base'], actions_this, revision_id=b'this')
342
320
# builder.get_branch() tip is now 'this'
344
322
builder.finish_series()
369
class TestResolveTextConflicts(TestParametrizedResolveConflicts):
371
_conflict_type = conflicts.TextConflict
373
# Set by the scenarios
374
# path and file-id for the file involved in the conflict
378
scenarios = mirror_scenarios(
380
# File modified on both sides
381
(dict(_base_actions='create_file',
382
_path='file', _file_id=b'file-id'),
384
dict(actions='modify_file_A', check='file_has_content_A')),
386
dict(actions='modify_file_B', check='file_has_content_B')),),
387
# File modified on both sides in dir
388
(dict(_base_actions='create_file_in_dir',
389
_path='dir/file', _file_id=b'file-id'),
390
('filed_modified_A_in_dir',
391
dict(actions='modify_file_A_in_dir',
392
check='file_in_dir_has_content_A')),
394
dict(actions='modify_file_B_in_dir',
395
check='file_in_dir_has_content_B')),),
398
def do_create_file(self, path='file'):
399
return [('add', (path, b'file-id', 'file', b'trunk content\n'))]
401
def do_modify_file_A(self):
402
return [('modify', ('file', b'trunk content\nfeature A\n'))]
404
def do_modify_file_B(self):
405
return [('modify', ('file', b'trunk content\nfeature B\n'))]
407
def do_modify_file_A_in_dir(self):
408
return [('modify', ('dir/file', b'trunk content\nfeature A\n'))]
410
def do_modify_file_B_in_dir(self):
411
return [('modify', ('dir/file', b'trunk content\nfeature B\n'))]
413
def check_file_has_content_A(self, path='file'):
414
self.assertFileEqual(b'trunk content\nfeature A\n',
415
osutils.pathjoin('branch', path))
417
def check_file_has_content_B(self, path='file'):
418
self.assertFileEqual(b'trunk content\nfeature B\n',
419
osutils.pathjoin('branch', path))
421
def do_create_file_in_dir(self):
422
return [('add', ('dir', b'dir-id', 'directory', '')),
423
] + self.do_create_file('dir/file')
425
def check_file_in_dir_has_content_A(self):
426
self.check_file_has_content_A('dir/file')
428
def check_file_in_dir_has_content_B(self):
429
self.check_file_has_content_B('dir/file')
431
def _get_resolve_path_arg(self, wt, action):
434
def assertTextConflict(self, wt, c):
435
self.assertEqual(self._file_id, c.file_id)
436
self.assertEqual(self._path, c.path)
437
_assert_conflict = assertTextConflict
391
440
class TestResolveContentsConflict(TestParametrizedResolveConflicts):
393
_conflict_type = conflicts.ContentsConflict,
442
_conflict_type = conflicts.ContentsConflict
395
# Set by load_tests from scenarios()
444
# Set by the scenarios
396
445
# path and file-id for the file involved in the conflict
449
scenarios = mirror_scenarios(
403
451
# File modified/deleted
404
452
(dict(_base_actions='create_file',
405
_path='file', _file_id='file-id'),
453
_path='file', _file_id=b'file-id'),
406
454
('file_modified',
407
455
dict(actions='modify_file', check='file_has_more_content')),
409
457
dict(actions='delete_file', check='file_doesnt_exist')),),
411
return mirror_scenarios(base_scenarios)
458
# File renamed-modified/deleted
459
(dict(_base_actions='create_file',
460
_path='new-file', _file_id=b'file-id'),
461
('file_renamed_and_modified',
462
dict(actions='modify_and_rename_file',
463
check='file_renamed_and_more_content')),
465
dict(actions='delete_file', check='file_doesnt_exist')),),
466
# File modified/deleted in dir
467
(dict(_base_actions='create_file_in_dir',
468
_path='dir/file', _file_id=b'file-id'),
469
('file_modified_in_dir',
470
dict(actions='modify_file_in_dir',
471
check='file_in_dir_has_more_content')),
472
('file_deleted_in_dir',
473
dict(actions='delete_file_in_dir',
474
check='file_in_dir_doesnt_exist')),),
413
477
def do_create_file(self):
414
return [('add', ('file', 'file-id', 'file', 'trunk content\n'))]
478
return [('add', ('file', b'file-id', 'file', b'trunk content\n'))]
416
480
def do_modify_file(self):
417
return [('modify', ('file-id', 'trunk content\nmore content\n'))]
481
return [('modify', ('file', b'trunk content\nmore content\n'))]
483
def do_modify_and_rename_file(self):
484
return [('modify', ('new-file', b'trunk content\nmore content\n')),
485
('rename', ('file', 'new-file'))]
419
487
def check_file_has_more_content(self):
420
self.assertFileEqual('trunk content\nmore content\n', 'branch/file')
488
self.assertFileEqual(b'trunk content\nmore content\n', 'branch/file')
490
def check_file_renamed_and_more_content(self):
491
self.assertFileEqual(
492
b'trunk content\nmore content\n', 'branch/new-file')
422
494
def do_delete_file(self):
423
return [('unversion', 'file-id')]
495
return [('unversion', 'file')]
497
def do_delete_file_in_dir(self):
498
return [('unversion', 'dir/file')]
425
500
def check_file_doesnt_exist(self):
426
self.failIfExists('branch/file')
501
self.assertPathDoesNotExist('branch/file')
503
def do_create_file_in_dir(self):
504
return [('add', ('dir', b'dir-id', 'directory', '')),
505
('add', ('dir/file', b'file-id', 'file', b'trunk content\n'))]
507
def do_modify_file_in_dir(self):
508
return [('modify', ('dir/file', b'trunk content\nmore content\n'))]
510
def check_file_in_dir_has_more_content(self):
511
self.assertFileEqual(
512
b'trunk content\nmore content\n', 'branch/dir/file')
514
def check_file_in_dir_doesnt_exist(self):
515
self.assertPathDoesNotExist('branch/dir/file')
428
517
def _get_resolve_path_arg(self, wt, action):
429
518
return self._path
437
526
class TestResolvePathConflict(TestParametrizedResolveConflicts):
439
_conflict_type = conflicts.PathConflict,
528
_conflict_type = conflicts.PathConflict
441
530
def do_nothing(self):
446
# Each side dict additionally defines:
447
# - path path involved (can be '<deleted>')
533
# Each side dict additionally defines:
534
# - path path involved (can be '<deleted>')
536
scenarios = mirror_scenarios(
450
538
# File renamed/deleted
451
539
(dict(_base_actions='create_file'),
453
541
dict(actions='rename_file', check='file_renamed',
454
path='new-file', file_id='file-id')),
542
path='new-file', file_id=b'file-id')),
456
544
dict(actions='delete_file', check='file_doesnt_exist',
457
545
# PathConflicts deletion handling requires a special
458
546
# hard-coded value
459
path='<deleted>', file_id='file-id')),),
547
path='<deleted>', file_id=b'file-id')),),
548
# File renamed/deleted in dir
549
(dict(_base_actions='create_file_in_dir'),
550
('file_renamed_in_dir',
551
dict(actions='rename_file_in_dir', check='file_in_dir_renamed',
552
path='dir/new-file', file_id=b'file-id')),
554
dict(actions='delete_file_in_dir', check='file_in_dir_doesnt_exist',
555
# PathConflicts deletion handling requires a special
557
path='<deleted>', file_id=b'file-id')),),
460
558
# File renamed/renamed differently
461
559
(dict(_base_actions='create_file'),
463
561
dict(actions='rename_file', check='file_renamed',
464
path='new-file', file_id='file-id')),
562
path='new-file', file_id=b'file-id')),
465
563
('file_renamed2',
466
564
dict(actions='rename_file2', check='file_renamed2',
467
path='new-file2', file_id='file-id')),),
565
path='new-file2', file_id=b'file-id')),),
468
566
# Dir renamed/deleted
469
567
(dict(_base_actions='create_dir'),
471
569
dict(actions='rename_dir', check='dir_renamed',
472
path='new-dir', file_id='dir-id')),
570
path='new-dir', file_id=b'dir-id')),
474
572
dict(actions='delete_dir', check='dir_doesnt_exist',
475
573
# PathConflicts deletion handling requires a special
476
574
# hard-coded value
477
path='<deleted>', file_id='dir-id')),),
575
path='<deleted>', file_id=b'dir-id')),),
478
576
# Dir renamed/renamed differently
479
577
(dict(_base_actions='create_dir'),
481
579
dict(actions='rename_dir', check='dir_renamed',
482
path='new-dir', file_id='dir-id')),
580
path='new-dir', file_id=b'dir-id')),
484
582
dict(actions='rename_dir2', check='dir_renamed2',
485
path='new-dir2', file_id='dir-id')),),
487
return mirror_scenarios(base_scenarios)
583
path='new-dir2', file_id=b'dir-id')),),
489
586
def do_create_file(self):
490
return [('add', ('file', 'file-id', 'file', 'trunk content\n'))]
587
return [('add', ('file', b'file-id', 'file', b'trunk content\n'))]
492
589
def do_create_dir(self):
493
return [('add', ('dir', 'dir-id', 'directory', ''))]
590
return [('add', ('dir', b'dir-id', 'directory', ''))]
495
592
def do_rename_file(self):
496
593
return [('rename', ('file', 'new-file'))]
498
595
def check_file_renamed(self):
499
self.failIfExists('branch/file')
500
self.failUnlessExists('branch/new-file')
596
self.assertPathDoesNotExist('branch/file')
597
self.assertPathExists('branch/new-file')
502
599
def do_rename_file2(self):
503
600
return [('rename', ('file', 'new-file2'))]
505
602
def check_file_renamed2(self):
506
self.failIfExists('branch/file')
507
self.failUnlessExists('branch/new-file2')
603
self.assertPathDoesNotExist('branch/file')
604
self.assertPathExists('branch/new-file2')
509
606
def do_rename_dir(self):
510
607
return [('rename', ('dir', 'new-dir'))]
512
609
def check_dir_renamed(self):
513
self.failIfExists('branch/dir')
514
self.failUnlessExists('branch/new-dir')
610
self.assertPathDoesNotExist('branch/dir')
611
self.assertPathExists('branch/new-dir')
516
613
def do_rename_dir2(self):
517
614
return [('rename', ('dir', 'new-dir2'))]
519
616
def check_dir_renamed2(self):
520
self.failIfExists('branch/dir')
521
self.failUnlessExists('branch/new-dir2')
617
self.assertPathDoesNotExist('branch/dir')
618
self.assertPathExists('branch/new-dir2')
523
620
def do_delete_file(self):
524
return [('unversion', 'file-id')]
621
return [('unversion', 'file')]
623
def do_delete_file_in_dir(self):
624
return [('unversion', 'dir/file')]
526
626
def check_file_doesnt_exist(self):
527
self.failIfExists('branch/file')
627
self.assertPathDoesNotExist('branch/file')
529
629
def do_delete_dir(self):
530
return [('unversion', 'dir-id')]
630
return [('unversion', 'dir')]
532
632
def check_dir_doesnt_exist(self):
533
self.failIfExists('branch/dir')
633
self.assertPathDoesNotExist('branch/dir')
635
def do_create_file_in_dir(self):
636
return [('add', ('dir', b'dir-id', 'directory', '')),
637
('add', ('dir/file', b'file-id', 'file', b'trunk content\n'))]
639
def do_rename_file_in_dir(self):
640
return [('rename', ('dir/file', 'dir/new-file'))]
642
def check_file_in_dir_renamed(self):
643
self.assertPathDoesNotExist('branch/dir/file')
644
self.assertPathExists('branch/dir/new-file')
646
def check_file_in_dir_doesnt_exist(self):
647
self.assertPathDoesNotExist('branch/dir/file')
535
649
def _get_resolve_path_arg(self, wt, action):
536
650
tpath = self._this['path']
569
683
class TestResolveDuplicateEntry(TestParametrizedResolveConflicts):
571
_conflict_type = conflicts.DuplicateEntry,
685
_conflict_type = conflicts.DuplicateEntry
575
# Each side dict additionally defines:
687
scenarios = mirror_scenarios(
579
689
# File created with different file-ids
580
690
(dict(_base_actions='nothing'),
581
691
('filea_created',
582
692
dict(actions='create_file_a', check='file_content_a',
583
path='file', file_id='file-a-id')),
693
path='file', file_id=b'file-a-id')),
584
694
('fileb_created',
585
695
dict(actions='create_file_b', check='file_content_b',
586
path='file', file_id='file-b-id')),),
588
return mirror_scenarios(base_scenarios)
696
path='file', file_id=b'file-b-id')),),
697
# File created with different file-ids but deleted on one side
698
(dict(_base_actions='create_file_a'),
700
dict(actions='replace_file_a_by_b', check='file_content_b',
701
path='file', file_id=b'file-b-id')),
703
dict(actions='modify_file_a', check='file_new_content',
704
path='file', file_id=b'file-a-id')),),
590
707
def do_nothing(self):
593
710
def do_create_file_a(self):
594
return [('add', ('file', 'file-a-id', 'file', 'file a content\n'))]
711
return [('add', ('file', b'file-a-id', 'file', b'file a content\n'))]
596
713
def check_file_content_a(self):
597
self.assertFileEqual('file a content\n', 'branch/file')
714
self.assertFileEqual(b'file a content\n', 'branch/file')
599
716
def do_create_file_b(self):
600
return [('add', ('file', 'file-b-id', 'file', 'file b content\n'))]
717
return [('add', ('file', b'file-b-id', 'file', b'file b content\n'))]
602
719
def check_file_content_b(self):
603
self.assertFileEqual('file b content\n', 'branch/file')
720
self.assertFileEqual(b'file b content\n', 'branch/file')
722
def do_replace_file_a_by_b(self):
723
return [('unversion', 'file'),
724
('add', ('file', b'file-b-id', 'file', b'file b content\n'))]
726
def do_modify_file_a(self):
727
return [('modify', ('file', b'new content\n'))]
729
def check_file_new_content(self):
730
self.assertFileEqual(b'new content\n', 'branch/file')
605
732
def _get_resolve_path_arg(self, wt, action):
606
733
return self._this['path']
692
817
def test_keep_them_all(self):
693
818
self.run_script("""
695
$ bzr commit --strict -m 'No more conflicts nor unknown files'
820
2>2 conflicts resolved, 0 remaining
821
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
698
824
def test_adopt_child(self):
699
825
self.run_script("""
700
$ bzr mv dir/file2 file2
703
$ bzr commit --strict -m 'No more conflicts nor unknown files'
826
$ brz mv -q dir/file2 file2
827
$ brz rm -q dir --no-backup
829
2>2 conflicts resolved, 0 remaining
830
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
706
833
def test_kill_them_all(self):
707
834
self.run_script("""
710
$ bzr commit --strict -m 'No more conflicts nor unknown files'
835
$ brz rm -q dir --no-backup
837
2>2 conflicts resolved, 0 remaining
838
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
713
841
def test_resolve_taking_this(self):
714
842
self.run_script("""
715
$ bzr resolve --take-this dir
716
$ bzr commit --strict -m 'No more conflicts nor unknown files'
843
$ brz resolve --take-this dir
845
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
719
848
def test_resolve_taking_other(self):
720
849
self.run_script("""
721
$ bzr resolve --take-other dir
722
$ bzr commit --strict -m 'No more conflicts nor unknown files'
850
$ brz resolve --take-other dir
852
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
726
856
class TestResolveDeletingParent(TestResolveConflicts):
732
863
$ 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
865
$ brz commit -m 'Create trunk' -q
866
$ brz rm -q dir/file --no-backup
867
$ brz rm -q dir --no-backup
868
$ brz commit -q -m 'Remove dir/file'
869
$ brz branch -q . -r 1 ../branch
742
871
$ echo 'branch content' >dir/file2
744
$ bzr commit -m 'Add dir/file2 in branch'
872
$ brz add -q dir/file2
873
$ brz commit -q -m 'Add dir/file2 in branch'
748
876
2>Conflict: can't delete dir because it is not empty. Not deleting.
749
877
2>Conflict because dir is not versioned, but has versioned children. Versioned directory.
753
881
def test_keep_them_all(self):
754
882
self.run_script("""
756
$ bzr commit --strict -m 'No more conflicts nor unknown files'
884
2>2 conflicts resolved, 0 remaining
885
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
759
888
def test_adopt_child(self):
760
889
self.run_script("""
761
$ bzr mv dir/file2 file2
764
$ bzr commit --strict -m 'No more conflicts nor unknown files'
890
$ brz mv -q dir/file2 file2
891
$ brz rm -q dir --no-backup
893
2>2 conflicts resolved, 0 remaining
894
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
767
897
def test_kill_them_all(self):
768
898
self.run_script("""
771
$ bzr commit --strict -m 'No more conflicts nor unknown files'
899
$ brz rm -q dir --no-backup
901
2>2 conflicts resolved, 0 remaining
902
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
774
905
def test_resolve_taking_this(self):
775
906
self.run_script("""
776
$ bzr resolve --take-this dir
777
$ bzr commit --strict -m 'No more conflicts nor unknown files'
907
$ brz resolve --take-this dir
908
2>2 conflicts resolved, 0 remaining
909
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
780
912
def test_resolve_taking_other(self):
781
913
self.run_script("""
782
$ bzr resolve --take-other dir
783
$ bzr commit --strict -m 'No more conflicts nor unknown files'
914
$ brz resolve --take-other dir
917
2>2 conflicts resolved, 0 remaining
918
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
787
922
class TestResolveParentLoop(TestParametrizedResolveConflicts):
789
_conflict_type = conflicts.ParentLoop,
924
_conflict_type = conflicts.ParentLoop
791
926
_this_args = None
792
927
_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'
929
# Each side dict additionally defines:
930
# - dir_id: the directory being moved
931
# - target_id: The target directory
932
# - xfail: whether the test is expected to fail if the action is
933
# involved as 'other'
934
scenarios = mirror_scenarios(
802
936
# Dirs moved into each other
803
937
(dict(_base_actions='create_dir1_dir2'),
804
938
('dir1_into_dir2',
805
939
dict(actions='move_dir1_into_dir2', check='dir1_moved',
806
dir_id='dir1-id', target_id='dir2-id', xfail=False)),
940
dir_id=b'dir1-id', target_id=b'dir2-id', xfail=False)),
807
941
('dir2_into_dir1',
808
942
dict(actions='move_dir2_into_dir1', check='dir2_moved',
809
dir_id='dir2-id', target_id='dir1-id', xfail=False))),
943
dir_id=b'dir2-id', target_id=b'dir1-id', xfail=False))),
810
944
# Subdirs moved into each other
811
945
(dict(_base_actions='create_dir1_4'),
812
946
('dir1_into_dir4',
813
947
dict(actions='move_dir1_into_dir4', check='dir1_2_moved',
814
dir_id='dir1-id', target_id='dir4-id', xfail=True)),
948
dir_id=b'dir1-id', target_id=b'dir4-id', xfail=True)),
815
949
('dir3_into_dir2',
816
950
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)
951
dir_id=b'dir3-id', target_id=b'dir2-id', xfail=True))),
821
954
def do_create_dir1_dir2(self):
822
return [('add', ('dir1', 'dir1-id', 'directory', '')),
823
('add', ('dir2', 'dir2-id', 'directory', '')),]
955
return [('add', ('dir1', b'dir1-id', 'directory', '')),
956
('add', ('dir2', b'dir2-id', 'directory', '')), ]
825
958
def do_move_dir1_into_dir2(self):
826
959
return [('rename', ('dir1', 'dir2/dir1'))]
828
961
def check_dir1_moved(self):
829
self.failIfExists('branch/dir1')
830
self.failUnlessExists('branch/dir2/dir1')
962
self.assertPathDoesNotExist('branch/dir1')
963
self.assertPathExists('branch/dir2/dir1')
832
965
def do_move_dir2_into_dir1(self):
833
966
return [('rename', ('dir2', 'dir1/dir2'))]
835
968
def check_dir2_moved(self):
836
self.failIfExists('branch/dir2')
837
self.failUnlessExists('branch/dir1/dir2')
969
self.assertPathDoesNotExist('branch/dir2')
970
self.assertPathExists('branch/dir1/dir2')
839
972
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', '')),]
973
return [('add', ('dir1', b'dir1-id', 'directory', '')),
974
('add', ('dir1/dir2', b'dir2-id', 'directory', '')),
975
('add', ('dir3', b'dir3-id', 'directory', '')),
976
('add', ('dir3/dir4', b'dir4-id', 'directory', '')), ]
845
978
def do_move_dir1_into_dir4(self):
846
979
return [('rename', ('dir1', 'dir3/dir4/dir1'))]
848
981
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')
982
self.assertPathDoesNotExist('branch/dir1')
983
self.assertPathExists('branch/dir3/dir4/dir1')
984
self.assertPathExists('branch/dir3/dir4/dir1/dir2')
853
986
def do_move_dir3_into_dir2(self):
854
987
return [('rename', ('dir3', 'dir1/dir2/dir3'))]
856
989
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')
990
self.assertPathDoesNotExist('branch/dir3')
991
self.assertPathExists('branch/dir1/dir2/dir3')
992
self.assertPathExists('branch/dir1/dir2/dir3/dir4')
861
994
def _get_resolve_path_arg(self, wt, action):
862
995
# ParentLoop says: moving <conflict_path> into <path>. Cancelled move.
941
1078
# This is nearly like TestResolveNonDirectoryParent but with branch and
942
1079
# trunk switched. As such it should certainly produce the same
1081
self.assertRaises(transform.MalformedTransform,
1082
self.run_script, """
948
$ bzr commit -m 'Create trunk'
1088
$ brz commit -m 'Create trunk' -q
950
1090
$ echo "Boo!" >foo
951
$ bzr commit -m 'foo is now a file'
953
$ bzr branch . -r 1 ../branch
1091
$ brz commit -m 'foo is now a file' -q
1092
$ brz branch -q . -r 1 ../branch -q
955
1094
$ echo "Boing" >foo/bar
957
$ bzr commit -m 'Add foo/bar'
960
2>bzr: ERROR: Tree transform is malformed [('unversioned executability', 'new-1')]
1095
$ brz add -q foo/bar -q
1096
$ brz commit -m 'Add foo/bar' -q
1097
$ brz merge ../trunk
1098
2>brz: ERROR: Tree transform is malformed [('unversioned executability', 'new-1')]
1102
class TestNoFinalPath(script.TestCaseWithTransportAndScript):
1104
def test_bug_805809(self):
1107
Created a standalone tree (format: 2a)
1112
$ brz commit -m 'create file on trunk'
1113
2>Committing to: .../trunk/
1115
2>Committed revision 1.
1116
# Create a debian branch based on trunk
1118
$ brz branch trunk -r 1 debian
1119
2>Branched 1 revision.
1126
$ brz commit -m 'rename file to dir/file for debian'
1127
2>Committing to: .../debian/
1129
2>renamed file => dir/file
1130
2>Committed revision 2.
1131
# Create an experimental branch with a new root-id
1133
$ brz init experimental
1134
Created a standalone tree (format: 2a)
1136
# Work around merging into empty branch not being supported
1137
# (http://pad.lv/308562)
1138
$ echo something >not-empty
1141
$ brz commit -m 'Add some content in experimental'
1142
2>Committing to: .../experimental/
1144
2>Committed revision 1.
1145
# merge debian even without a common ancestor
1146
$ brz merge ../debian -r0..2
1149
2>All changes applied successfully.
1150
$ brz commit -m 'merging debian into experimental'
1151
2>Committing to: .../experimental/
1154
2>Committed revision 2.
1155
# Create an ubuntu branch with yet another root-id
1158
Created a standalone tree (format: 2a)
1160
# Work around merging into empty branch not being supported
1161
# (http://pad.lv/308562)
1162
$ echo something >not-empty-ubuntu
1164
adding not-empty-ubuntu
1165
$ brz commit -m 'Add some content in experimental'
1166
2>Committing to: .../ubuntu/
1167
2>added not-empty-ubuntu
1168
2>Committed revision 1.
1170
$ brz merge ../debian -r0..2
1173
2>All changes applied successfully.
1174
$ brz commit -m 'merging debian'
1175
2>Committing to: .../ubuntu/
1178
2>Committed revision 2.
1179
# Now try to merge experimental
1180
$ brz merge ../experimental
1182
2>Path conflict: dir / dir
1183
2>1 conflicts encountered.