/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/tests/test_conflicts.py

  • Committer: Jelmer Vernooij
  • Date: 2020-07-15 21:51:27 UTC
  • mto: (7490.40.58 work)
  • mto: This revision was merged to the branch mainline in revision 7519.
  • Revision ID: jelmer@jelmer.uk-20200715215127-3hn9ktbg3f1xikjj
More fixes for hg probing.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2005-2011 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
17
17
 
18
18
import os
19
19
 
20
 
from bzrlib import (
21
 
    branchbuilder,
22
 
    bzrdir,
 
20
from .. import (
23
21
    conflicts,
24
22
    errors,
25
23
    option,
 
24
    osutils,
26
25
    tests,
27
 
    workingtree,
28
 
    )
29
 
from bzrlib.tests import script
30
 
 
31
 
 
32
 
def load_tests(standard_tests, module, loader):
33
 
    result = loader.suiteClass()
34
 
 
35
 
    sp_tests, remaining_tests = tests.split_suite_by_condition(
36
 
        standard_tests, tests.condition_isinstance((
37
 
                TestParametrizedResolveConflicts,
38
 
                )))
39
 
    # Each test class defines its own scenarios. This is needed for
40
 
    # TestResolvePathConflictBefore531967 that verifies that the same tests as
41
 
    # TestResolvePathConflict still pass.
42
 
    for test in tests.iter_suite_tests(sp_tests):
43
 
        tests.apply_scenarios(test, test.scenarios(), result)
44
 
 
45
 
    # No parametrization for the remaining tests
46
 
    result.addTests(remaining_tests)
47
 
 
48
 
    return result
 
26
    transform,
 
27
    )
 
28
from ..sixish import text_type
 
29
from . import (
 
30
    script,
 
31
    scenarios,
 
32
    )
 
33
 
 
34
 
 
35
load_tests = scenarios.load_tests_apply_scenarios
49
36
 
50
37
 
51
38
# TODO: Test commit with some added, and added-but-missing files
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',
69
 
                             '\xc3\xaedd', None),
70
 
    conflicts.ParentLoop('Cancelled move', u'p\xe5the', u'p\xe5th2e',
71
 
                         None, '\xc3\xaed2e'),
72
 
    conflicts.UnversionedParent('Versioned directory',
73
 
                                u'p\xe5thf', '\xc3\xaedf'),
74
 
    conflicts.NonDirectoryParent('Created directory',
75
 
                                 u'p\xe5thg', '\xc3\xaedg'),
76
 
])
 
53
                           b'\xc3\xaedc', b'\xc3\xaedc'),
 
54
     conflicts.DuplicateEntry('Moved existing file to',
 
55
                              u'p\xe5thdd.moved', u'p\xe5thd',
 
56
                              b'\xc3\xaedd', None),
 
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'),
 
63
     ])
 
64
 
 
65
 
 
66
def vary_by_conflicts():
 
67
    for conflict in example_conflicts:
 
68
        yield (conflict.__class__.__name__, {"conflict": conflict})
77
69
 
78
70
 
79
71
class TestConflicts(tests.TestCaseWithTransport):
80
72
 
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'),
91
 
                                  ])
92
 
        tree.lock_read()
93
 
        self.assertLength(6, list(tree.list_files()))
94
 
        tree.unlock()
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')
107
 
 
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'),
113
78
                                  ])
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)
118
83
 
133
98
        check_select(clist(), tree_conflicts,
134
99
                     [''], ignore_misses=True, recurse=True)
135
100
 
136
 
        foobaz  = conflicts.ContentsConflict('foo/baz')
 
101
        foobaz = conflicts.ContentsConflict('foo/baz')
137
102
        tree_conflicts = clist([foobaz, bar])
138
103
 
139
104
        check_select(clist([bar]), clist([foobaz]),
144
109
 
145
110
        check_select(clist(), tree_conflicts,
146
111
                     ['foo'], ignore_misses=True, recurse=True)
147
 
        check_select (tree_conflicts, clist(), ['foo'], ignore_misses=True)
 
112
        check_select(tree_conflicts, clist(), ['foo'], ignore_misses=True)
148
113
 
149
114
    def test_resolve_conflicts_recursive(self):
150
115
        tree = self.make_branch_and_tree('.')
151
116
        self.build_tree(['dir/', 'dir/hello'])
152
117
        tree.add(['dir', 'dir/hello'])
153
118
 
154
 
        dirhello = conflicts.ConflictList([conflicts.TextConflict('dir/hello')])
 
119
        dirhello = conflicts.ConflictList(
 
120
            [conflicts.TextConflict('dir/hello')])
155
121
        tree.set_conflicts(dirhello)
156
122
 
157
123
        conflicts.resolve(tree, ['dir'], recursive=False, ignore_misses=True)
161
127
        self.assertEqual(conflicts.ConflictList([]), tree.conflicts())
162
128
 
163
129
 
164
 
class TestConflictStanzas(tests.TestCase):
 
130
class TestPerConflict(tests.TestCase):
 
131
 
 
132
    scenarios = scenarios.multiply_scenarios(vary_by_conflicts())
 
133
 
 
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__)
165
140
 
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)
172
 
 
173
 
            self.assertIsInstance(o.path, unicode)
