/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-09-02 16:35:18 UTC
  • mto: (7490.40.109 work)
  • mto: This revision was merged to the branch mainline in revision 7526.
  • Revision ID: jelmer@jelmer.uk-20200902163518-sy9f4unbboljphgu
Handle duplicate directories entries for git.

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
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
 
18
17
import os
19
18
 
20
 
from bzrlib import (
21
 
    branchbuilder,
22
 
    bzrdir,
 
19
from .. import (
23
20
    conflicts,
24
21
    errors,
25
22
    option,
 
23
    osutils,
26
24
    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
 
25
    transform,
 
26
    )
 
27
from ..sixish import text_type
 
28
from ..bzr import conflicts as bzr_conflicts
 
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
56
43
# u'\xe5' == a with circle
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
 
example_conflicts = conflicts.ConflictList(
60
 
    [conflicts.MissingParent('Not deleting', u'p\xe5thg', '\xc3\xaedg'),
61
 
     conflicts.ContentsConflict(u'p\xe5tha', None, '\xc3\xaeda'),
62
 
     conflicts.TextConflict(u'p\xe5tha'),
63
 
     conflicts.PathConflict(u'p\xe5thb', u'p\xe5thc', '\xc3\xaedb'),
64
 
     conflicts.DuplicateID('Unversioned existing file',
65
 
                           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
 
])
 
46
example_conflicts = [
 
47
     bzr_conflicts.MissingParent('Not deleting', u'p\xe5thg', b'\xc3\xaedg'),
 
48
     bzr_conflicts.ContentsConflict(u'p\xe5tha', None, b'\xc3\xaeda'),
 
49
     bzr_conflicts.TextConflict(u'p\xe5tha'),
 
50
     bzr_conflicts.PathConflict(u'p\xe5thb', u'p\xe5thc', b'\xc3\xaedb'),
 
51
     bzr_conflicts.DuplicateID('Unversioned existing file',
 
52
                               u'p\xe5thc', u'p\xe5thc2',
 
53
                               b'\xc3\xaedc', b'\xc3\xaedc'),
 
54
     bzr_conflicts.DuplicateEntry('Moved existing file to',
 
55
                                  u'p\xe5thdd.moved', u'p\xe5thd',
 
56
                                  b'\xc3\xaedd', None),
 
57
     bzr_conflicts.ParentLoop('Cancelled move', u'p\xe5the', u'p\xe5th2e',
 
58
                              None, b'\xc3\xaed2e'),
 
59
     bzr_conflicts.UnversionedParent('Versioned directory',
 
60
                                     u'p\xe5thf', b'\xc3\xaedf'),
 
61
     bzr_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')
116
 
        l = conflicts.ConflictList([conflicts.TextConflict('hello')])
 
80
        tree.add('hello', b'q')
 
81
        l = conflicts.ConflictList([bzr_conflicts.TextConflict('hello')])
117
82
        l.remove_files(tree)
118
83
 
119
84
    def test_select_conflicts(self):
125
90
                (not_selected, selected),
126
91
                tree_conflicts.select_conflicts(tree, paths, **kwargs))
127
92
 
128
 
        foo = conflicts.ContentsConflict('foo')
129
 
        bar = conflicts.ContentsConflict('bar')
 
93
        foo = bzr_conflicts.ContentsConflict('foo')
 
94
        bar = bzr_conflicts.ContentsConflict('bar')
130
95
        tree_conflicts = clist([foo, bar])
131
96
 
132
97
        check_select(clist([bar]), clist([foo]), ['foo'])
133
98
        check_select(clist(), tree_conflicts,
134
99
                     [''], ignore_misses=True, recurse=True)
135
100
 
136
 
        foobaz  = conflicts.ContentsConflict('foo/baz')
 
101
        foobaz = bzr_conflicts.ContentsConflict('foo/baz')
137
102
        tree_conflicts = clist([foobaz, bar])
138
103
 
139
104
        check_select(clist([bar]), clist([foobaz]),
140
105
                     ['foo'], ignore_misses=True, recurse=True)
141
106
 
142
 
        qux = conflicts.PathConflict('qux', 'foo/baz')
 
107
        qux = bzr_conflicts.PathConflict('qux', 'foo/baz')
143
108
        tree_conflicts = clist([qux])
144
109
 
145
 
        check_select(clist(), tree_conflicts,
 
110
        check_select(tree_conflicts, clist(),
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 = [bzr_conflicts.TextConflict('dir/hello')]
155
120
        tree.set_conflicts(dirhello)
156
121
 
157
122
        conflicts.resolve(tree, ['dir'], recursive=False, ignore_misses=True)
161
126
        self.assertEqual(conflicts.ConflictList([]), tree.conflicts())
162
127
 
163
128
 
164
 
class TestConflictStanzas(tests.TestCase):
165
 
 
166
 
    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)
185
 
 
186
 
    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')
 
129
class TestPerConflict(tests.TestCase):
 
130
 
 
131
    scenarios = scenarios.multiply_scenarios(vary_by_conflicts())
 
132
 
 
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__)
 
139
 
 
140
 
 
141
class TestConflictList(tests.TestCase):
 
142
 
 
143
    def test_stanzas_roundtrip(self):
 
144
        stanzas_iter = bzr_conflicts.ConflictList(example_conflicts).to_stanzas()
 
145
        processed = bzr_conflicts.ConflictList.from_stanzas(stanzas_iter)
 
146
        self.assertEqual(example_conflicts, processed)
 
147
 
 
148
    def test_stringification(self):
 
149
        for text, o in zip(
 
150
                bzr_conflicts.ConflictList(example_conflicts).to_strings(),
 
151
                example_conflicts):
 
152
            self.assertEqual(text, text_type(o))
196
153
 
197
154
 
198
155
# FIXME: The shell-like tests should be converted to real whitebox tests... or
203
160
# FIXME: Tests missing for DuplicateID conflict type
204
161
class TestResolveConflicts(script.TestCaseWithTransportAndScript):
205
162
 
206
 
    preamble = None # The setup script set by daughter classes
 
163
    preamble = None  # The setup script set by daughter classes
207
164
 
208
165
    def setUp(self):
209
166
        super(TestResolveConflicts, self).setUp()
210
167
        self.run_script(self.preamble)
211
168
 
212
169
 
213
 
class TestResolveTextConflicts(TestResolveConflicts):
214
 
    # TBC
215
 
    pass
216
 
 
217
 
 
218
170
def mirror_scenarios(base_scenarios):
219
171
    """Return a list of mirrored scenarios.
220
172
 
293
245
    _this = None
294
246
    _other = None
295
247
 
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 []
 
248
    scenarios = []
 
249
    """The scenario list for the conflict type defined by the class.
 
250
 
 
251
    Each scenario is of the form:
 
252
    (common, (left_name, left_dict), (right_name, right_dict))
 
253
 
 
254
    * common is a dict
 
255
 
 
256
    * left_name and right_name are the scenario names that will be combined
 
257
 
 
258
    * left_dict and right_dict are the attributes specific to each half of
 
259
      the scenario. They should include at least 'actions' and 'check' and
 
260
      will be available as '_this' and '_other' test instance attributes.
 
261
 
 
262
    Daughters classes are free to add their specific attributes as they see
 
263
    fit in any of the three dicts.
 
264
 
 
265
    This is a class method so that load_tests can find it.
 
266
 
 
267
    '_base_actions' in the common dict, 'actions' and 'check' in the left
 
268
    and right dicts use names that map to methods in the test classes. Some
 
269
    prefixes are added to these names to get the correspong methods (see
 
270
    _get_actions() and _get_check()). The motivation here is to avoid
 
271
    collisions in the class namespace.
 
272
    """
324
273
 
325
274
    def setUp(self):
326
275
        super(TestParametrizedResolveConflicts, self).setUp()
328
277
        builder.start_series()
329
278
 
330
279
        # Create an empty trunk
331
 
        builder.build_snapshot('start', None, [
332
 
                ('add', ('', 'root-id', 'directory', ''))])
 
280
        builder.build_snapshot(None, [
 
281
            ('add', (u'', b'root-id', 'directory', ''))],
 
282
            revision_id=b'start')
333
283
        # Add a minimal base content
334
284
        base_actions = self._get_actions(self._base_actions)()
335
 
        builder.build_snapshot('base', ['start'], base_actions)
 
285
        builder.build_snapshot([b'start'], base_actions, revision_id=b'base')
336
286
        # Modify the base content in branch
337
287
        actions_other = self._get_actions(self._other['actions'])()
338
 
        builder.build_snapshot('other', ['base'], actions_other)
 
288
        builder.build_snapshot([b'base'], actions_other, revision_id=b'other')
339
289
        # Modify the base content in trunk
340
290
        actions_this = self._get_actions(self._this['actions'])()
341
 
        builder.build_snapshot('this', ['base'], actions_this)
 
291
        builder.build_snapshot([b'base'], actions_this, revision_id=b'this')
342
292
        # builder.get_branch() tip is now 'this'
343
293
 
344
294
        builder.finish_series()
352
302
 
353
303
    def _merge_other_into_this(self):
354
304
        b = self.builder.get_branch()
355
 
        wt = b.bzrdir.sprout('branch').open_workingtree()
356
 
        wt.merge_from_branch(b, 'other')
 
305
        wt = b.controldir.sprout('branch').open_workingtree()
 
306
        wt.merge_from_branch(b, b'other')
357
307
        return wt
358
308
 
359
309
    def assertConflict(self, wt):
388
338
        check_other()
389
339
 
390
340
 
 
341
class TestResolveTextConflicts(TestParametrizedResolveConflicts):
 
342
 
 
343
    _conflict_type = bzr_conflicts.TextConflict
 
344
 
 
345
    # Set by the scenarios
 
346
    # path and file-id for the file involved in the conflict
 
347
    _path = None
 
348
    _file_id = None
 
349
 
 
350
    scenarios = mirror_scenarios(
 
351
        [
 
352
            # File modified on both sides
 
353
            (dict(_base_actions='create_file',
 
354
                  _path='file', _file_id=b'file-id'),
 
355
             ('filed_modified_A',
 
356
              dict(actions='modify_file_A', check='file_has_content_A')),
 
357
             ('file_modified_B',
 
358
              dict(actions='modify_file_B', check='file_has_content_B')),),
 
359
            # File modified on both sides in dir
 
360
            (dict(_base_actions='create_file_in_dir',
 
361
                  _path='dir/file', _file_id=b'file-id'),
 
362
             ('filed_modified_A_in_dir',
 
363
              dict(actions='modify_file_A_in_dir',
 
364
                   check='file_in_dir_has_content_A')),
 
365
             ('file_modified_B',
 
366
              dict(actions='modify_file_B_in_dir',
 
367
                   check='file_in_dir_has_content_B')),),
 
368
            ])
 
369
 
 
370
    def do_create_file(self, path='file'):
 
371
        return [('add', (path, b'file-id', 'file', b'trunk content\n'))]
 
372
 
 
373
    def do_modify_file_A(self):
 
374
        return [('modify', ('file', b'trunk content\nfeature A\n'))]
 
375
 
 
376
    def do_modify_file_B(self):
 
377
        return [('modify', ('file', b'trunk content\nfeature B\n'))]
 
378
 
 
379
    def do_modify_file_A_in_dir(self):
 
380
        return [('modify', ('dir/file', b'trunk content\nfeature A\n'))]
 
381
 
 
382
    def do_modify_file_B_in_dir(self):
 
383
        return [('modify', ('dir/file', b'trunk content\nfeature B\n'))]
 
384
 
 
385
    def check_file_has_content_A(self, path='file'):
 
386
        self.assertFileEqual(b'trunk content\nfeature A\n',
 
387
                             osutils.pathjoin('branch', path))
 
388
 
 
389
    def check_file_has_content_B(self, path='file'):
 
390
        self.assertFileEqual(b'trunk content\nfeature B\n',
 
391
                             osutils.pathjoin('branch', path))
 
392
 
 
393
    def do_create_file_in_dir(self):
 
394
        return [('add', ('dir', b'dir-id', 'directory', '')),
 
395
                ] + self.do_create_file('dir/file')
 
396
 
 
397
    def check_file_in_dir_has_content_A(self):
 
398
        self.check_file_has_content_A('dir/file')
 
399
 
 
400
    def check_file_in_dir_has_content_B(self):
 
401
        self.check_file_has_content_B('dir/file')
 
402
 
 
403
    def _get_resolve_path_arg(self, wt, action):
 
404
        return self._path
 
405
 
 
406
    def assertTextConflict(self, wt, c):
 
407
        self.assertEqual(self._file_id, c.file_id)
 
408
        self.assertEqual(self._path, c.path)
 
409
    _assert_conflict = assertTextConflict
 
410
 
 
411
 
391
412
class TestResolveContentsConflict(TestParametrizedResolveConflicts):
392
413
 
393
 
    _conflict_type = conflicts.ContentsConflict,
 
414
    _conflict_type = bzr_conflicts.ContentsConflict
394
415
 
395
 
    # Set by load_tests from scenarios()
 
416
    # Set by the scenarios
396
417
    # path and file-id for the file involved in the conflict
397
418
    _path = None
398
419
    _file_id = None
399
420
 
400
 
    @staticmethod
401
 
    def scenarios():
402
 
        base_scenarios = [
 
421
    scenarios = mirror_scenarios(
 
422
        [
403
423
            # File modified/deleted
404
424
            (dict(_base_actions='create_file',
405
 
                  _path='file', _file_id='file-id'),
 
425
                  _path='file', _file_id=b'file-id'),
406
426
             ('file_modified',
407
427
              dict(actions='modify_file', check='file_has_more_content')),
408
428
             ('file_deleted',
409
429
              dict(actions='delete_file', check='file_doesnt_exist')),),
410
 
            ]
411
 
        return mirror_scenarios(base_scenarios)
 
430
            # File renamed-modified/deleted
 
431
            (dict(_base_actions='create_file',
 
432
                  _path='new-file', _file_id=b'file-id'),
 
433
             ('file_renamed_and_modified',
 
434
              dict(actions='modify_and_rename_file',
 
435
                   check='file_renamed_and_more_content')),
 
436
             ('file_deleted',
 
437
              dict(actions='delete_file', check='file_doesnt_exist')),),
 
438
            # File modified/deleted in dir
 
439
            (dict(_base_actions='create_file_in_dir',
 
440
                  _path='dir/file', _file_id=b'file-id'),
 
441
             ('file_modified_in_dir',
 
442
              dict(actions='modify_file_in_dir',
 
443
                   check='file_in_dir_has_more_content')),
 
444
             ('file_deleted_in_dir',
 
445
              dict(actions='delete_file_in_dir',
 
446
                   check='file_in_dir_doesnt_exist')),),
 
447
            ])
412
448
 
413
449
    def do_create_file(self):
414
 
        return [('add', ('file', 'file-id', 'file', 'trunk content\n'))]
 
450
        return [('add', ('file', b'file-id', 'file', b'trunk content\n'))]
415
451
 
416
452
    def do_modify_file(self):
417
 
        return [('modify', ('file-id', 'trunk content\nmore content\n'))]
 
453
        return [('modify', ('file', b'trunk content\nmore content\n'))]
 
454
 
 
455
    def do_modify_and_rename_file(self):
 
456
        return [('modify', ('new-file', b'trunk content\nmore content\n')),
 
457
                ('rename', ('file', 'new-file'))]
418
458
 
419
459
    def check_file_has_more_content(self):
420
 
        self.assertFileEqual('trunk content\nmore content\n', 'branch/file')
 
460
        self.assertFileEqual(b'trunk content\nmore content\n', 'branch/file')
 
461
 
 
462
    def check_file_renamed_and_more_content(self):
 
463
        self.assertFileEqual(
 
464
            b'trunk content\nmore content\n', 'branch/new-file')
421
465
 
422
466
    def do_delete_file(self):
423
 
        return [('unversion', 'file-id')]
 
467
        return [('unversion', 'file')]
 
468
 
 
469
    def do_delete_file_in_dir(self):
 
470
        return [('unversion', 'dir/file')]
424
471
 
425
472
    def check_file_doesnt_exist(self):
426
 
        self.failIfExists('branch/file')
 
473
        self.assertPathDoesNotExist('branch/file')
 
474
 
 
475
    def do_create_file_in_dir(self):
 
476
        return [('add', ('dir', b'dir-id', 'directory', '')),
 
477
                ('add', ('dir/file', b'file-id', 'file', b'trunk content\n'))]
 
478
 
 
479
    def do_modify_file_in_dir(self):
 
480
        return [('modify', ('dir/file', b'trunk content\nmore content\n'))]
 
481
 
 
482
    def check_file_in_dir_has_more_content(self):
 
483
        self.assertFileEqual(
 
484
            b'trunk content\nmore content\n', 'branch/dir/file')
 
485
 
 
486
    def check_file_in_dir_doesnt_exist(self):
 
487
        self.assertPathDoesNotExist('branch/dir/file')
427
488
 
428
489
    def _get_resolve_path_arg(self, wt, action):
429
490
        return self._path
436
497
 
437
498
class TestResolvePathConflict(TestParametrizedResolveConflicts):
438
499
 
439
 
    _conflict_type = conflicts.PathConflict,
 
500
    _conflict_type = bzr_conflicts.PathConflict
440
501
 
441
502
    def do_nothing(self):
442
503
        return []
443
504
 
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 = [
 
505
    # Each side dict additionally defines:
 
506
    # - path path involved (can be '<deleted>')
 
507
    # - file-id involved
 
508
    scenarios = mirror_scenarios(
 
509
        [
450
510
            # File renamed/deleted
451
511
            (dict(_base_actions='create_file'),
452
512
             ('file_renamed',
453
513
              dict(actions='rename_file', check='file_renamed',
454
 
                   path='new-file', file_id='file-id')),
 
514
                   path='new-file', file_id=b'file-id')),
455
515
             ('file_deleted',
456
516
              dict(actions='delete_file', check='file_doesnt_exist',
457
517
                   # PathConflicts deletion handling requires a special
458
518
                   # hard-coded value
459
 
                   path='<deleted>', file_id='file-id')),),
 
519
                   path='<deleted>', file_id=b'file-id')),),
 
520
            # File renamed/deleted in dir
 
521
            (dict(_base_actions='create_file_in_dir'),
 
522
             ('file_renamed_in_dir',
 
523
              dict(actions='rename_file_in_dir', check='file_in_dir_renamed',
 
524
                   path='dir/new-file', file_id=b'file-id')),
 
525
             ('file_deleted',
 
526
              dict(actions='delete_file_in_dir', check='file_in_dir_doesnt_exist',
 
527
                   # PathConflicts deletion handling requires a special
 
528
                   # hard-coded value
 
529
                   path='<deleted>', file_id=b'file-id')),),
460
530
            # File renamed/renamed differently
461
531
            (dict(_base_actions='create_file'),
462
532
             ('file_renamed',
463
533
              dict(actions='rename_file', check='file_renamed',
464
 
                   path='new-file', file_id='file-id')),
 
534
                   path='new-file', file_id=b'file-id')),
465
535
             ('file_renamed2',
466
536
              dict(actions='rename_file2', check='file_renamed2',
467
 
                   path='new-file2', file_id='file-id')),),
 
537
                   path='new-file2', file_id=b'file-id')),),
468
538
            # Dir renamed/deleted
469
539
            (dict(_base_actions='create_dir'),
470
540
             ('dir_renamed',
471
541
              dict(actions='rename_dir', check='dir_renamed',
472
 
                   path='new-dir', file_id='dir-id')),
 
542
                   path='new-dir', file_id=b'dir-id')),
473
543
             ('dir_deleted',
474
544
              dict(actions='delete_dir', check='dir_doesnt_exist',
475
545
                   # PathConflicts deletion handling requires a special
476
546
                   # hard-coded value
477
 
                   path='<deleted>', file_id='dir-id')),),
 
547
                   path='<deleted>', file_id=b'dir-id')),),
478
548
            # Dir renamed/renamed differently
479
549
            (dict(_base_actions='create_dir'),
480
550
             ('dir_renamed',
481
551
              dict(actions='rename_dir', check='dir_renamed',
482
 
                   path='new-dir', file_id='dir-id')),
 
552
                   path='new-dir', file_id=b'dir-id')),
483
553
             ('dir_renamed2',
484
554
              dict(actions='rename_dir2', check='dir_renamed2',
485
 
                   path='new-dir2', file_id='dir-id')),),
486
 
        ]
487
 
        return mirror_scenarios(base_scenarios)
 
555
                   path='new-dir2', file_id=b'dir-id')),),
 
556
            ])
488
557
 
489
558
    def do_create_file(self):
490
 
        return [('add', ('file', 'file-id', 'file', 'trunk content\n'))]
 
559
        return [('add', ('file', b'file-id', 'file', b'trunk content\n'))]
491
560
 
492
561
    def do_create_dir(self):
493
 
        return [('add', ('dir', 'dir-id', 'directory', ''))]
 
562
        return [('add', ('dir', b'dir-id', 'directory', ''))]
494
563
 
495
564
    def do_rename_file(self):
496
565
        return [('rename', ('file', 'new-file'))]
497
566
 
498
567
    def check_file_renamed(self):
499
 
        self.failIfExists('branch/file')
500
 
        self.failUnlessExists('branch/new-file')
 
568
        self.assertPathDoesNotExist('branch/file')
 
569
        self.assertPathExists('branch/new-file')
501
570
 
502
571
    def do_rename_file2(self):
503
572
        return [('rename', ('file', 'new-file2'))]
504
573
 
505
574
    def check_file_renamed2(self):
506
 
        self.failIfExists('branch/file')
507
 
        self.failUnlessExists('branch/new-file2')
 
575
        self.assertPathDoesNotExist('branch/file')
 
576
        self.assertPathExists('branch/new-file2')
508
577
 
509
578
    def do_rename_dir(self):
510
579
        return [('rename', ('dir', 'new-dir'))]
511
580
 
512
581
    def check_dir_renamed(self):
513
 
        self.failIfExists('branch/dir')
514
 
        self.failUnlessExists('branch/new-dir')
 
582
        self.assertPathDoesNotExist('branch/dir')
 
583
        self.assertPathExists('branch/new-dir')
515
584
 
516
585
    def do_rename_dir2(self):
517
586
        return [('rename', ('dir', 'new-dir2'))]
518
587
 
519
588
    def check_dir_renamed2(self):
520
 
        self.failIfExists('branch/dir')
521
 
        self.failUnlessExists('branch/new-dir2')
 
589
        self.assertPathDoesNotExist('branch/dir')
 
590
        self.assertPathExists('branch/new-dir2')
522
591
 
523
592
    def do_delete_file(self):
524
 
        return [('unversion', 'file-id')]
 
593
        return [('unversion', 'file')]
 
594
 
 
595
    def do_delete_file_in_dir(self):
 
596
        return [('unversion', 'dir/file')]
525
597
 
526
598
    def check_file_doesnt_exist(self):
527
 
        self.failIfExists('branch/file')
 
599
        self.assertPathDoesNotExist('branch/file')
528
600
 
529
601
    def do_delete_dir(self):
530
 
        return [('unversion', 'dir-id')]
 
602
        return [('unversion', 'dir')]
531
603
 
532
604
    def check_dir_doesnt_exist(self):
533
 
        self.failIfExists('branch/dir')
 
605
        self.assertPathDoesNotExist('branch/dir')
 
606
 
 
607
    def do_create_file_in_dir(self):
 
608
        return [('add', ('dir', b'dir-id', 'directory', '')),
 
609
                ('add', ('dir/file', b'file-id', 'file', b'trunk content\n'))]
 
610
 
 
611
    def do_rename_file_in_dir(self):
 
612
        return [('rename', ('dir/file', 'dir/new-file'))]
 
613
 
 
614
    def check_file_in_dir_renamed(self):
 
615
        self.assertPathDoesNotExist('branch/dir/file')
 
616
        self.assertPathExists('branch/dir/new-file')
 
617
 
 
618
    def check_file_in_dir_doesnt_exist(self):
 
619
        self.assertPathDoesNotExist('branch/dir/file')
534
620
 
535
621
    def _get_resolve_path_arg(self, wt, action):
536
622
        tpath = self._this['path']
546
632
        tfile_id = self._this['file_id']
547
633
        opath = self._other['path']
548
634
        ofile_id = self._other['file_id']
549
 
        self.assertEqual(tfile_id, ofile_id) # Sanity check
 
635
        self.assertEqual(tfile_id, ofile_id)  # Sanity check
550
636
        self.assertEqual(tfile_id, c.file_id)
551
637
        self.assertEqual(tpath, c.path)
552
638
        self.assertEqual(opath, c.conflict_path)
561
647
        # We create a conflict object as it was created before the fix and
562
648
        # inject it into the working tree, the test will exercise the
563
649
        # compatibility code.
564
 
        old_c = conflicts.PathConflict('<deleted>', self._item_path,
 
650
        old_c = bzr_conflicts.PathConflict('<deleted>', self._item_path,
565
651
                                       file_id=None)
566
 
        wt.set_conflicts(conflicts.ConflictList([old_c]))
 
652
        wt.set_conflicts([old_c])
567
653
 
568
654
 
569
655
class TestResolveDuplicateEntry(TestParametrizedResolveConflicts):
570
656
 
571
 
    _conflict_type = conflicts.DuplicateEntry,
 
657
    _conflict_type = bzr_conflicts.DuplicateEntry
572
658
 
573
 
    @staticmethod
574
 
    def scenarios():
575
 
        # Each side dict additionally defines:
576
 
        # - path involved
577
 
        # - file-id involved
578
 
        base_scenarios = [
 
659
    scenarios = mirror_scenarios(
 
660
        [
579
661
            # File created with different file-ids
580
662
            (dict(_base_actions='nothing'),
581
663
             ('filea_created',
582
664
              dict(actions='create_file_a', check='file_content_a',
583
 
                   path='file', file_id='file-a-id')),
 
665
                   path='file', file_id=b'file-a-id')),
584
666
             ('fileb_created',
585
667
              dict(actions='create_file_b', check='file_content_b',
586
 
                   path='file', file_id='file-b-id')),),
587
 
            ]
588
 
        return mirror_scenarios(base_scenarios)
 
668
                   path='file', file_id=b'file-b-id')),),
 
669
            # File created with different file-ids but deleted on one side
 
670
            (dict(_base_actions='create_file_a'),
 
671
             ('filea_replaced',
 
672
              dict(actions='replace_file_a_by_b', check='file_content_b',
 
673
                   path='file', file_id=b'file-b-id')),
 
674
             ('filea_modified',
 
675
              dict(actions='modify_file_a', check='file_new_content',
 
676
                   path='file', file_id=b'file-a-id')),),
 
677
            ])
589
678
 
590
679
    def do_nothing(self):
591
680
        return []
592
681
 
593
682
    def do_create_file_a(self):
594
 
        return [('add', ('file', 'file-a-id', 'file', 'file a content\n'))]
 
683
        return [('add', ('file', b'file-a-id', 'file', b'file a content\n'))]
595
684
 
596
685
    def check_file_content_a(self):
597
 
        self.assertFileEqual('file a content\n', 'branch/file')
 
686
        self.assertFileEqual(b'file a content\n', 'branch/file')
598
687
 
599
688
    def do_create_file_b(self):
600
 
        return [('add', ('file', 'file-b-id', 'file', 'file b content\n'))]
 
689
        return [('add', ('file', b'file-b-id', 'file', b'file b content\n'))]
601
690
 
602
691
    def check_file_content_b(self):
603
 
        self.assertFileEqual('file b content\n', 'branch/file')
 
692
        self.assertFileEqual(b'file b content\n', 'branch/file')
 
693
 
 
694
    def do_replace_file_a_by_b(self):
 
695
        return [('unversion', 'file'),
 
696
                ('add', ('file', b'file-b-id', 'file', b'file b content\n'))]
 
697
 
 
698
    def do_modify_file_a(self):
 
699
        return [('modify', ('file', b'new content\n'))]
 
700
 
 
701
    def check_file_new_content(self):
 
702
        self.assertFileEqual(b'new content\n', 'branch/file')
604
703
 
605
704
    def _get_resolve_path_arg(self, wt, action):
606
705
        return self._this['path']
610
709
        tfile_id = self._this['file_id']
611
710
        opath = self._other['path']
612
711
        ofile_id = self._other['file_id']
613
 
        self.assertEqual(tpath, opath) # Sanity check
 
712
        self.assertEqual(tpath, opath)  # Sanity check
614
713
        self.assertEqual(tfile_id, c.file_id)
615
714
        self.assertEqual(tpath + '.moved', c.path)
616
715
        self.assertEqual(tpath, c.conflict_path)
624
723
    # FIXME: While this *creates* UnversionedParent conflicts, this really only
625
724
    # tests MissingParent resolution :-/
626
725
    preamble = """
627
 
$ bzr init trunk
 
726
$ brz init trunk
 
727
...
628
728
$ cd trunk
629
729
$ mkdir dir
630
 
$ bzr add dir
631
 
$ bzr commit -m 'Create trunk'
632
 
 
 
730
$ brz add -q dir
 
731
$ brz commit -m 'Create trunk' -q
633
732
$ 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
 
733
$ brz add -q dir/file
 
734
$ brz commit -q -m 'Add dir/file in trunk'
 
735
$ brz branch -q . -r 1 ../branch
638
736
$ cd ../branch
639
 
$ bzr rm dir
640
 
$ bzr commit -m 'Remove dir in branch'
641
 
 
642
 
$ bzr merge ../trunk
 
737
$ brz rm dir -q
 
738
$ brz commit -q -m 'Remove dir in branch'
 
739
$ brz merge ../trunk
643
740
2>+N  dir/
644
741
2>+N  dir/file
645
742
2>Conflict adding files to dir.  Created directory.
649
746
 
650
747
    def test_take_this(self):
651
748
        self.run_script("""
652
 
$ bzr rm dir  --force
653
 
$ bzr resolve dir
654
 
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
749
$ brz rm -q dir --no-backup
 
750
$ brz resolve dir
 
751
2>2 conflicts resolved, 0 remaining
 
752
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
655
753
""")
656
754
 
657
755
    def test_take_other(self):
658
756
        self.run_script("""
659
 
$ bzr resolve dir
660
 
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
757
$ brz resolve dir
 
758
2>2 conflicts resolved, 0 remaining
 
759
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
661
760
""")
662
761
 
663
762
 
664
763
class TestResolveMissingParent(TestResolveConflicts):
665
764
 
666
765
    preamble = """
667
 
$ bzr init trunk
 
766
$ brz init trunk
 
767
...
668
768
$ cd trunk
669
769
$ mkdir dir
670
770
$ echo 'trunk content' >dir/file
671
 
$ bzr add
672
 
$ bzr commit -m 'Create trunk'
673
 
 
 
771
$ brz add -q
 
772
$ brz commit -m 'Create trunk' -q
674
773
$ 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
 
774
$ brz add -q dir/file2
 
775
$ brz commit -q -m 'Add dir/file2 in branch'
 
776
$ brz branch -q . -r 1 ../branch
679
777
$ cd ../branch
680
 
$ bzr rm dir/file --force
681
 
$ bzr rm dir
682
 
$ bzr commit -m 'Remove dir/file'
683
 
 
684
 
$ bzr merge ../trunk
 
778
$ brz rm -q dir/file --no-backup
 
779
$ brz rm -q dir
 
780
$ brz commit -q -m 'Remove dir/file'
 
781
$ brz merge ../trunk
685
782
2>+N  dir/
686
783
2>+N  dir/file2
687
784
2>Conflict adding files to dir.  Created directory.
691
788
 
692
789
    def test_keep_them_all(self):
693
790
        self.run_script("""
694
 
$ bzr resolve dir
695
 
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
791
$ brz resolve dir
 
792
2>2 conflicts resolved, 0 remaining
 
793
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
696
794
""")
697
795
 
698
796
    def test_adopt_child(self):
699
797
        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'
 
798
$ brz mv -q dir/file2 file2
 
799
$ brz rm -q dir --no-backup
 
800
$ brz resolve dir
 
801
2>2 conflicts resolved, 0 remaining
 
802
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
704
803
""")
705
804
 
706
805
    def test_kill_them_all(self):
707
806
        self.run_script("""
708
 
$ bzr rm dir --force
709
 
$ bzr resolve dir
710
 
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
807
$ brz rm -q dir --no-backup
 
808
$ brz resolve dir
 
809
2>2 conflicts resolved, 0 remaining
 
810
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
711
811
""")
712
812
 
713
813
    def test_resolve_taking_this(self):
714
814
        self.run_script("""
715
 
$ bzr resolve --take-this dir
716
 
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
815
$ brz resolve --take-this dir
 
816
2>...
 
817
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
717
818
""")
718
819
 
719
820
    def test_resolve_taking_other(self):
720
821
        self.run_script("""
721
 
$ bzr resolve --take-other dir
722
 
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
822
$ brz resolve --take-other dir
 
823
2>...
 
824
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
723
825
""")
724
826
 
725
827
 
726
828
class TestResolveDeletingParent(TestResolveConflicts):
727
829
 
728
830
    preamble = """
729
 
$ bzr init trunk
 
831
$ brz init trunk
 
832
...
730
833
$ cd trunk
731
834
$ mkdir dir
732
835
$ 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
 
836
$ brz add -q
 
837
$ brz commit -m 'Create trunk' -q
 
838
$ brz rm -q dir/file --no-backup
 
839
$ brz rm -q dir --no-backup
 
840
$ brz commit -q -m 'Remove dir/file'
 
841
$ brz branch -q . -r 1 ../branch
741
842
$ cd ../branch
742
843
$ echo 'branch content' >dir/file2
743
 
$ bzr add dir/file2
744
 
$ bzr commit -m 'Add dir/file2 in branch'
745
 
 
746
 
$ bzr merge ../trunk
 
844
$ brz add -q dir/file2
 
845
$ brz commit -q -m 'Add dir/file2 in branch'
 
846
$ brz merge ../trunk
747
847
2>-D  dir/file
748
848
2>Conflict: can't delete dir because it is not empty.  Not deleting.
749
849
2>Conflict because dir is not versioned, but has versioned children.  Versioned directory.
752
852
 
753
853
    def test_keep_them_all(self):
754
854
        self.run_script("""
755
 
$ bzr resolve dir
756
 
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
855
$ brz resolve dir
 
856
2>2 conflicts resolved, 0 remaining
 
857
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
757
858
""")
758
859
 
759
860
    def test_adopt_child(self):
760
861
        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'
 
862
$ brz mv -q dir/file2 file2
 
863
$ brz rm -q dir --no-backup
 
864
$ brz resolve dir
 
865
2>2 conflicts resolved, 0 remaining
 
866
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
765
867
""")
766
868
 
