/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-05-24 00:42:36 UTC
  • mto: This revision was merged to the branch mainline in revision 7505.
  • Revision ID: jelmer@jelmer.uk-20200524004236-jdj6obo4k5lznqw2
Cleanup Windows functions.

Show diffs side-by-side

added added

removed removed

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