174
 
 
175
 
            if o.file_id is not None:
176
 
                self.assertIsInstance(o.file_id, str)
177
 
 
178
 
            conflict_path = getattr(o, 'conflict_path', None)
179
 
            if conflict_path is not None:
180
 
                self.assertIsInstance(conflict_path, unicode)
181
 
 
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)
 
142
        p = self.conflict
 
143
        o = conflicts.Conflict.factory(**p.as_stanza().as_dict())
 
144
        self.assertEqual(o, p)
 
145
 
 
146
        self.assertIsInstance(o.path, text_type)
 
147
 
 
148
        if o.file_id is not None:
 
149
            self.assertIsInstance(o.file_id, bytes)
 
150
 
 
151
        conflict_path = getattr(o, 'conflict_path', None)
 
152
        if conflict_path is not None:
 
153
            self.assertIsInstance(conflict_path, text_type)
 
154
 
 
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)
185
158
 
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')
 
169
 
 
170
 
 
171
class TestConflictList(tests.TestCase):
 
172
 
 
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)
 
177
 
 
178
    def test_stringification(self):
 
179
        for text, o in zip(example_conflicts.to_strings(), example_conflicts):
 
180
            self.assertEqual(text, text_type(o))
196
181
 
197
182
 
198
183
# FIXME: The shell-like tests should be converted to real whitebox tests... or
203
188
# FIXME: Tests missing for DuplicateID conflict type
204
189
class TestResolveConflicts(script.TestCaseWithTransportAndScript):
205
190
 
206
 
    preamble = None # The setup script set by daughter classes
 
191
    preamble = None  # The setup script set by daughter classes
207
192
 
208
193
    def setUp(self):
209
194
        super(TestResolveConflicts, self).setUp()
210
195
        self.run_script(self.preamble)
211
196
 
212
197
 
213
 
class TestResolveTextConflicts(TestResolveConflicts):
214
 
    # TBC
215
 
    pass
216
 
 
217
 
 
218
198
def mirror_scenarios(base_scenarios):
219
199
    """Return a list of mirrored scenarios.
220
200
 
293
273
    _this = None
294
274
    _other = None
295
275
 
296
 
    @staticmethod
297
 
    def scenarios():
298
 
        """Return the scenario list for the conflict type defined by the class.
299
 
 
300
 
        Each scenario is of the form:
301
 
        (common, (left_name, left_dict), (right_name, right_dict))
302
 
 
303
 
        * common is a dict
304
 
 
305
 
        * left_name and right_name are the scenario names that will be combined
306
 
 
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.
310
 
 
311
 
        Daughters classes are free to add their specific attributes as they see
312
 
        fit in any of the three dicts.
313
 
 
314
 
        This is a class method so that load_tests can find it.
315
 
 
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.
321
 
        """
322
 
        # Only concrete classes return actual scenarios
323
 
        return []
 
276
    scenarios = []
 
277
    """The scenario list for the conflict type defined by the class.
 
278
 
 
279
    Each scenario is of the form:
 
280
    (common, (left_name, left_dict), (right_name, right_dict))
 
281
 
 
282
    * common is a dict
 
283
 
 
284
    * left_name and right_name are the scenario names that will be combined
 
285
 
 
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.
 
289
 
 
290
    Daughters classes are free to add their specific attributes as they see
 
291
    fit in any of the three dicts.
 
292
 
 
293
    This is a class method so that load_tests can find it.
 
294
 
 
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.
 