767
869
    def test_kill_them_all(self):
768
870
        self.run_script("""
769
 
$ bzr rm dir --force
770
 
$ bzr resolve dir
771
 
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
871
$ brz rm -q dir --no-backup
 
872
$ brz resolve dir
 
873
2>2 conflicts resolved, 0 remaining
 
874
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
772
875
""")
773
876
 
774
877
    def test_resolve_taking_this(self):
775
878
        self.run_script("""
776
 
$ bzr resolve --take-this dir
777
 
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
879
$ brz resolve --take-this dir
 
880
2>2 conflicts resolved, 0 remaining
 
881
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
778
882
""")
779
883
 
780
884
    def test_resolve_taking_other(self):
781
885
        self.run_script("""
782
 
$ bzr resolve --take-other dir
783
 
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
886
$ brz resolve --take-other dir
 
887
2>deleted dir/file2
 
888
2>deleted dir
 
889
2>2 conflicts resolved, 0 remaining
 
890
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
784
891
""")
785
892
 
786
893
 
787
894
class TestResolveParentLoop(TestParametrizedResolveConflicts):
788
895
 
789
 
    _conflict_type = conflicts.ParentLoop,
 
896
    _conflict_type = bzr_conflicts.ParentLoop
790
897
 
791
898
    _this_args = None
