/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: Breezy landing bot
  • Author(s): Jelmer Vernooij
  • Date: 2020-08-23 01:15:41 UTC
  • mfrom: (7520.1.4 merge-3.1)
  • Revision ID: breezy.the.bot@gmail.com-20200823011541-nv0oh7nzaganx2qy
Merge lp:brz/3.1.

Merged from https://code.launchpad.net/~jelmer/brz/merge-3.1/+merge/389690

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