300
    """
324
301
 
325
302
    def setUp(self):
326
303
        super(TestParametrizedResolveConflicts, self).setUp()
328
305
        builder.start_series()
329
306
 
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'
343
321
 
344
322
        builder.finish_series()
352
330
 
353
331
    def _merge_other_into_this(self):
354
332
        b = self.builder.get_branch()
355
 
        wt = b.bzrdir.sprout('branch').open_workingtree()
356
 
        wt.merge_from_branch(b, 'other')
 
333
        wt = b.controldir.sprout('branch').open_workingtree()
 
334
        wt.merge_from_branch(b, b'other')
357
335
        return wt
358
336
 
359
337
    def assertConflict(self, wt):
388
366
        check_other()
389
367
 
390
368
 
 
369
class TestResolveTextConflicts(TestParametrizedResolveConflicts):
 
370
 
 
371
    _conflict_type = conflicts.TextConflict
 
372
 
 
373
    # Set by the scenarios
 
374
    # path and file-id for the file involved in the conflict
 
375
    _path = None
 
376
    _file_id = None
 
377
 
 
378
    scenarios = mirror_scenarios(
 
379
        [
 
380
            # File modified on both sides
 
381
            (dict(_base_actions='create_file',
 
382
                  _path='file', _file_id=b'file-id'),
 
383
             ('filed_modified_A',
 
384
              dict(actions='modify_file_A', check='file_has_content_A')),
 
385
             ('file_modified_B',
 
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')),
 
393
             ('file_modified_B',
 
394
              dict(actions='modify_file_B_in_dir',
 
395
                   check='file_in_dir_has_content_B')),),
 
396
            ])
 
397
 
 
398
    def do_create_file(self, path='file'):
 
399
        return [('add', (path, b'file-id', 'file', b'trunk content\n'))]
 
400
 
 
401
    def do_modify_file_A(self):
 
402
        return [('modify', ('file', b'trunk content\nfeature A\n'))]
 
403
 
 
404
    def do_modify_file_B(self):
 
405
        return [('modify', ('file', b'trunk content\nfeature B\n'))]
 
406
 
 
407
    def do_modify_file_A_in_dir(self):
 
408
        return [('modify', ('dir/file', b'trunk content\nfeature A\n'))]
 
409
 
 
410
    def do_modify_file_B_in_dir(self):
 
411
        return [('modify', ('dir/file', b'trunk content\nfeature B\n'))]
 
412
 
 
413
    def check_file_has_content_A(self, path='file'):
 
414
        self.assertFileEqual(b'trunk content\nfeature A\n',
 
415
                             osutils.pathjoin('branch', path))
 
416
 
 
417
    def check_file_has_content_B(self, path='file'):
 
418
        self.assertFileEqual(b'trunk content\nfeature B\n',
 
419
                             osutils.pathjoin('branch', path))
 
420
 
 
421
    def do_create_file_in_dir(self):
 
422
        return [('add', ('dir', b'dir-id', 'directory', '')),
 
423
                ] + self.do_create_file('dir/file')
 
424
 
 
425
    def check_file_in_dir_has_content_A(self):
 
426
        self.check_file_has_content_A('dir/file')
 
427
 
 
428
    def check_file_in_dir_has_content_B(self):
 
429
        self.check_file_has_content_B('dir/file')
 
430
 
 
431
    def _get_resolve_path_arg(self, wt, action):
 
432
        return self._path
 
433
 
 
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
 
438
 
 
439
 
391
440
class TestResolveContentsConflict(TestParametrizedResolveConflicts):
392
441
 
393
 
    _conflict_type = conflicts.ContentsConflict,
 
442
    _conflict_type = conflicts.ContentsConflict
394
443
 
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
397
446
    _path = None
398
447
    _file_id = None
399
448
 
400
 
    @staticmethod
401
 
    def scenarios():
402
 
        base_scenarios = [
 
449
    scenarios = mirror_scenarios(
 
450
        [
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')),
408
456
             ('file_deleted',
409
457
              dict(actions='delete_file', check='file_doesnt_exist')),),
410
 
            ]
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')),
 
464
             ('file_deleted',
 
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')),),
 
475
            ])
412
476
 
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'))]
415
479
 
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'))]
 
482
 
 
483
    def do_modify_and_rename_file(self):
 
484
        return [('modify', ('new-file', b'trunk content\nmore content\n')),
 
485
                ('rename', ('file', 'new-file'))]
418
486
 
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')
 
489
 
 
490
    def check_file_renamed_and_more_content(self):
 
491
        self.assertFileEqual(
 
492
            b'trunk content\nmore content\n', 'branch/new-file')
421
493
 
422
494
    def do_delete_file(self):
423
 
        return [('unversion', 'file-id')]
 
495
        return [('unversion', 'file')]
 
496
 
 
497
    def do_delete_file_in_dir(self):
 
498
        return [('unversion', 'dir/file')]
424
499
 
425
500
    def check_file_doesnt_exist(self):
426
 
        self.failIfExists('branch/file')
 
501
        self.assertPathDoesNotExist('branch/file')
 
502
 
 
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'))]
 
506
 
 
507
    def do_modify_file_in_dir(self):
 
508
        return [('modify', ('dir/file', b'trunk content\nmore content\n'))]
 
509
 
 
510
    def check_file_in_dir_has_more_content(self):
 
511
        self.assertFileEqual(
 
512
            b'trunk content\nmore content\n', 'branch/dir/file')
 
513
 
 
514
    def check_file_in_dir_doesnt_exist(self):
 
515
        self.assertPathDoesNotExist('branch/dir/file')
427
516
 
428
517
    def _get_resolve_path_arg(self, wt, action):
429
518
        return self._path
436
525
 
437
526
class TestResolvePathConflict(TestParametrizedResolveConflicts):
438
527
 
439
 
    _conflict_type = conflicts.PathConflict,
 
528
    _conflict_type = conflicts.PathConflict
440
529
 
441
530
    def do_nothing(self):
442
531
        return []
443
532
 
444
 
    @staticmethod
445
 
    def scenarios():
446
 
        # Each side dict additionally defines:
447
 
        # - path path involved (can be '<deleted>')
448
 
        # - file-id involved
449
 
        base_scenarios = [
 
533
    # Each side dict additionally defines:
 
534
    # - path path involved (can be '<deleted>')
 
535
    # - file-id involved
 
536
    scenarios = mirror_scenarios(
 
537
        [
450
538
            # File renamed/deleted
451
539
            (dict(_base_actions='create_file'),
452
540
             ('file_renamed',
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')),
455
543
             ('file_deleted',
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')),
 
553
             ('file_deleted',
 
554
              dict(actions='delete_file_in_dir', check='file_in_dir_doesnt_exist',
 
555
                   # PathConflicts deletion handling requires a special
 
556
                   # hard-coded value
 
557
                   path='<deleted>', file_id=b'file-id')),),
460
558
            # File renamed/renamed differently
461
559
            (dict(_base_actions='create_file'),
462
560
             ('file_renamed',
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'),
470
568
             ('dir_renamed',
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')),
473
571
             ('dir_deleted',
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'),
480
578
             ('dir_renamed',
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')),
483
581
             ('dir_renamed2',
484
582
              dict(actions='rename_dir2', check='dir_renamed2',
485
 
                   path='new-dir2', file_id='dir-id')),),
486
 
        ]
487
 
        return mirror_scenarios(base_scenarios)
 
583
                   path='new-dir2', file_id=b'dir-id')),),
 
584
            ])
488
585
 
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'))]
491
588
 
492
589
    def do_create_dir(self):
493
 
        return [('add', ('dir', 'dir-id', 'directory', ''))]
 
590
        return [('add', ('dir', b'dir-id', 'directory', ''))]
494
591
 
495
592
    def do_rename_file(self):
496
593
        return [('rename', ('file', 'new-file'))]
497
594
 
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')
501
598
 
502
599
    def do_rename_file2(self):
503
600
        return [('rename', ('file', 'new-file2'))]
504
601
 
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')
508
605
 
509
606
    def do_rename_dir(self):
510
607
        return [('rename', ('dir', 'new-dir'))]
511
608
 
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')
515
612
 
516
613
    def do_rename_dir2(self):
517
614
        return [('rename', ('dir', 'new-dir2'))]
518
615
 
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')
522
619
 
523
620
    def do_delete_file(self):
524
 
        return [('unversion', 'file-id')]
 
621
        return [('unversion', 'file')]
 
622
 
 
623
    def do_delete_file_in_dir(self):
 
624
        return [('unversion', 'dir/file')]
525
625
 
526
626
    def check_file_doesnt_exist(self):
527
 
        self.failIfExists('branch/file')
 
627
        self.assertPathDoesNotExist('branch/file')
528
628
 
529
629
    def do_delete_dir(self):
530
 
        return [('unversion', 'dir-id')]
 
630
        return [('unversion', 'dir')]
531
631
 
532
632
    def check_dir_doesnt_exist(self):
533
 
        self.failIfExists('branch/dir')
 
633
        self.assertPathDoesNotExist('branch/dir')
 
634
 
 
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'))]
 
638
 
 
639
    def do_rename_file_in_dir(self):
 
640
        return [('rename', ('dir/file', 'dir/new-file'))]
 
641
 
 
642
    def check_file_in_dir_renamed(self):
 
643
        self.assertPathDoesNotExist('branch/dir/file')
 
644
        self.assertPathExists('branch/dir/new-file')
 
645
 
 
646
    def check_file_in_dir_doesnt_exist(self):
 
647
        self.assertPathDoesNotExist('branch/dir/file')
534
648
 
535
649
    def _get_resolve_path_arg(self, wt, action):
536
650
        tpath = self._this['path']
546
660
        tfile_id = self._this['file_id']
547
661
        opath = self._other['path']
548
662
        ofile_id = self._other['file_id']
549
 
        self.assertEqual(tfile_id, ofile_id) # Sanity check
 
663
        self.assertEqual(tfile_id, ofile_id)  # Sanity check
550
664
        self.assertEqual(tfile_id, c.file_id)
551
665
        self.assertEqual(tpath, c.path)
552
666
        self.assertEqual(opath, c.conflict_path)
568
682
 
569
683
class TestResolveDuplicateEntry(TestParametrizedResolveConflicts):
570
684
 
571
 
    _conflict_type = conflicts.DuplicateEntry,
 
685
    _conflict_type = conflicts.DuplicateEntry
572
686
 
573
 
    @staticmethod
574
 
    def scenarios():
575
 
        # Each side dict additionally defines:
576
 
        # - path involved
577
 
        # - file-id involved
578
 
        base_scenarios = [
 
687
    scenarios = mirror_scenarios(
 
688
        [
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')),),
587
 
            ]
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'),
 
699
             ('filea_replaced',
 
700
              dict(actions='replace_file_a_by_b', check='file_content_b',
 
701
                   path='file', file_id=b'file-b-id')),
 
702
             ('filea_modified',
 
703
              dict(actions='modify_file_a', check='file_new_content',
 
704
                   path='file', file_id=b'file-a-id')),),
 
705
            ])
589
706
 
590
707
    def do_nothing(self):
591
708
        return []
592
709
 
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'))]
595
712
 
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')
598
715
 
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'))]
601
718
 
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')
 
721
 
 
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'))]
 
725
 
 
726
    def do_modify_file_a(self):
 
727
        return [('modify', ('file', b'new content\n'))]
 
728
 
 
729
    def check_file_new_content(self):
 
730
        self.assertFileEqual(b'new content\n', 'branch/file')
604
731
 
605
732
    def _get_resolve_path_arg(self, wt, action):
606
733
        return self._this['path']
610
737
        tfile_id = self._this['file_id']
611
738
        opath = self._other['path']
612
739
        ofile_id = self._other['file_id']
613
 
        self.assertEqual(tpath, opath) # Sanity check
 
740
        self.assertEqual(tpath, opath)  # Sanity check
614
741
        self.assertEqual(tfile_id, c.file_id)
615
742
        self.assertEqual(tpath + '.moved', c.path)
616
743
        self.assertEqual(tpath, c.conflict_path)
624
751
    # FIXME: While this *creates* UnversionedParent conflicts, this really only
625
752
    # tests MissingParent resolution :-/
626
753
    preamble = """