792
899
    _other_args = None
793
900
 
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 = [
 
901
    # Each side dict additionally defines:
 
902
    # - dir_id: the directory being moved
 
903
    # - target_id: The target directory
 
904
    # - xfail: whether the test is expected to fail if the action is
 
905
    #   involved as 'other'
 
906
    scenarios = mirror_scenarios(
 
907
        [
802
908
            # Dirs moved into each other
803
909
            (dict(_base_actions='create_dir1_dir2'),
804
910
             ('dir1_into_dir2',
805
911
              dict(actions='move_dir1_into_dir2', check='dir1_moved',
806
 
                   dir_id='dir1-id', target_id='dir2-id', xfail=False)),
 
912
                   dir_id=b'dir1-id', target_id=b'dir2-id', xfail=False)),
807
913
             ('dir2_into_dir1',
808
914
              dict(actions='move_dir2_into_dir1', check='dir2_moved',
809
 
                   dir_id='dir2-id', target_id='dir1-id', xfail=False))),
 
915
                   dir_id=b'dir2-id', target_id=b'dir1-id', xfail=False))),
810
916
            # Subdirs moved into each other
811
917
            (dict(_base_actions='create_dir1_4'),
812
918
             ('dir1_into_dir4',
813
919
              dict(actions='move_dir1_into_dir4', check='dir1_2_moved',
814
 
                   dir_id='dir1-id', target_id='dir4-id', xfail=True)),
 
920
                   dir_id=b'dir1-id', target_id=b'dir4-id', xfail=True)),
