57
42
# '\xc3\xae' == u'\xee' == i with hat
58
43
# So these are u'path' and 'id' only with a circle and a hat. (shappo?)
59
44
example_conflicts = conflicts.ConflictList(
60
[conflicts.MissingParent('Not deleting', u'p\xe5thg', '\xc3\xaedg'),
61
conflicts.ContentsConflict(u'p\xe5tha', None, '\xc3\xaeda'),
45
[conflicts.MissingParent('Not deleting', u'p\xe5thg', b'\xc3\xaedg'),
46
conflicts.ContentsConflict(u'p\xe5tha', None, b'\xc3\xaeda'),
62
47
conflicts.TextConflict(u'p\xe5tha'),
63
conflicts.PathConflict(u'p\xe5thb', u'p\xe5thc', '\xc3\xaedb'),
48
conflicts.PathConflict(u'p\xe5thb', u'p\xe5thc', b'\xc3\xaedb'),
64
49
conflicts.DuplicateID('Unversioned existing file',
65
50
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'),
51
b'\xc3\xaedc', b'\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',
56
None, b'\xc3\xaed2e'),
57
conflicts.UnversionedParent('Versioned directory',
58
u'p\xe5thf', b'\xc3\xaedf'),
59
conflicts.NonDirectoryParent('Created directory',
60
u'p\xe5thg', b'\xc3\xaedg'),
64
def vary_by_conflicts():
65
for conflict in example_conflicts:
66
yield (conflict.__class__.__name__, {"conflict": conflict})
79
69
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
71
def test_resolve_conflict_dir(self):
109
72
tree = self.make_branch_and_tree('.')
110
self.build_tree_contents([('hello', 'hello world4'),
111
('hello.THIS', 'hello world2'),
112
('hello.BASE', 'hello world1'),
73
self.build_tree_contents([('hello', b'hello world4'),
74
('hello.THIS', b'hello world2'),
75
('hello.BASE', b'hello world1'),
114
77
os.mkdir('hello.OTHER')
115
tree.add('hello', 'q')
78
tree.add('hello', b'q')
116
79
l = conflicts.ConflictList([conflicts.TextConflict('hello')])
117
80
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 = str(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, str)
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, str)
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, str(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(
490
b'trunk content\nmore content\n', 'branch/new-file')
422
492
def do_delete_file(self):
423
return [('unversion', 'file-id')]
493
return [('unversion', 'file')]
495
def do_delete_file_in_dir(self):
496
return [('unversion', 'dir/file')]
425
498
def check_file_doesnt_exist(self):
426
self.failIfExists('branch/file')
499
self.assertPathDoesNotExist('branch/file')
501
def do_create_file_in_dir(self):
502
return [('add', ('dir', b'dir-id', 'directory', '')),
503
('add', ('dir/file', b'file-id', 'file', b'trunk content\n'))]
505
def do_modify_file_in_dir(self):
506
return [('modify', ('dir/file', b'trunk content\nmore content\n'))]
508
def check_file_in_dir_has_more_content(self):
509
self.assertFileEqual(
510
b'trunk content\nmore content\n', 'branch/dir/file')
512
def check_file_in_dir_doesnt_exist(self):
513
self.assertPathDoesNotExist('branch/dir/file')
428
515
def _get_resolve_path_arg(self, wt, action):
429
516
return self._path
437
524
class TestResolvePathConflict(TestParametrizedResolveConflicts):
439
_conflict_type = conflicts.PathConflict,
526
_conflict_type = conflicts.PathConflict
441
528
def do_nothing(self):
446
# Each side dict additionally defines:
447
# - path path involved (can be '<deleted>')
531
# Each side dict additionally defines:
532
# - path path involved (can be '<deleted>')
534
scenarios = mirror_scenarios(
450
536
# File renamed/deleted
451
537
(dict(_base_actions='create_file'),
453
539
dict(actions='rename_file', check='file_renamed',
454
path='new-file', file_id='file-id')),
540
path='new-file', file_id=b'file-id')),
456
542
dict(actions='delete_file', check='file_doesnt_exist',
457
543
# PathConflicts deletion handling requires a special
458
544
# hard-coded value
459
path='<deleted>', file_id='file-id')),),
545
path='<deleted>', file_id=b'file-id')),),
546
# File renamed/deleted in dir
547
(dict(_base_actions='create_file_in_dir'),
548
('file_renamed_in_dir',
549
dict(actions='rename_file_in_dir', check='file_in_dir_renamed',
550
path='dir/new-file', file_id=b'file-id')),
552
dict(actions='delete_file_in_dir', check='file_in_dir_doesnt_exist',
553
# PathConflicts deletion handling requires a special
555
path='<deleted>', file_id=b'file-id')),),
460
556
# File renamed/renamed differently
461
557
(dict(_base_actions='create_file'),
463
559
dict(actions='rename_file', check='file_renamed',
464
path='new-file', file_id='file-id')),
560
path='new-file', file_id=b'file-id')),
465
561
('file_renamed2',
466
562
dict(actions='rename_file2', check='file_renamed2',
467
path='new-file2', file_id='file-id')),),
563
path='new-file2', file_id=b'file-id')),),
468
564
# Dir renamed/deleted
469
565
(dict(_base_actions='create_dir'),
471
567
dict(actions='rename_dir', check='dir_renamed',
472
path='new-dir', file_id='dir-id')),
568
path='new-dir', file_id=b'dir-id')),
474
570
dict(actions='delete_dir', check='dir_doesnt_exist',
475
571
# PathConflicts deletion handling requires a special
476
572
# hard-coded value
477
path='<deleted>', file_id='dir-id')),),
573
path='<deleted>', file_id=b'dir-id')),),
478
574
# Dir renamed/renamed differently
479
575
(dict(_base_actions='create_dir'),
481
577
dict(actions='rename_dir', check='dir_renamed',
482
path='new-dir', file_id='dir-id')),
578
path='new-dir', file_id=b'dir-id')),
484
580
dict(actions='rename_dir2', check='dir_renamed2',
485
path='new-dir2', file_id='dir-id')),),
487
return mirror_scenarios(base_scenarios)
581
path='new-dir2', file_id=b'dir-id')),),
489
584
def do_create_file(self):
490
return [('add', ('file', 'file-id', 'file', 'trunk content\n'))]
585
return [('add', ('file', b'file-id', 'file', b'trunk content\n'))]
492
587
def do_create_dir(self):
493
return [('add', ('dir', 'dir-id', 'directory', ''))]
588
return [('add', ('dir', b'dir-id', 'directory', ''))]
495
590
def do_rename_file(self):
496
591
return [('rename', ('file', 'new-file'))]
498
593
def check_file_renamed(self):
499
self.failIfExists('branch/file')
500
self.failUnlessExists('branch/new-file')
594
self.assertPathDoesNotExist('branch/file')
595
self.assertPathExists('branch/new-file')
502
597
def do_rename_file2(self):
503
598
return [('rename', ('file', 'new-file2'))]
505
600
def check_file_renamed2(self):
506
self.failIfExists('branch/file')
507
self.failUnlessExists('branch/new-file2')
601
self.assertPathDoesNotExist('branch/file')
602
self.assertPathExists('branch/new-file2')
509
604
def do_rename_dir(self):
510
605
return [('rename', ('dir', 'new-dir'))]
512
607
def check_dir_renamed(self):
513
self.failIfExists('branch/dir')
514
self.failUnlessExists('branch/new-dir')
608
self.assertPathDoesNotExist('branch/dir')
609
self.assertPathExists('branch/new-dir')
516
611
def do_rename_dir2(self):
517
612
return [('rename', ('dir', 'new-dir2'))]
519
614
def check_dir_renamed2(self):
520
self.failIfExists('branch/dir')
521
self.failUnlessExists('branch/new-dir2')
615
self.assertPathDoesNotExist('branch/dir')
616
self.assertPathExists('branch/new-dir2')
523
618
def do_delete_file(self):
524
return [('unversion', 'file-id')]
619
return [('unversion', 'file')]
621
def do_delete_file_in_dir(self):
622
return [('unversion', 'dir/file')]
526
624
def check_file_doesnt_exist(self):
527
self.failIfExists('branch/file')
625
self.assertPathDoesNotExist('branch/file')
529
627
def do_delete_dir(self):
530
return [('unversion', 'dir-id')]
628
return [('unversion', 'dir')]
532
630
def check_dir_doesnt_exist(self):
533
self.failIfExists('branch/dir')
631
self.assertPathDoesNotExist('branch/dir')
633
def do_create_file_in_dir(self):
634
return [('add', ('dir', b'dir-id', 'directory', '')),
635
('add', ('dir/file', b'file-id', 'file', b'trunk content\n'))]
637
def do_rename_file_in_dir(self):
638
return [('rename', ('dir/file', 'dir/new-file'))]
640
def check_file_in_dir_renamed(self):
641
self.assertPathDoesNotExist('branch/dir/file')
642
self.assertPathExists('branch/dir/new-file')
644
def check_file_in_dir_doesnt_exist(self):
645
self.assertPathDoesNotExist('branch/dir/file')
535
647
def _get_resolve_path_arg(self, wt, action):
536
648
tpath = self._this['path']
569
681
class TestResolveDuplicateEntry(TestParametrizedResolveConflicts):
571
_conflict_type = conflicts.DuplicateEntry,
683
_conflict_type = conflicts.DuplicateEntry
575
# Each side dict additionally defines:
685
scenarios = mirror_scenarios(
579
687
# File created with different file-ids
580
688
(dict(_base_actions='nothing'),
581
689
('filea_created',
582
690
dict(actions='create_file_a', check='file_content_a',
583
path='file', file_id='file-a-id')),
691
path='file', file_id=b'file-a-id')),
584
692
('fileb_created',
585
693
dict(actions='create_file_b', check='file_content_b',
586
path='file', file_id='file-b-id')),),
588
return mirror_scenarios(base_scenarios)
694
path='file', file_id=b'file-b-id')),),
695
# File created with different file-ids but deleted on one side
696
(dict(_base_actions='create_file_a'),
698
dict(actions='replace_file_a_by_b', check='file_content_b',
699
path='file', file_id=b'file-b-id')),
701
dict(actions='modify_file_a', check='file_new_content',
702
path='file', file_id=b'file-a-id')),),
590
705
def do_nothing(self):
593
708
def do_create_file_a(self):
594
return [('add', ('file', 'file-a-id', 'file', 'file a content\n'))]
709
return [('add', ('file', b'file-a-id', 'file', b'file a content\n'))]
596
711
def check_file_content_a(self):
597
self.assertFileEqual('file a content\n', 'branch/file')
712
self.assertFileEqual(b'file a content\n', 'branch/file')
599
714
def do_create_file_b(self):
600
return [('add', ('file', 'file-b-id', 'file', 'file b content\n'))]
715
return [('add', ('file', b'file-b-id', 'file', b'file b content\n'))]
602
717
def check_file_content_b(self):
603
self.assertFileEqual('file b content\n', 'branch/file')
718
self.assertFileEqual(b'file b content\n', 'branch/file')
720
def do_replace_file_a_by_b(self):
721
return [('unversion', 'file'),
722
('add', ('file', b'file-b-id', 'file', b'file b content\n'))]
724
def do_modify_file_a(self):
725
return [('modify', ('file', b'new content\n'))]
727
def check_file_new_content(self):
728
self.assertFileEqual(b'new content\n', 'branch/file')
605
730
def _get_resolve_path_arg(self, wt, action):
606
731
return self._this['path']
692
815
def test_keep_them_all(self):
693
816
self.run_script("""
695
$ bzr commit --strict -m 'No more conflicts nor unknown files'
818
2>2 conflicts resolved, 0 remaining
819
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
698
822
def test_adopt_child(self):
699
823
self.run_script("""
700
$ bzr mv dir/file2 file2
703
$ bzr commit --strict -m 'No more conflicts nor unknown files'
824
$ brz mv -q dir/file2 file2
825
$ brz rm -q dir --no-backup
827
2>2 conflicts resolved, 0 remaining
828
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
706
831
def test_kill_them_all(self):
707
832
self.run_script("""
710
$ bzr commit --strict -m 'No more conflicts nor unknown files'
833
$ brz rm -q dir --no-backup
835
2>2 conflicts resolved, 0 remaining
836
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
713
839
def test_resolve_taking_this(self):
714
840
self.run_script("""
715
$ bzr resolve --take-this dir
716
$ bzr commit --strict -m 'No more conflicts nor unknown files'
841
$ brz resolve --take-this dir
843
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
719
846
def test_resolve_taking_other(self):
720
847
self.run_script("""
721
$ bzr resolve --take-other dir
722
$ bzr commit --strict -m 'No more conflicts nor unknown files'
848
$ brz resolve --take-other dir
850
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
726
854
class TestResolveDeletingParent(TestResolveConflicts):
732
861
$ 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
863
$ brz commit -m 'Create trunk' -q
864
$ brz rm -q dir/file --no-backup
865
$ brz rm -q dir --no-backup
866
$ brz commit -q -m 'Remove dir/file'
867
$ brz branch -q . -r 1 ../branch
742
869
$ echo 'branch content' >dir/file2
744
$ bzr commit -m 'Add dir/file2 in branch'
870
$ brz add -q dir/file2
871
$ brz commit -q -m 'Add dir/file2 in branch'
748
874
2>Conflict: can't delete dir because it is not empty. Not deleting.
749
875
2>Conflict because dir is not versioned, but has versioned children. Versioned directory.
753
879
def test_keep_them_all(self):
754
880
self.run_script("""
756
$ bzr commit --strict -m 'No more conflicts nor unknown files'
882
2>2 conflicts resolved, 0 remaining
883
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
759
886
def test_adopt_child(self):
760
887
self.run_script("""
761
$ bzr mv dir/file2 file2
764
$ bzr commit --strict -m 'No more conflicts nor unknown files'
888
$ brz mv -q dir/file2 file2
889
$ brz rm -q dir --no-backup
891
2>2 conflicts resolved, 0 remaining
892
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
767
895
def test_kill_them_all(self):
768
896
self.run_script("""
771
$ bzr commit --strict -m 'No more conflicts nor unknown files'
897
$ brz rm -q dir --no-backup
899
2>2 conflicts resolved, 0 remaining
900
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
774
903
def test_resolve_taking_this(self):
775
904
self.run_script("""
776
$ bzr resolve --take-this dir
777
$ bzr commit --strict -m 'No more conflicts nor unknown files'
905
$ brz resolve --take-this dir
906
2>2 conflicts resolved, 0 remaining
907
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
780
910
def test_resolve_taking_other(self):
781
911
self.run_script("""
782
$ bzr resolve --take-other dir
783
$ bzr commit --strict -m 'No more conflicts nor unknown files'
912
$ brz resolve --take-other dir
915
2>2 conflicts resolved, 0 remaining
916
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
787
920
class TestResolveParentLoop(TestParametrizedResolveConflicts):
789
_conflict_type = conflicts.ParentLoop,
922
_conflict_type = conflicts.ParentLoop
791
924
_this_args = None
792
925
_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'
927
# Each side dict additionally defines:
928
# - dir_id: the directory being moved
929
# - target_id: The target directory
930
# - xfail: whether the test is expected to fail if the action is
931
# involved as 'other'
932
scenarios = mirror_scenarios(
802
934
# Dirs moved into each other
803
935
(dict(_base_actions='create_dir1_dir2'),
804
936
('dir1_into_dir2',
805
937
dict(actions='move_dir1_into_dir2', check='dir1_moved',
806
dir_id='dir1-id', target_id='dir2-id', xfail=False)),
938
dir_id=b'dir1-id', target_id=b'dir2-id', xfail=False)),
807
939
('dir2_into_dir1',
808
940
dict(actions='move_dir2_into_dir1', check='dir2_moved',
809
dir_id='dir2-id', target_id='dir1-id', xfail=False))),
941
dir_id=b'dir2-id', target_id=b'dir1-id', xfail=False))),
810
942
# Subdirs moved into each other
811
943
(dict(_base_actions='create_dir1_4'),
812
944
('dir1_into_dir4',
813
945
dict(actions='move_dir1_into_dir4', check='dir1_2_moved',
814
dir_id='dir1-id', target_id='dir4-id', xfail=True)),
946
dir_id=b'dir1-id', target_id=b'dir4-id', xfail=True)),
815
947
('dir3_into_dir2',
816
948
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)
949
dir_id=b'dir3-id', target_id=b'dir2-id', xfail=True))),
821
952
def do_create_dir1_dir2(self):
822
return [('add', ('dir1', 'dir1-id', 'directory', '')),
823
('add', ('dir2', 'dir2-id', 'directory', '')),]
953
return [('add', ('dir1', b'dir1-id', 'directory', '')),
954
('add', ('dir2', b'dir2-id', 'directory', '')), ]
825
956
def do_move_dir1_into_dir2(self):
826
957
return [('rename', ('dir1', 'dir2/dir1'))]
828
959
def check_dir1_moved(self):
829
self.failIfExists('branch/dir1')
830
self.failUnlessExists('branch/dir2/dir1')
960
self.assertPathDoesNotExist('branch/dir1')
961
self.assertPathExists('branch/dir2/dir1')
832
963
def do_move_dir2_into_dir1(self):
833
964
return [('rename', ('dir2', 'dir1/dir2'))]
835
966
def check_dir2_moved(self):
836
self.failIfExists('branch/dir2')
837
self.failUnlessExists('branch/dir1/dir2')
967
self.assertPathDoesNotExist('branch/dir2')
968
self.assertPathExists('branch/dir1/dir2')
839
970
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', '')),]
971
return [('add', ('dir1', b'dir1-id', 'directory', '')),
972
('add', ('dir1/dir2', b'dir2-id', 'directory', '')),
973
('add', ('dir3', b'dir3-id', 'directory', '')),
974
('add', ('dir3/dir4', b'dir4-id', 'directory', '')), ]
845
976
def do_move_dir1_into_dir4(self):
846
977
return [('rename', ('dir1', 'dir3/dir4/dir1'))]
848
979
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')
980
self.assertPathDoesNotExist('branch/dir1')
981
self.assertPathExists('branch/dir3/dir4/dir1')
982
self.assertPathExists('branch/dir3/dir4/dir1/dir2')
853
984
def do_move_dir3_into_dir2(self):
854
985
return [('rename', ('dir3', 'dir1/dir2/dir3'))]
856
987
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')
988
self.assertPathDoesNotExist('branch/dir3')
989
self.assertPathExists('branch/dir1/dir2/dir3')
990
self.assertPathExists('branch/dir1/dir2/dir3/dir4')
861
992
def _get_resolve_path_arg(self, wt, action):
862
993
# ParentLoop says: moving <conflict_path> into <path>. Cancelled move.
941
1076
# This is nearly like TestResolveNonDirectoryParent but with branch and
942
1077
# trunk switched. As such it should certainly produce the same
1079
self.assertRaises(errors.MalformedTransform,
1080
self.run_script, """
948
$ bzr commit -m 'Create trunk'
1086
$ brz commit -m 'Create trunk' -q
950
1088
$ echo "Boo!" >foo
951
$ bzr commit -m 'foo is now a file'
953
$ bzr branch . -r 1 ../branch
1089
$ brz commit -m 'foo is now a file' -q
1090
$ brz branch -q . -r 1 ../branch -q
955
1092
$ echo "Boing" >foo/bar
957
$ bzr commit -m 'Add foo/bar'
960
2>bzr: ERROR: Tree transform is malformed [('unversioned executability', 'new-1')]
1093
$ brz add -q foo/bar -q
1094
$ brz commit -m 'Add foo/bar' -q
1095
$ brz merge ../trunk
1096
2>brz: ERROR: Tree transform is malformed [('unversioned executability', 'new-1')]
1100
class TestNoFinalPath(script.TestCaseWithTransportAndScript):
1102
def test_bug_805809(self):
1105
Created a standalone tree (format: 2a)
1110
$ brz commit -m 'create file on trunk'
1111
2>Committing to: .../trunk/
1113
2>Committed revision 1.
1114
# Create a debian branch based on trunk
1116
$ brz branch trunk -r 1 debian
1117
2>Branched 1 revision.
1124
$ brz commit -m 'rename file to dir/file for debian'
1125
2>Committing to: .../debian/
1127
2>renamed file => dir/file
1128
2>Committed revision 2.
1129
# Create an experimental branch with a new root-id
1131
$ brz init experimental
1132
Created a standalone tree (format: 2a)
1134
# Work around merging into empty branch not being supported
1135
# (http://pad.lv/308562)
1136
$ echo something >not-empty
1139
$ brz commit -m 'Add some content in experimental'
1140
2>Committing to: .../experimental/
1142
2>Committed revision 1.
1143
# merge debian even without a common ancestor
1144
$ brz merge ../debian -r0..2
1147
2>All changes applied successfully.
1148
$ brz commit -m 'merging debian into experimental'
1149
2>Committing to: .../experimental/
1152
2>Committed revision 2.
1153
# Create an ubuntu branch with yet another root-id
1156
Created a standalone tree (format: 2a)
1158
# Work around merging into empty branch not being supported
1159
# (http://pad.lv/308562)
1160
$ echo something >not-empty-ubuntu
1162
adding not-empty-ubuntu
1163
$ brz commit -m 'Add some content in experimental'
1164
2>Committing to: .../ubuntu/
1165
2>added not-empty-ubuntu
1166
2>Committed revision 1.
1168
$ brz merge ../debian -r0..2
1171
2>All changes applied successfully.
1172
$ brz commit -m 'merging debian'
1173
2>Committing to: .../ubuntu/
1176
2>Committed revision 2.
1177
# Now try to merge experimental
1178
$ brz merge ../experimental
1180
2>Path conflict: dir / dir
1181
2>1 conflicts encountered.