627
 
$ bzr init trunk
 
754
$ brz init trunk
 
755
...
628
756
$ cd trunk
629
757
$ mkdir dir
630
 
$ bzr add dir
631
 
$ bzr commit -m 'Create trunk'
632
 
 
 
758
$ brz add -q dir
 
759
$ brz commit -m 'Create trunk' -q
633
760
$ echo 'trunk content' >dir/file
634
 
$ bzr add dir/file
635
 
$ bzr commit -m 'Add dir/file in trunk'
636
 
 
637
 
$ bzr branch . -r 1 ../branch
 
761
$ brz add -q dir/file
 
762
$ brz commit -q -m 'Add dir/file in trunk'
 
763
$ brz branch -q . -r 1 ../branch
638
764
$ cd ../branch
639
 
$ bzr rm dir
640
 
$ bzr commit -m 'Remove dir in branch'
641
 
 
642
 
$ bzr merge ../trunk
 
765
$ brz rm dir -q
 
766
$ brz commit -q -m 'Remove dir in branch'
 
767
$ brz merge ../trunk
643
768
2>+N  dir/
644
769
2>+N  dir/file
645
770
2>Conflict adding files to dir.  Created directory.
649
774
 
650
775
    def test_take_this(self):
651
776
        self.run_script("""
652
 
$ bzr rm dir  --force
653
 
$ bzr resolve dir
654
 
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
777
$ brz rm -q dir --no-backup
 
778
$ brz resolve dir
 
779
2>2 conflicts resolved, 0 remaining
 
780
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
655
781
""")
656
782
 