815
921
             ('dir3_into_dir2',
816
922
              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)
 
923
                   dir_id=b'dir3-id', target_id=b'dir2-id', xfail=True))),
 
924
            ])
820
925
 
821
926
    def do_create_dir1_dir2(self):
822
 
        return [('add', ('dir1', 'dir1-id', 'directory', '')),
823
 
                ('add', ('dir2', 'dir2-id', 'directory', '')),]
 
927
        return [('add', ('dir1', b'dir1-id', 'directory', '')),
 
928
                ('add', ('dir2', b'dir2-id', 'directory', '')), ]
824
929
 
825
930
    def do_move_dir1_into_dir2(self):
826
931
        return [('rename', ('dir1', 'dir2/dir1'))]
827
932
 
828
933
    def check_dir1_moved(self):
829
 
        self.failIfExists('branch/dir1')
830
 
        self.failUnlessExists('branch/dir2/dir1')
 
934
        self.assertPathDoesNotExist('branch/dir1')
 
935
        self.assertPathExists('branch/dir2/dir1')
831
936
 
832
937
    def do_move_dir2_into_dir1(self):
833
938
        return [('rename', ('dir2', 'dir1/dir2'))]
834
939
 
835
940
    def check_dir2_moved(self):
836
 
        self.failIfExists('branch/dir2')
