43
57
# '\xc3\xae' == u'\xee' == i with hat
44
58
# So these are u'path' and 'id' only with a circle and a hat. (shappo?)
45
59
example_conflicts = conflicts.ConflictList(
46
[conflicts.MissingParent('Not deleting', u'p\xe5thg', b'\xc3\xaedg'),
47
conflicts.ContentsConflict(u'p\xe5tha', None, b'\xc3\xaeda'),
60
[conflicts.MissingParent('Not deleting', u'p\xe5thg', '\xc3\xaedg'),
61
conflicts.ContentsConflict(u'p\xe5tha', None, '\xc3\xaeda'),
48
62
conflicts.TextConflict(u'p\xe5tha'),
49
conflicts.PathConflict(u'p\xe5thb', u'p\xe5thc', b'\xc3\xaedb'),
63
conflicts.PathConflict(u'p\xe5thb', u'p\xe5thc', '\xc3\xaedb'),
50
64
conflicts.DuplicateID('Unversioned existing file',
51
65
u'p\xe5thc', u'p\xe5thc2',
52
b'\xc3\xaedc', b'\xc3\xaedc'),
53
conflicts.DuplicateEntry('Moved existing file to',
54
u'p\xe5thdd.moved', u'p\xe5thd',
56
conflicts.ParentLoop('Cancelled move', u'p\xe5the', u'p\xe5th2e',
57
None, b'\xc3\xaed2e'),
58
conflicts.UnversionedParent('Versioned directory',
59
u'p\xe5thf', b'\xc3\xaedf'),
60
conflicts.NonDirectoryParent('Created directory',
61
u'p\xe5thg', b'\xc3\xaedg'),
65
def vary_by_conflicts():
66
for conflict in example_conflicts:
67
yield (conflict.__class__.__name__, {"conflict": conflict})
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'),
70
79
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')
72
108
def test_resolve_conflict_dir(self):
73
109
tree = self.make_branch_and_tree('.')
74
self.build_tree_contents([('hello', b'hello world4'),
75
('hello.THIS', b'hello world2'),
76
('hello.BASE', b'hello world1'),
110
self.build_tree_contents([('hello', 'hello world4'),
111
('hello.THIS', 'hello world2'),
112
('hello.BASE', 'hello world1'),
78
114
os.mkdir('hello.OTHER')
79
tree.add('hello', b'q')
115
tree.add('hello', 'q')
80
116
l = conflicts.ConflictList([conflicts.TextConflict('hello')])
81
117
l.remove_files(tree)
126
161
self.assertEqual(conflicts.ConflictList([]), tree.conflicts())
129
class TestPerConflict(tests.TestCase):
131
scenarios = scenarios.multiply_scenarios(vary_by_conflicts())
133
def test_stringification(self):
134
text = text_type(self.conflict)
135
self.assertContainsString(text, self.conflict.path)
136
self.assertContainsString(text.lower(), "conflict")
137
self.assertContainsString(repr(self.conflict),
138
self.conflict.__class__.__name__)
164
class TestConflictStanzas(tests.TestCase):
140
166
def test_stanza_roundtrip(self):
142
o = conflicts.Conflict.factory(**p.as_stanza().as_dict())
143
self.assertEqual(o, p)
145
self.assertIsInstance(o.path, text_type)
147
if o.file_id is not None:
148
self.assertIsInstance(o.file_id, bytes)
150
conflict_path = getattr(o, 'conflict_path', None)
151
if conflict_path is not None:
152
self.assertIsInstance(conflict_path, text_type)
154
conflict_file_id = getattr(o, 'conflict_file_id', None)
155
if conflict_file_id is not None:
156
self.assertIsInstance(conflict_file_id, bytes)
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)
158
186
def test_stanzification(self):
159
stanza = self.conflict.as_stanza()
160
if 'file_id' in stanza:
161
# In Stanza form, the file_id has to be unicode.
162
self.assertStartsWith(stanza['file_id'], u'\xeed')
163
self.assertStartsWith(stanza['path'], u'p\xe5th')
164
if 'conflict_path' in stanza:
165
self.assertStartsWith(stanza['conflict_path'], u'p\xe5th')
166
if 'conflict_file_id' in stanza:
167
self.assertStartsWith(stanza['conflict_file_id'], u'\xeed')
170
class TestConflictList(tests.TestCase):
172
def test_stanzas_roundtrip(self):
173
stanzas_iter = example_conflicts.to_stanzas()
174
processed = conflicts.ConflictList.from_stanzas(stanzas_iter)
175
self.assertEqual(example_conflicts, processed)
177
def test_stringification(self):
178
for text, o in zip(example_conflicts.to_strings(), example_conflicts):
179
self.assertEqual(text, text_type(o))
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')
182
198
# FIXME: The shell-like tests should be converted to real whitebox tests... or
276
"""The scenario list for the conflict type defined by the class.
278
Each scenario is of the form:
279
(common, (left_name, left_dict), (right_name, right_dict))
283
* left_name and right_name are the scenario names that will be combined
285
* left_dict and right_dict are the attributes specific to each half of
286
the scenario. They should include at least 'actions' and 'check' and
287
will be available as '_this' and '_other' test instance attributes.
289
Daughters classes are free to add their specific attributes as they see
290
fit in any of the three dicts.
292
This is a class method so that load_tests can find it.
294
'_base_actions' in the common dict, 'actions' and 'check' in the left
295
and right dicts use names that map to methods in the test classes. Some
296
prefixes are added to these names to get the correspong methods (see
297
_get_actions() and _get_check()). The motivation here is to avoid
298
collisions in the class namespace.
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
302
326
super(TestParametrizedResolveConflicts, self).setUp()
304
328
builder.start_series()
306
330
# Create an empty trunk
307
builder.build_snapshot(None, [
308
('add', (u'', b'root-id', 'directory', ''))],
309
revision_id=b'start')
331
builder.build_snapshot('start', None, [
332
('add', ('', 'root-id', 'directory', ''))])
310
333
# Add a minimal base content
311
334
base_actions = self._get_actions(self._base_actions)()
312
builder.build_snapshot([b'start'], base_actions, revision_id=b'base')
335
builder.build_snapshot('base', ['start'], base_actions)
313
336
# Modify the base content in branch
314
337
actions_other = self._get_actions(self._other['actions'])()
315
builder.build_snapshot([b'base'], actions_other, revision_id=b'other')
338
builder.build_snapshot('other', ['base'], actions_other)
316
339
# Modify the base content in trunk
317
340
actions_this = self._get_actions(self._this['actions'])()
318
builder.build_snapshot([b'base'], actions_this, revision_id=b'this')
341
builder.build_snapshot('this', ['base'], actions_this)
319
342
# builder.get_branch() tip is now 'this'
321
344
builder.finish_series()
368
class TestResolveTextConflicts(TestParametrizedResolveConflicts):
370
_conflict_type = conflicts.TextConflict
372
# Set by the scenarios
373
# path and file-id for the file involved in the conflict
377
scenarios = mirror_scenarios(
379
# File modified on both sides
380
(dict(_base_actions='create_file',
381
_path='file', _file_id=b'file-id'),
383
dict(actions='modify_file_A', check='file_has_content_A')),
385
dict(actions='modify_file_B', check='file_has_content_B')),),
386
# File modified on both sides in dir
387
(dict(_base_actions='create_file_in_dir',
388
_path='dir/file', _file_id=b'file-id'),
389
('filed_modified_A_in_dir',
390
dict(actions='modify_file_A_in_dir',
391
check='file_in_dir_has_content_A')),
393
dict(actions='modify_file_B_in_dir',
394
check='file_in_dir_has_content_B')),),
397
def do_create_file(self, path='file'):
398
return [('add', (path, b'file-id', 'file', b'trunk content\n'))]
400
def do_modify_file_A(self):
401
return [('modify', ('file', b'trunk content\nfeature A\n'))]
403
def do_modify_file_B(self):
404
return [('modify', ('file', b'trunk content\nfeature B\n'))]
406
def do_modify_file_A_in_dir(self):
407
return [('modify', ('dir/file', b'trunk content\nfeature A\n'))]
409
def do_modify_file_B_in_dir(self):
410
return [('modify', ('dir/file', b'trunk content\nfeature B\n'))]
412
def check_file_has_content_A(self, path='file'):
413
self.assertFileEqual(b'trunk content\nfeature A\n',
414
osutils.pathjoin('branch', path))
416
def check_file_has_content_B(self, path='file'):
417
self.assertFileEqual(b'trunk content\nfeature B\n',
418
osutils.pathjoin('branch', path))
420
def do_create_file_in_dir(self):
421
return [('add', ('dir', b'dir-id', 'directory', '')),
422
] + self.do_create_file('dir/file')
424
def check_file_in_dir_has_content_A(self):
425
self.check_file_has_content_A('dir/file')
427
def check_file_in_dir_has_content_B(self):
428
self.check_file_has_content_B('dir/file')
430
def _get_resolve_path_arg(self, wt, action):
433
def assertTextConflict(self, wt, c):
434
self.assertEqual(self._file_id, c.file_id)
435
self.assertEqual(self._path, c.path)
436
_assert_conflict = assertTextConflict
439
391
class TestResolveContentsConflict(TestParametrizedResolveConflicts):
441
_conflict_type = conflicts.ContentsConflict
393
_conflict_type = conflicts.ContentsConflict,
443
# Set by the scenarios
395
# Set by load_tests from scenarios()
444
396
# path and file-id for the file involved in the conflict
448
scenarios = mirror_scenarios(
450
403
# File modified/deleted
451
404
(dict(_base_actions='create_file',
452
_path='file', _file_id=b'file-id'),
405
_path='file', _file_id='file-id'),
453
406
('file_modified',
454
407
dict(actions='modify_file', check='file_has_more_content')),
456
409
dict(actions='delete_file', check='file_doesnt_exist')),),
457
# File renamed-modified/deleted
458
(dict(_base_actions='create_file',
459
_path='new-file', _file_id=b'file-id'),
460
('file_renamed_and_modified',
461
dict(actions='modify_and_rename_file',
462
check='file_renamed_and_more_content')),
464
dict(actions='delete_file', check='file_doesnt_exist')),),
465
# File modified/deleted in dir
466
(dict(_base_actions='create_file_in_dir',
467
_path='dir/file', _file_id=b'file-id'),
468
('file_modified_in_dir',
469
dict(actions='modify_file_in_dir',
470
check='file_in_dir_has_more_content')),
471
('file_deleted_in_dir',
472
dict(actions='delete_file_in_dir',
473
check='file_in_dir_doesnt_exist')),),
411
return mirror_scenarios(base_scenarios)
476
413
def do_create_file(self):
477
return [('add', ('file', b'file-id', 'file', b'trunk content\n'))]
414
return [('add', ('file', 'file-id', 'file', 'trunk content\n'))]
479
416
def do_modify_file(self):
480
return [('modify', ('file', b'trunk content\nmore content\n'))]
482
def do_modify_and_rename_file(self):
483
return [('modify', ('new-file', b'trunk content\nmore content\n')),
484
('rename', ('file', 'new-file'))]
417
return [('modify', ('file-id', 'trunk content\nmore content\n'))]
486
419
def check_file_has_more_content(self):
487
self.assertFileEqual(b'trunk content\nmore content\n', 'branch/file')
489
def check_file_renamed_and_more_content(self):
490
self.assertFileEqual(
491
b'trunk content\nmore content\n', 'branch/new-file')
420
self.assertFileEqual('trunk content\nmore content\n', 'branch/file')
493
422
def do_delete_file(self):
494
return [('unversion', 'file')]
496
def do_delete_file_in_dir(self):
497
return [('unversion', 'dir/file')]
423
return [('unversion', 'file-id')]
499
425
def check_file_doesnt_exist(self):
500
self.assertPathDoesNotExist('branch/file')
502
def do_create_file_in_dir(self):
503
return [('add', ('dir', b'dir-id', 'directory', '')),
504
('add', ('dir/file', b'file-id', 'file', b'trunk content\n'))]
506
def do_modify_file_in_dir(self):
507
return [('modify', ('dir/file', b'trunk content\nmore content\n'))]
509
def check_file_in_dir_has_more_content(self):
510
self.assertFileEqual(
511
b'trunk content\nmore content\n', 'branch/dir/file')
513
def check_file_in_dir_doesnt_exist(self):
514
self.assertPathDoesNotExist('branch/dir/file')
426
self.failIfExists('branch/file')
516
428
def _get_resolve_path_arg(self, wt, action):
517
429
return self._path
525
437
class TestResolvePathConflict(TestParametrizedResolveConflicts):
527
_conflict_type = conflicts.PathConflict
439
_conflict_type = conflicts.PathConflict,
529
441
def do_nothing(self):
532
# Each side dict additionally defines:
533
# - path path involved (can be '<deleted>')
535
scenarios = mirror_scenarios(
446
# Each side dict additionally defines:
447
# - path path involved (can be '<deleted>')
537
450
# File renamed/deleted
538
451
(dict(_base_actions='create_file'),
540
453
dict(actions='rename_file', check='file_renamed',
541
path='new-file', file_id=b'file-id')),
454
path='new-file', file_id='file-id')),
543
456
dict(actions='delete_file', check='file_doesnt_exist',
544
457
# PathConflicts deletion handling requires a special
545
458
# hard-coded value
546
path='<deleted>', file_id=b'file-id')),),
547
# File renamed/deleted in dir
548
(dict(_base_actions='create_file_in_dir'),
549
('file_renamed_in_dir',
550
dict(actions='rename_file_in_dir', check='file_in_dir_renamed',
551
path='dir/new-file', file_id=b'file-id')),
553
dict(actions='delete_file_in_dir', check='file_in_dir_doesnt_exist',
554
# PathConflicts deletion handling requires a special
556
path='<deleted>', file_id=b'file-id')),),
459
path='<deleted>', file_id='file-id')),),
557
460
# File renamed/renamed differently
558
461
(dict(_base_actions='create_file'),
560
463
dict(actions='rename_file', check='file_renamed',
561
path='new-file', file_id=b'file-id')),
464
path='new-file', file_id='file-id')),
562
465
('file_renamed2',
563
466
dict(actions='rename_file2', check='file_renamed2',
564
path='new-file2', file_id=b'file-id')),),
467
path='new-file2', file_id='file-id')),),
565
468
# Dir renamed/deleted
566
469
(dict(_base_actions='create_dir'),
568
471
dict(actions='rename_dir', check='dir_renamed',
569
path='new-dir', file_id=b'dir-id')),
472
path='new-dir', file_id='dir-id')),
571
474
dict(actions='delete_dir', check='dir_doesnt_exist',
572
475
# PathConflicts deletion handling requires a special
573
476
# hard-coded value
574
path='<deleted>', file_id=b'dir-id')),),
477
path='<deleted>', file_id='dir-id')),),
575
478
# Dir renamed/renamed differently
576
479
(dict(_base_actions='create_dir'),
578
481
dict(actions='rename_dir', check='dir_renamed',
579
path='new-dir', file_id=b'dir-id')),
482
path='new-dir', file_id='dir-id')),
581
484
dict(actions='rename_dir2', check='dir_renamed2',
582
path='new-dir2', file_id=b'dir-id')),),
485
path='new-dir2', file_id='dir-id')),),
487
return mirror_scenarios(base_scenarios)
585
489
def do_create_file(self):
586
return [('add', ('file', b'file-id', 'file', b'trunk content\n'))]
490
return [('add', ('file', 'file-id', 'file', 'trunk content\n'))]
588
492
def do_create_dir(self):
589
return [('add', ('dir', b'dir-id', 'directory', ''))]
493
return [('add', ('dir', 'dir-id', 'directory', ''))]
591
495
def do_rename_file(self):
592
496
return [('rename', ('file', 'new-file'))]
594
498
def check_file_renamed(self):
595
self.assertPathDoesNotExist('branch/file')
596
self.assertPathExists('branch/new-file')
499
self.failIfExists('branch/file')
500
self.failUnlessExists('branch/new-file')
598
502
def do_rename_file2(self):
599
503
return [('rename', ('file', 'new-file2'))]
601
505
def check_file_renamed2(self):
602
self.assertPathDoesNotExist('branch/file')
603
self.assertPathExists('branch/new-file2')
506
self.failIfExists('branch/file')
507
self.failUnlessExists('branch/new-file2')
605
509
def do_rename_dir(self):
606
510
return [('rename', ('dir', 'new-dir'))]
608
512
def check_dir_renamed(self):
609
self.assertPathDoesNotExist('branch/dir')
610
self.assertPathExists('branch/new-dir')
513
self.failIfExists('branch/dir')
514
self.failUnlessExists('branch/new-dir')
612
516
def do_rename_dir2(self):
613
517
return [('rename', ('dir', 'new-dir2'))]
615
519
def check_dir_renamed2(self):
616
self.assertPathDoesNotExist('branch/dir')
617
self.assertPathExists('branch/new-dir2')
520
self.failIfExists('branch/dir')
521
self.failUnlessExists('branch/new-dir2')
619
523
def do_delete_file(self):
620
return [('unversion', 'file')]
622
def do_delete_file_in_dir(self):
623
return [('unversion', 'dir/file')]
524
return [('unversion', 'file-id')]
625
526
def check_file_doesnt_exist(self):
626
self.assertPathDoesNotExist('branch/file')
527
self.failIfExists('branch/file')
628
529
def do_delete_dir(self):
629
return [('unversion', 'dir')]
530
return [('unversion', 'dir-id')]
631
532
def check_dir_doesnt_exist(self):
632
self.assertPathDoesNotExist('branch/dir')
634
def do_create_file_in_dir(self):
635
return [('add', ('dir', b'dir-id', 'directory', '')),
636
('add', ('dir/file', b'file-id', 'file', b'trunk content\n'))]
638
def do_rename_file_in_dir(self):
639
return [('rename', ('dir/file', 'dir/new-file'))]
641
def check_file_in_dir_renamed(self):
642
self.assertPathDoesNotExist('branch/dir/file')
643
self.assertPathExists('branch/dir/new-file')
645
def check_file_in_dir_doesnt_exist(self):
646
self.assertPathDoesNotExist('branch/dir/file')
533
self.failIfExists('branch/dir')
648
535
def _get_resolve_path_arg(self, wt, action):
649
536
tpath = self._this['path']
682
569
class TestResolveDuplicateEntry(TestParametrizedResolveConflicts):
684
_conflict_type = conflicts.DuplicateEntry
571
_conflict_type = conflicts.DuplicateEntry,
686
scenarios = mirror_scenarios(
575
# Each side dict additionally defines:
688
579
# File created with different file-ids
689
580
(dict(_base_actions='nothing'),
690
581
('filea_created',
691
582
dict(actions='create_file_a', check='file_content_a',
692
path='file', file_id=b'file-a-id')),
583
path='file', file_id='file-a-id')),
693
584
('fileb_created',
694
585
dict(actions='create_file_b', check='file_content_b',
695
path='file', file_id=b'file-b-id')),),
696
# File created with different file-ids but deleted on one side
697
(dict(_base_actions='create_file_a'),
699
dict(actions='replace_file_a_by_b', check='file_content_b',
700
path='file', file_id=b'file-b-id')),
702
dict(actions='modify_file_a', check='file_new_content',
703
path='file', file_id=b'file-a-id')),),
586
path='file', file_id='file-b-id')),),
588
return mirror_scenarios(base_scenarios)
706
590
def do_nothing(self):
709
593
def do_create_file_a(self):
710
return [('add', ('file', b'file-a-id', 'file', b'file a content\n'))]
594
return [('add', ('file', 'file-a-id', 'file', 'file a content\n'))]
712
596
def check_file_content_a(self):
713
self.assertFileEqual(b'file a content\n', 'branch/file')
597
self.assertFileEqual('file a content\n', 'branch/file')
715
599
def do_create_file_b(self):
716
return [('add', ('file', b'file-b-id', 'file', b'file b content\n'))]
600
return [('add', ('file', 'file-b-id', 'file', 'file b content\n'))]
718
602
def check_file_content_b(self):
719
self.assertFileEqual(b'file b content\n', 'branch/file')
721
def do_replace_file_a_by_b(self):
722
return [('unversion', 'file'),
723
('add', ('file', b'file-b-id', 'file', b'file b content\n'))]
725
def do_modify_file_a(self):
726
return [('modify', ('file', b'new content\n'))]
728
def check_file_new_content(self):
729
self.assertFileEqual(b'new content\n', 'branch/file')
603
self.assertFileEqual('file b content\n', 'branch/file')
731
605
def _get_resolve_path_arg(self, wt, action):
732
606
return self._this['path']
816
692
def test_keep_them_all(self):
817
693
self.run_script("""
819
2>2 conflicts resolved, 0 remaining
820
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
695
$ bzr commit --strict -m 'No more conflicts nor unknown files'
823
698
def test_adopt_child(self):
824
699
self.run_script("""
825
$ brz mv -q dir/file2 file2
826
$ brz rm -q dir --no-backup
828
2>2 conflicts resolved, 0 remaining
829
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
700
$ bzr mv dir/file2 file2
703
$ bzr commit --strict -m 'No more conflicts nor unknown files'
832
706
def test_kill_them_all(self):
833
707
self.run_script("""
834
$ brz rm -q dir --no-backup
836
2>2 conflicts resolved, 0 remaining
837
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
710
$ bzr commit --strict -m 'No more conflicts nor unknown files'
840
713
def test_resolve_taking_this(self):
841
714
self.run_script("""
842
$ brz resolve --take-this dir
844
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
715
$ bzr resolve --take-this dir
716
$ bzr commit --strict -m 'No more conflicts nor unknown files'
847
719
def test_resolve_taking_other(self):
848
720
self.run_script("""
849
$ brz resolve --take-other dir
851
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
721
$ bzr resolve --take-other dir
722
$ bzr commit --strict -m 'No more conflicts nor unknown files'
855
726
class TestResolveDeletingParent(TestResolveConflicts):
862
732
$ echo 'trunk content' >dir/file
864
$ brz commit -m 'Create trunk' -q
865
$ brz rm -q dir/file --no-backup
866
$ brz rm -q dir --no-backup
867
$ brz commit -q -m 'Remove dir/file'
868
$ brz branch -q . -r 1 ../branch
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
870
742
$ echo 'branch content' >dir/file2
871
$ brz add -q dir/file2
872
$ brz commit -q -m 'Add dir/file2 in branch'
744
$ bzr commit -m 'Add dir/file2 in branch'
875
748
2>Conflict: can't delete dir because it is not empty. Not deleting.
876
749
2>Conflict because dir is not versioned, but has versioned children. Versioned directory.
880
753
def test_keep_them_all(self):
881
754
self.run_script("""
883
2>2 conflicts resolved, 0 remaining
884
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
756
$ bzr commit --strict -m 'No more conflicts nor unknown files'
887
759
def test_adopt_child(self):
888
760
self.run_script("""
889
$ brz mv -q dir/file2 file2
890
$ brz rm -q dir --no-backup
892
2>2 conflicts resolved, 0 remaining
893
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
761
$ bzr mv dir/file2 file2
764
$ bzr commit --strict -m 'No more conflicts nor unknown files'
896
767
def test_kill_them_all(self):
897
768
self.run_script("""
898
$ brz rm -q dir --no-backup
900
2>2 conflicts resolved, 0 remaining
901
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
771
$ bzr commit --strict -m 'No more conflicts nor unknown files'
904
774
def test_resolve_taking_this(self):
905
775
self.run_script("""
906
$ brz resolve --take-this dir
907
2>2 conflicts resolved, 0 remaining
908
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
776
$ bzr resolve --take-this dir
777
$ bzr commit --strict -m 'No more conflicts nor unknown files'
911
780
def test_resolve_taking_other(self):
912
781
self.run_script("""
913
$ brz resolve --take-other dir
916
2>2 conflicts resolved, 0 remaining
917
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
782
$ bzr resolve --take-other dir
783
$ bzr commit --strict -m 'No more conflicts nor unknown files'
921
787
class TestResolveParentLoop(TestParametrizedResolveConflicts):
923
_conflict_type = conflicts.ParentLoop
789
_conflict_type = conflicts.ParentLoop,
925
791
_this_args = None
926
792
_other_args = None
928
# Each side dict additionally defines:
929
# - dir_id: the directory being moved
930
# - target_id: The target directory
931
# - xfail: whether the test is expected to fail if the action is
932
# involved as 'other'
933
scenarios = mirror_scenarios(
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'
935
802
# Dirs moved into each other
936
803
(dict(_base_actions='create_dir1_dir2'),
937
804
('dir1_into_dir2',
938
805
dict(actions='move_dir1_into_dir2', check='dir1_moved',
939
dir_id=b'dir1-id', target_id=b'dir2-id', xfail=False)),
806
dir_id='dir1-id', target_id='dir2-id', xfail=False)),
940
807
('dir2_into_dir1',
941
808
dict(actions='move_dir2_into_dir1', check='dir2_moved',
942
dir_id=b'dir2-id', target_id=b'dir1-id', xfail=False))),
809
dir_id='dir2-id', target_id='dir1-id', xfail=False))),
943
810
# Subdirs moved into each other
944
811
(dict(_base_actions='create_dir1_4'),
945
812
('dir1_into_dir4',
946
813
dict(actions='move_dir1_into_dir4', check='dir1_2_moved',
947
dir_id=b'dir1-id', target_id=b'dir4-id', xfail=True)),
814
dir_id='dir1-id', target_id='dir4-id', xfail=True)),
948
815
('dir3_into_dir2',
949
816
dict(actions='move_dir3_into_dir2', check='dir3_4_moved',
950
dir_id=b'dir3-id', target_id=b'dir2-id', xfail=True))),
817
dir_id='dir3-id', target_id='dir2-id', xfail=True))),
819
return mirror_scenarios(base_scenarios)
953
821
def do_create_dir1_dir2(self):
954
return [('add', ('dir1', b'dir1-id', 'directory', '')),
955
('add', ('dir2', b'dir2-id', 'directory', '')), ]
822
return [('add', ('dir1', 'dir1-id', 'directory', '')),
823
('add', ('dir2', 'dir2-id', 'directory', '')),]
957
825
def do_move_dir1_into_dir2(self):
958
826
return [('rename', ('dir1', 'dir2/dir1'))]
960
828
def check_dir1_moved(self):
961
self.assertPathDoesNotExist('branch/dir1')
962
self.assertPathExists('branch/dir2/dir1')
829
self.failIfExists('branch/dir1')
830
self.failUnlessExists('branch/dir2/dir1')
964
832
def do_move_dir2_into_dir1(self):
965
833
return [('rename', ('dir2', 'dir1/dir2'))]
967
835
def check_dir2_moved(self):
968
self.assertPathDoesNotExist('branch/dir2')
969
self.assertPathExists('branch/dir1/dir2')
836
self.failIfExists('branch/dir2')
837
self.failUnlessExists('branch/dir1/dir2')
971
839
def do_create_dir1_4(self):
972
return [('add', ('dir1', b'dir1-id', 'directory', '')),
973
('add', ('dir1/dir2', b'dir2-id', 'directory', '')),
974
('add', ('dir3', b'dir3-id', 'directory', '')),
975
('add', ('dir3/dir4', b'dir4-id', 'directory', '')), ]
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', '')),]
977
845
def do_move_dir1_into_dir4(self):
978
846
return [('rename', ('dir1', 'dir3/dir4/dir1'))]
980
848
def check_dir1_2_moved(self):
981
self.assertPathDoesNotExist('branch/dir1')
982
self.assertPathExists('branch/dir3/dir4/dir1')
983
self.assertPathExists('branch/dir3/dir4/dir1/dir2')
849
self.failIfExists('branch/dir1')
850
self.failUnlessExists('branch/dir3/dir4/dir1')
851
self.failUnlessExists('branch/dir3/dir4/dir1/dir2')
985
853
def do_move_dir3_into_dir2(self):
986
854
return [('rename', ('dir3', 'dir1/dir2/dir3'))]
988
856
def check_dir3_4_moved(self):
989
self.assertPathDoesNotExist('branch/dir3')
990
self.assertPathExists('branch/dir1/dir2/dir3')
991
self.assertPathExists('branch/dir1/dir2/dir3/dir4')
857
self.failIfExists('branch/dir3')
858
self.failUnlessExists('branch/dir1/dir2/dir3')
859
self.failUnlessExists('branch/dir1/dir2/dir3/dir4')
993
861
def _get_resolve_path_arg(self, wt, action):
994
862
# ParentLoop says: moving <conflict_path> into <path>. Cancelled move.
1077
941
# This is nearly like TestResolveNonDirectoryParent but with branch and
1078
942
# trunk switched. As such it should certainly produce the same
1080
self.assertRaises(errors.MalformedTransform,
1081
self.run_script, """
1087
$ brz commit -m 'Create trunk' -q
948
$ bzr commit -m 'Create trunk'
1089
950
$ echo "Boo!" >foo
1090
$ brz commit -m 'foo is now a file' -q
1091
$ brz branch -q . -r 1 ../branch -q
951
$ bzr commit -m 'foo is now a file'
953
$ bzr branch . -r 1 ../branch
1093
955
$ echo "Boing" >foo/bar
1094
$ brz add -q foo/bar -q
1095
$ brz commit -m 'Add foo/bar' -q
1096
$ brz merge ../trunk
1097
2>brz: ERROR: Tree transform is malformed [('unversioned executability', 'new-1')]
1101
class TestNoFinalPath(script.TestCaseWithTransportAndScript):
1103
def test_bug_805809(self):
1106
Created a standalone tree (format: 2a)
1111
$ brz commit -m 'create file on trunk'
1112
2>Committing to: .../trunk/
1114
2>Committed revision 1.
1115
# Create a debian branch based on trunk
1117
$ brz branch trunk -r 1 debian
1118
2>Branched 1 revision.
1125
$ brz commit -m 'rename file to dir/file for debian'
1126
2>Committing to: .../debian/
1128
2>renamed file => dir/file
1129
2>Committed revision 2.
1130
# Create an experimental branch with a new root-id
1132
$ brz init experimental
1133
Created a standalone tree (format: 2a)
1135
# Work around merging into empty branch not being supported
1136
# (http://pad.lv/308562)
1137
$ echo something >not-empty
1140
$ brz commit -m 'Add some content in experimental'
1141
2>Committing to: .../experimental/
1143
2>Committed revision 1.
1144
# merge debian even without a common ancestor
1145
$ brz merge ../debian -r0..2
1148
2>All changes applied successfully.
1149
$ brz commit -m 'merging debian into experimental'
1150
2>Committing to: .../experimental/
1153
2>Committed revision 2.
1154
# Create an ubuntu branch with yet another root-id
1157
Created a standalone tree (format: 2a)
1159
# Work around merging into empty branch not being supported
1160
# (http://pad.lv/308562)
1161
$ echo something >not-empty-ubuntu
1163
adding not-empty-ubuntu
1164
$ brz commit -m 'Add some content in experimental'
1165
2>Committing to: .../ubuntu/
1166
2>added not-empty-ubuntu
1167
2>Committed revision 1.
1169
$ brz merge ../debian -r0..2
1172
2>All changes applied successfully.
1173
$ brz commit -m 'merging debian'
1174
2>Committing to: .../ubuntu/
1177
2>Committed revision 2.
1178
# Now try to merge experimental
1179
$ brz merge ../experimental
1181
2>Path conflict: dir / dir
1182
2>1 conflicts encountered.
957
$ bzr commit -m 'Add foo/bar'
960
2>bzr: ERROR: Tree transform is malformed [('unversioned executability', 'new-1')]