657
783
    def test_take_other(self):
658
784
        self.run_script("""
659
 
$ bzr resolve dir
660
 
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
785
$ brz resolve dir
 
786
2>2 conflicts resolved, 0 remaining
 
787
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
661
788
""")
662
789
 
663
790
 
664
791
class TestResolveMissingParent(TestResolveConflicts):
665
792
 
666
793
    preamble = """
667
 
$ bzr init trunk
 
794
$ brz init trunk
 
795
...
668
796
$ cd trunk
669
797
$ mkdir dir
670
798
$ echo 'trunk content' >dir/file
671
 
$ bzr add
672
 
$ bzr commit -m 'Create trunk'
673
 
 
 
799
$ brz add -q
 
800
$ brz commit -m 'Create trunk' -q
674
801
$ echo 'trunk content' >dir/file2
675
 
$ bzr add dir/file2
676
 
$ bzr commit -m 'Add dir/file2 in branch'
677
 
 
678
 
$ bzr branch . -r 1 ../branch
 
802
$ brz add -q dir/file2
 
803
$ brz commit -q -m 'Add dir/file2 in branch'
 
804
$ brz branch -q . -r 1 ../branch
679
805
$ cd ../branch
680
 
$ bzr rm dir/file --force
681
 
$ bzr rm dir
682
 
$ bzr commit -m 'Remove dir/file'
683
 
 
684
 
$ bzr merge ../trunk
 
806
$ brz rm -q dir/file --no-backup
 
807
$ brz rm -q dir
 
808
$ brz commit -q -m 'Remove dir/file'
 
809
$ brz merge ../trunk
685
810
2>+N  dir/
686
811
2>+N  dir/file2
687
812
2>Conflict adding files to dir.  Created directory.
691
816
 
692
817
    def test_keep_them_all(self):
693
818
        self.run_script("""