837
 
        self.failUnlessExists('branch/dir1/dir2')
 
941
        self.assertPathDoesNotExist('branch/dir2')
 
942
        self.assertPathExists('branch/dir1/dir2')
838
943
 
839
944
    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', '')),]
 
945
        return [('add', ('dir1', b'dir1-id', 'directory', '')),
 
946
                ('add', ('dir1/dir2', b'dir2-id', 'directory', '')),
 
947
                ('add', ('dir3', b'dir3-id', 'directory', '')),
 
948
                ('add', ('dir3/dir4', b'dir4-id', 'directory', '')), ]
844
949
 
845
950
    def do_move_dir1_into_dir4(self):
846
951
        return [('rename', ('dir1', 'dir3/dir4/dir1'))]
847
952
 
848
953
    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')
 
954
        self.assertPathDoesNotExist('branch/dir1')
 
955
        self.assertPathExists('branch/dir3/dir4/dir1')
 
956
        self.assertPathExists('branch/dir3/dir4/dir1/dir2')
852
957
 
853
958
    def do_move_dir3_into_dir2(self):
854
959
        return [('rename', ('dir3', 'dir1/dir2/dir3'))]
855
960
 
856
961
    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')
 
962
        self.assertPathDoesNotExist('branch/dir3')
 
963
        self.assertPathExists('branch/dir1/dir2/dir3')
 
964
        self.assertPathExists('branch/dir1/dir2/dir3/dir4')
860
965
 
861
966
    def _get_resolve_path_arg(self, wt, action):
862
967
        # ParentLoop says: moving <conflict_path> into <path>. Cancelled move.
873
978
        if self._other['xfail']:
874
979
            # It's a bit hackish to raise from here relying on being called for
875
980
            # both tests but this avoid overriding test_resolve_taking_other
876
 
            raise tests.KnownFailure(
 
981
            self.knownFailure(
877
982
                "ParentLoop doesn't carry enough info to resolve --take-other")
878
983
    _assert_conflict = assertParentLoop
879
984
 
881
986
class TestResolveNonDirectoryParent(TestResolveConflicts):
882
987
 
883
988
    preamble = """
884
 
$ bzr init trunk
 
989
$ brz init trunk
 
990
...
885
991
$ cd trunk
886
 
$ bzr mkdir foo
887
 
$ bzr commit -m 'Create trunk'
 
992
$ brz mkdir foo
 
993
...
 
994
$ brz commit -m 'Create trunk' -q
888
995
$ echo "Boing" >foo/bar
889
 
$ bzr add foo/bar
890
 
$ bzr commit -m 'Add foo/bar'
891
 
 
892
 
$ bzr branch . -r 1 ../branch
 
996
$ brz add -q foo/bar
 
997
$ brz commit -q -m 'Add foo/bar'
 
998
$ brz branch -q . -r 1 ../branch
893
999
$ cd ../branch
894
1000
$ rm -r foo
895
1001
$ echo "Boo!" >foo
896
 
$ bzr commit -m 'foo is now a file'
897
 
 
898
 
$ bzr merge ../trunk
 
1002
$ brz commit -q -m 'foo is now a file'
 
1003
$ brz merge ../trunk
 
1004
2>RK  foo => foo.new/
899
1005
2>+N  foo.new/bar
900
 
2>RK  foo => foo.new/
901
1006
# FIXME: The message is misleading, foo.new *is* a directory when the message
902
1007
# is displayed -- vila 090916
903
1008
2>Conflict: foo.new is not a directory, but has files in it.  Created directory.
906
1011
 
907
1012
    def test_take_this(self):
908
1013
        self.run_script("""
909
 
$ bzr rm foo.new --force
 
1014
$ brz rm -q foo.new --no-backup
910
1015
# FIXME: Isn't it weird that foo is now unkown even if foo.new has been put
911
1016
# aside ? -- vila 090916
912
 
$ bzr add foo
913
 
$ bzr resolve foo.new
914
 
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
1017
$ brz add -q foo
 
1018
$ brz resolve foo.new
 
1019
2>1 conflict resolved, 0 remaining
 
1020
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
915
1021
""")
916
1022
 
917
1023
    def test_take_other(self):
918
1024
        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'
 
1025
$ brz rm -q foo --no-backup
 
1026
$ brz mv -q foo.new foo
 
1027
$ brz resolve foo
 
1028
2>1 conflict resolved, 0 remaining
 
1029
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
923
1030
""")
924
1031
 