694
 
$ bzr resolve dir
695
 
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
819
$ brz resolve dir
 
820
2>2 conflicts resolved, 0 remaining
 
821
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
696
822
""")
697
823
 
698
824
    def test_adopt_child(self):
699
825
        self.run_script("""
700
 
$ bzr mv dir/file2 file2
701
 
$ bzr rm dir --force
702
 
$ bzr resolve dir
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
 
828
$ brz resolve dir
 
829
2>2 conflicts resolved, 0 remaining
 
830
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
704
831
""")
705
832
 
706
833
    def test_kill_them_all(self):
707
834
        self.run_script("""
708
 
$ bzr rm dir --force
709
 
$ bzr resolve dir
710
 
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
835
$ brz rm -q dir --no-backup
 
836
$ brz resolve dir
 
837
2>2 conflicts resolved, 0 remaining
 
838
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
711
839
""")
712
840
 
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
 
844
2>...
 
845
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
717
846
""")
718
847
 
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
 
851
2>...
 
852
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
723
853
""")
724
854
 
725
855
 
726
856
class TestResolveDeletingParent(TestResolveConflicts):
727
857
 
728
858
    preamble = """
729
 
$ bzr init trunk
 
859
$ brz init trunk
 
860
...
730
861
$ cd trunk
731
862
$ mkdir dir
732
863
$ echo 'trunk content' >dir/file
733
 
$ bzr add
734
 
$ bzr commit -m 'Create trunk'
735
 
 
736
 
$ bzr rm dir/file --force
737
 
$ bzr rm dir --force
738
 
$ bzr commit -m 'Remove dir/file'
739
 
 
740
 
$ bzr branch . -r 1 ../branch
 
864
$ brz add -q
 
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
741
870
$ cd ../branch
742
871
$ echo 'branch content' >dir/file2
743
 
$ bzr add dir/file2
744
 
$ bzr commit -m 'Add dir/file2 in branch'
745
 
 
746
 
$ bzr merge ../trunk
 
872
$ brz add -q dir/file2
 
873
$ brz commit -q -m 'Add dir/file2 in branch'
 
874
$ brz merge ../trunk
747
875
2>-D  dir/file
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.
752
880
 
753
881
    def test_keep_them_all(self):
754
882
        self.run_script("""
755
 
$ bzr resolve dir
756
 
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
883
$ brz resolve dir
 
884
2>2 conflicts resolved, 0 remaining
 
885
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
757
886
""")
758
887
 
759
888
    def test_adopt_child(self):
760
889
        self.run_script("""
761
 
$ bzr mv dir/file2 file2
762
 
$ bzr rm dir --force
763
 
$ bzr resolve dir
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
 
892
$ brz resolve dir
 
893
2>2 conflicts resolved, 0 remaining
 
894
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
765
895
""")
766
896
 
767
897
    def test_kill_them_all(self):
768
898
        self.run_script("""
769
 
$ bzr rm dir --force
770
 
$ bzr resolve dir
771
 
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
899
$ brz rm -q dir --no-backup
 
900
$ brz resolve dir
 
901
2>2 conflicts resolved, 0 remaining
 
902
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
772
903
""")
773
904
 
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'
778
910
""")
779
911
 
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
 
915
2>deleted dir/file2
 
916
2>deleted dir
 
917
2>2 conflicts resolved, 0 remaining
 
918
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
784
919
""")
785
920
 
786
921
 
787
922
class TestResolveParentLoop(TestParametrizedResolveConflicts):
788
923
 
789
 
    _conflict_type = conflicts.ParentLoop,
 
924
    _conflict_type = conflicts.ParentLoop
790
925
 
791
926
    _this_args = None
792
927
    _other_args = None
793
928
 
794
 
    @staticmethod
795
 
    def 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'
801
 
        base_scenarios = [
 
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(
 
935
        [
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))),
818
 
            ]
819
 
        return mirror_scenarios(base_scenarios)
 
951
                   dir_id=b'dir3-id', target_id=b'dir2-id', xfail=True))),
 
952
            ])
820
953
 
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', '')), ]
824
957
 
825
958
    def do_move_dir1_into_dir2(self):
826
959
        return [('rename', ('dir1', 'dir2/dir1'))]
827
960
 
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')
831
964
 
832
965
    def do_move_dir2_into_dir1(self):
833
966
        return [('rename', ('dir2', 'dir1/dir2'))]
834
967
 
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')
838
971
 
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', '')), ]
844
977
 
845
978
    def do_move_dir1_into_dir4(self):
846
979
        return [('rename', ('dir1', 'dir3/dir4/dir1'))]
847
980
 
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')
852
985
 
853
986
    def do_move_dir3_into_dir2(self):
854
987
        return [('rename', ('dir3', 'dir1/dir2/dir3'))]
855
988
 
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')
860
993
 
861
994
    def _get_resolve_path_arg(self, wt, action):
862
995
        # ParentLoop says: moving <conflict_path> into <path>. Cancelled move.
873
1006
        if self._other['xfail']:
874
1007
            # It's a bit hackish to raise from here relying on being called for
875
1008
            # both tests but this avoid overriding test_resolve_taking_other
876
 
            raise tests.KnownFailure(
 
1009
            self.knownFailure(
877
1010
                "ParentLoop doesn't carry enough info to resolve --take-other")
878
1011
    _assert_conflict = assertParentLoop
879
1012
 
881
1014
class TestResolveNonDirectoryParent(TestResolveConflicts):
882
1015
 
883
1016
    preamble = """
884
 
$ bzr init trunk
 
1017
$ brz init trunk
 
1018
...
885
1019
$ cd trunk
886
 
$ bzr mkdir foo
887
 
$ bzr commit -m 'Create trunk'
 
1020
$ brz mkdir foo
 
1021
...
 
1022
$ brz commit -m 'Create trunk' -q
888
1023
$ echo "Boing" >foo/bar
889
 
$ bzr add foo/bar
890
 
$ bzr commit -m 'Add foo/bar'
891
 
 
892
 
$ bzr branch . -r 1 ../branch
 
1024
$ brz add -q foo/bar
 
1025
$ brz commit -q -m 'Add foo/bar'
 
1026
$ brz branch -q . -r 1 ../branch
893
1027
$ cd ../branch
894
1028
$ rm -r foo
895
1029
$ echo "Boo!" >foo
896
 
$ bzr commit -m 'foo is now a file'
897
 
 
898
 
$ bzr merge ../trunk
 
1030
$ brz commit -q -m 'foo is now a file'
 
1031
$ brz merge ../trunk
 
1032
2>RK  foo => foo.new/
899
1033
2>+N  foo.new/bar
900
 
2>RK  foo => foo.new/
901
1034
# FIXME: The message is misleading, foo.new *is* a directory when the message
902
1035
# is displayed -- vila 090916
903
1036
2>Conflict: foo.new is not a directory, but has files in it.  Created directory.
906
1039
 
907
1040
    def test_take_this(self):
908
1041
        self.run_script("""
909
 
$ bzr rm foo.new --force
 
1042
$ brz rm -q foo.new --no-backup
910
1043
# FIXME: Isn't it weird that foo is now unkown even if foo.new has been put
911
1044
# aside ? -- vila 090916
912
 
$ bzr add foo
913
 
$ bzr resolve foo.new
914
 
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
1045
$ brz add -q foo
 
1046
$ brz resolve foo.new
 
1047
2>1 conflict resolved, 0 remaining
 
1048
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
915
1049
""")
916
1050
 
917
1051
    def test_take_other(self):
918
1052
        self.run_script("""
919
 
$ bzr rm foo --force
920
 
$ bzr mv foo.new foo
921
 
$ bzr resolve foo
922
 
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
1053
$ brz rm -q foo --no-backup
 
1054
$ brz mv -q foo.new foo
 
1055
$ brz resolve foo
 
1056
2>1 conflict resolved, 0 remaining
 
1057
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
923
1058
""")
924
1059
 
925
1060
    def test_resolve_taking_this(self):
926
1061
        self.run_script("""
927
 
$ bzr resolve --take-this foo.new
928
 
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
1062
$ brz resolve --take-this foo.new
 
1063
2>...
 
1064
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
929
1065
""")
930
1066
 
931
1067
    def test_resolve_taking_other(self):
932
1068
        self.run_script("""
933
 
$ bzr resolve --take-other foo.new
934
 
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
1069
$ brz resolve --take-other foo.new
 
1070
2>...
 
1071
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
935
1072
""")
936
1073
 
937
1074
 
941
1078
        # This is nearly like TestResolveNonDirectoryParent but with branch and
942
1079
        # trunk switched. As such it should certainly produce the same
943
1080
        # conflict.
944
 
        self.run_script("""
945
 
$ bzr init trunk
 
1081
        self.assertRaises(transform.MalformedTransform,
 
1082
                          self.run_script, """
 
1083
$ brz init trunk
 
1084
...
946
1085
$ cd trunk
947
 
$ bzr mkdir foo
948
 
$ bzr commit -m 'Create trunk'
 
1086
$ brz mkdir foo
 
1087
...
 
1088
$ brz commit -m 'Create trunk' -q
949
1089
$ rm -r foo
950
1090
$ echo "Boo!" >foo
951
 
$ bzr commit -m 'foo is now a file'
952
 
 
953
 
$ bzr branch . -r 1 ../branch
 
1091
$ brz commit -m 'foo is now a file' -q
 
1092
$ brz branch -q . -r 1 ../branch -q
954
1093
$ cd ../branch
955
1094
$ echo "Boing" >foo/bar
956
 
$ bzr add foo/bar
957
 
$ bzr commit -m 'Add foo/bar'
958
 
 
959
 
$ bzr merge ../trunk
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')]
 
1099
""")
 
1100
 
 
1101
 
 
1102
class TestNoFinalPath(script.TestCaseWithTransportAndScript):
 
1103
 
 
1104
    def test_bug_805809(self):
 
1105
        self.run_script("""
 
1106
$ brz init trunk
 
1107
Created a standalone tree (format: 2a)
 
1108
$ cd trunk
 
1109
$ echo trunk >file
 
1110
$ brz add
 
1111
adding file
 
1112
$ brz commit -m 'create file on trunk'
 
1113
2>Committing to: .../trunk/
 
1114
2>added file
 
1115
2>Committed revision 1.
 
1116
# Create a debian branch based on trunk
 
1117
$ cd ..
 
1118
$ brz branch trunk -r 1 debian
 
1119
2>Branched 1 revision.
 
1120
$ cd debian
 
1121
$ mkdir dir
 
1122
$ brz add
 
1123
adding dir
 
1124
$ brz mv file dir
 
1125
file => dir/file
 
1126
$ brz commit -m 'rename file to dir/file for debian'
 
1127
2>Committing to: .../debian/
 
1128
2>added dir
 
1129
2>renamed file => dir/file
 
1130
2>Committed revision 2.
 
1131
# Create an experimental branch with a new root-id
 
1132
$ cd ..
 
1133
$ brz init experimental
 
1134
Created a standalone tree (format: 2a)
 
1135
$ cd experimental
 
1136
# Work around merging into empty branch not being supported
 
1137
# (http://pad.lv/308562)
 
1138
$ echo something >not-empty
 
1139
$ brz add
 
1140
adding not-empty
 
1141
$ brz commit -m 'Add some content in experimental'
 
1142
2>Committing to: .../experimental/
 
1143
2>added not-empty
 
1144
2>Committed revision 1.
 
1145
# merge debian even without a common ancestor
 
1146
$ brz merge ../debian -r0..2
 
1147
2>+N  dir/
 
1148
2>+N  dir/file
 
1149
2>All changes applied successfully.
 
1150
$ brz commit -m 'merging debian into experimental'
 
1151
2>Committing to: .../experimental/
 
1152
2>added dir
 
1153
2>added dir/file
 
1154
2>Committed revision 2.
 
1155
# Create an ubuntu branch with yet another root-id
 
1156
$ cd ..
 
1157
$ brz init ubuntu
 
1158
Created a standalone tree (format: 2a)
 
1159
$ cd ubuntu
 
1160
# Work around merging into empty branch not being supported
 
1161
# (http://pad.lv/308562)
 
1162
$ echo something >not-empty-ubuntu
 
1163
$ brz add
 
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.
 
1169
# Also merge debian
 
1170
$ brz merge ../debian -r0..2
 
1171
2>+N  dir/
 
1172
2>+N  dir/file
 
1173
2>All changes applied successfully.
 
1174
$ brz commit -m 'merging debian'
 
1175
2>Committing to: .../ubuntu/
 
1176
2>added dir
 
1177
2>added dir/file
 
1178
2>Committed revision 2.
 
1179
# Now try to merge experimental
 
1180
$ brz merge ../experimental
 
1181
2>+N  not-empty
 
1182
2>Path conflict: dir / dir
 
1183
2>1 conflicts encountered.
961
1184
""")
962
1185
 
963
1186
 
966
1189
    def setUp(self):
967
1190
        super(TestResolveActionOption, self).setUp()
968
1191
        self.options = [conflicts.ResolveActionOption()]
969
 
        self.parser = option.get_optparser(dict((o.name, o)
970
 
                                                for o in self.options))
 
1192
        self.parser = option.get_optparser(self.options)
971
1193
 
972
1194
    def parse(self, args):
973
1195
        return self.parser.parse_args(args)
974
1196
 
975
1197
    def test_unknown_action(self):
976
 
        self.assertRaises(errors.BadOptionValue,
 
1198
        self.assertRaises(option.BadOptionValue,
977
1199
                          self.parse, ['--action', 'take-me-to-the-moon'])
978
1200
 
979
1201
    def test_done(self):
980
1202
        opts, args = self.parse(['--action', 'done'])
981
 
        self.assertEqual({'action':'done'}, opts)
 
1203
        self.assertEqual({'action': 'done'}, opts)
982
1204
 
983
1205
    def test_take_this(self):
984
1206
        opts, args = self.parse(['--action', 'take-this'])