925
1032
    def test_resolve_taking_this(self):
926
1033
        self.run_script("""
927
 
$ bzr resolve --take-this foo.new
928
 
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
1034
$ brz resolve --take-this foo.new
 
1035
2>...
 
1036
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
929
1037
""")
930
1038
 
931
1039
    def test_resolve_taking_other(self):
932
1040
        self.run_script("""
933
 
$ bzr resolve --take-other foo.new
934
 
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
1041
$ brz resolve --take-other foo.new
 
1042
2>...
 
1043
$ brz commit -q --strict -m 'No more conflicts nor unknown files'
935
1044
""")
936
1045
 
937
1046
 
941
1050
        # This is nearly like TestResolveNonDirectoryParent but with branch and
942
1051
        # trunk switched. As such it should certainly produce the same
943
1052
        # conflict.
944
 
        self.run_script("""
945
 
$ bzr init trunk
 
1053
        self.assertRaises(transform.MalformedTransform,
 
1054
                          self.run_script, """
 
1055
$ brz init trunk
 
1056
...
946
1057
$ cd trunk
947
 
$ bzr mkdir foo
948
 
$ bzr commit -m 'Create trunk'
 
1058
$ brz mkdir foo
 
1059
...
 
1060
$ brz commit -m 'Create trunk' -q
949
1061
$ rm -r foo
950
1062
$ echo "Boo!" >foo
951
 
$ bzr commit -m 'foo is now a file'
952
 
 
953
 
$ bzr branch . -r 1 ../branch
 
1063
$ brz commit -m 'foo is now a file' -q
 
1064
$ brz branch -q . -r 1 ../branch -q
954
1065
$ cd ../branch
955
1066
$ 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')]
 
1067
$ brz add -q foo/bar -q
 
1068
$ brz commit -m 'Add foo/bar' -q
 
1069
$ brz merge ../trunk
 
1070
2>brz: ERROR: Tree transform is malformed [('unversioned executability', 'new-1')]
 
1071
""")
 
1072
 
 
1073
 
 
1074
class TestNoFinalPath(script.TestCaseWithTransportAndScript):
 
1075
 
 
1076
    def test_bug_805809(self):
 
1077
        self.run_script("""
 
1078
$ brz init trunk
 
1079
Created a standalone tree (format: 2a)
 
1080
$ cd trunk
 
1081
$ echo trunk >file
 
1082
$ brz add
 
1083
adding file
 
1084
$ brz commit -m 'create file on trunk'
 
1085
2>Committing to: .../trunk/
 
1086
2>added file
 
1087
2>Committed revision 1.
 
1088
# Create a debian branch based on trunk
 
1089
$ cd ..
 
1090
$ brz branch trunk -r 1 debian
 
1091
2>Branched 1 revision.
 
1092
$ cd debian
 
1093
$ mkdir dir
 
1094
$ brz add
 
1095
adding dir
 
1096
$ brz mv file dir
 
1097
file => dir/file
 
1098
$ brz commit -m 'rename file to dir/file for debian'
 
1099
2>Committing to: .../debian/
 
1100
2>added dir
 
1101
2>renamed file => dir/file
 
1102
2>Committed revision 2.
 
1103
# Create an experimental branch with a new root-id
 
1104
$ cd ..
 
1105
$ brz init experimental
 
1106
Created a standalone tree (format: 2a)
 
1107
$ cd experimental
 
1108
# Work around merging into empty branch not being supported
 
1109
# (http://pad.lv/308562)
 
1110
$ echo something >not-empty
 
1111
$ brz add
 
1112
adding not-empty
 
1113
$ brz commit -m 'Add some content in experimental'
 
1114
2>Committing to: .../experimental/
 
1115
2>added not-empty
 
1116
2>Committed revision 1.
 
1117
# merge debian even without a common ancestor
 
1118
$ brz merge ../debian -r0..2
 
1119
2>+N  dir/
 
1120
2>+N  dir/file
 
1121
2>All changes applied successfully.
 
1122
$ brz commit -m 'merging debian into experimental'
 
1123
2>Committing to: .../experimental/
 
1124
2>added dir
 
1125
2>added dir/file
 
1126
2>Committed revision 2.
 
1127
# Create an ubuntu branch with yet another root-id
 
1128
$ cd ..
 
1129
$ brz init ubuntu
 
1130
Created a standalone tree (format: 2a)
 
1131
$ cd ubuntu
 
1132
# Work around merging into empty branch not being supported
 
1133
# (http://pad.lv/308562)
 
1134
$ echo something >not-empty-ubuntu
 
1135
$ brz add
 
1136
adding not-empty-ubuntu
 
1137
$ brz commit -m 'Add some content in experimental'
 
1138
2>Committing to: .../ubuntu/
 
1139
2>added not-empty-ubuntu
 
1140
2>Committed revision 1.
 
1141
# Also merge debian
 
1142
$ brz merge ../debian -r0..2
 
1143
2>+N  dir/
 
1144
2>+N  dir/file
 
1145
2>All changes applied successfully.
 
1146
$ brz commit -m 'merging debian'
 
1147
2>Committing to: .../ubuntu/
 
1148
2>added dir
 
1149
2>added dir/file
 
1150
2>Committed revision 2.
 
1151
# Now try to merge experimental
 
1152
$ brz merge ../experimental
 
1153
2>+N  not-empty
 
1154
2>Path conflict: dir / dir
 
1155
2>1 conflicts encountered.
961
1156
""")
962
1157
 
963
1158
 
966
1161
    def setUp(self):
967
1162
        super(TestResolveActionOption, self).setUp()
968
1163
        self.options = [conflicts.ResolveActionOption()]
969
 
        self.parser = option.get_optparser(dict((o.name, o)
970
 
                                                for o in self.options))
 
1164
        self.parser = option.get_optparser(self.options)
971
1165
 
972
1166
    def parse(self, args):
973
1167
        return self.parser.parse_args(args)
974
1168
 
975
1169
    def test_unknown_action(self):
976
 
        self.assertRaises(errors.BadOptionValue,
 
1170
        self.assertRaises(option.BadOptionValue,
977
1171
                          self.parse, ['--action', 'take-me-to-the-moon'])
978
1172
 
979
1173
    def test_done(self):
980
1174
        opts, args = self.parse(['--action', 'done'])
981
 
        self.assertEqual({'action':'done'}, opts)
 
1175
        self.assertEqual({'action': 'done'}, opts)
982
1176
 
983
1177
    def test_take_this(self):
984
1178
        opts, args = self.parse(['--action', 'take-this'])