/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
4988.10.5 by John Arbash Meinel
Merge bzr.dev 5021 to resolve NEWS
1
# Copyright (C) 2005-2010 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.14.8 by Aaron Bentley
Added test_commit.py
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1185.14.8 by Aaron Bentley
Added test_commit.py
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1185.14.8 by Aaron Bentley
Added test_commit.py
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1185.14.8 by Aaron Bentley
Added test_commit.py
16
17
18
import os
19
4597.2.2 by Vincent Ladeuil
Cleanup conflict tests.
20
from bzrlib import (
4597.2.23 by Vincent Ladeuil
Start translating blackbox tests into whitebox ones.
21
    branchbuilder,
4597.2.2 by Vincent Ladeuil
Cleanup conflict tests.
22
    bzrdir,
23
    conflicts,
24
    errors,
4597.3.51 by Vincent Ladeuil
Implement conflicts.ResolveActionOption.
25
    option,
4597.2.2 by Vincent Ladeuil
Cleanup conflict tests.
26
    tests,
4597.2.23 by Vincent Ladeuil
Start translating blackbox tests into whitebox ones.
27
    workingtree,
4597.2.2 by Vincent Ladeuil
Cleanup conflict tests.
28
    )
4597.13.3 by Vincent Ladeuil
Switch to load_tests_apply_scenarios.
29
from bzrlib.tests import (
30
    script,
31
    scenarios,
32
    )
33
34
35
load_tests = scenarios.load_tests_apply_scenarios
4597.2.26 by Vincent Ladeuil
Fix bug #529968 by renaming the kept file on content conflicts.
36
37
1185.14.8 by Aaron Bentley
Added test_commit.py
38
# TODO: Test commit with some added, and added-but-missing files
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
39
# RBC 20060124 is that not tested in test_commit.py ?
1185.14.8 by Aaron Bentley
Added test_commit.py
40
1666.1.4 by Robert Collins
* 'Metadir' is now the default disk format. This improves behaviour in
41
# The order of 'path' here is important - do not let it
42
# be a sorted list.
2309.4.13 by John Arbash Meinel
Conflicts go through Stanza so the need to be aware of utf8 versus unicode file ids.
43
# u'\xe5' == a with circle
44
# '\xc3\xae' == u'\xee' == i with hat
4597.2.2 by Vincent Ladeuil
Cleanup conflict tests.
45
# So these are u'path' and 'id' only with a circle and a hat. (shappo?)
46
example_conflicts = conflicts.ConflictList(
47
    [conflicts.MissingParent('Not deleting', u'p\xe5thg', '\xc3\xaedg'),
48
     conflicts.ContentsConflict(u'p\xe5tha', None, '\xc3\xaeda'),
49
     conflicts.TextConflict(u'p\xe5tha'),
50
     conflicts.PathConflict(u'p\xe5thb', u'p\xe5thc', '\xc3\xaedb'),
51
     conflicts.DuplicateID('Unversioned existing file',
52
                           u'p\xe5thc', u'p\xe5thc2',
53
                           '\xc3\xaedc', '\xc3\xaedc'),
54
    conflicts.DuplicateEntry('Moved existing file to',
55
                             u'p\xe5thdd.moved', u'p\xe5thd',
56
                             '\xc3\xaedd', None),
57
    conflicts.ParentLoop('Cancelled move', u'p\xe5the', u'p\xe5th2e',
58
                         None, '\xc3\xaed2e'),
59
    conflicts.UnversionedParent('Versioned directory',
60
                                u'p\xe5thf', '\xc3\xaedf'),
61
    conflicts.NonDirectoryParent('Created directory',
62
                                 u'p\xe5thg', '\xc3\xaedg'),
1534.10.22 by Aaron Bentley
Got ConflictList implemented
63
])
1534.10.4 by Aaron Bentley
Implemented conflict serialization
64
65
4597.2.2 by Vincent Ladeuil
Cleanup conflict tests.
66
class TestConflicts(tests.TestCaseWithTransport):
1185.14.8 by Aaron Bentley
Added test_commit.py
67
68
    def test_conflicts(self):
69
        """Conflicts are detected properly"""
4597.2.3 by Vincent Ladeuil
More cleanup.
70
        # Use BzrDirFormat6 so we can fake conflicts
71
        tree = self.make_branch_and_tree('.', format=bzrdir.BzrDirFormat6())
72
        self.build_tree_contents([('hello', 'hello world4'),
73
                                  ('hello.THIS', 'hello world2'),
74
                                  ('hello.BASE', 'hello world1'),
75
                                  ('hello.OTHER', 'hello world3'),
76
                                  ('hello.sploo.BASE', 'yellowworld'),
77
                                  ('hello.sploo.OTHER', 'yellowworld2'),
78
                                  ])
2255.2.61 by John Arbash Meinel
Find callers of list_files() and make sure the tree is always locked.
79
        tree.lock_read()
4597.2.28 by Vincent Ladeuil
Use assertLength where appropriate.
80
        self.assertLength(6, list(tree.list_files()))
2255.2.61 by John Arbash Meinel
Find callers of list_files() and make sure the tree is always locked.
81
        tree.unlock()
4597.2.3 by Vincent Ladeuil
More cleanup.
82
        tree_conflicts = tree.conflicts()
4597.2.28 by Vincent Ladeuil
Use assertLength where appropriate.
83
        self.assertLength(2, tree_conflicts)
4597.2.3 by Vincent Ladeuil
More cleanup.
84
        self.assertTrue('hello' in tree_conflicts[0].path)
85
        self.assertTrue('hello.sploo' in tree_conflicts[1].path)
86
        conflicts.restore('hello')
87
        conflicts.restore('hello.sploo')
4597.2.28 by Vincent Ladeuil
Use assertLength where appropriate.
88
        self.assertLength(0, tree.conflicts())
1185.35.1 by Aaron Bentley
Implemented conflicts.restore
89
        self.assertFileEqual('hello world2', 'hello')
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
90
        self.assertFalse(os.path.lexists('hello.sploo'))
4597.2.3 by Vincent Ladeuil
More cleanup.
91
        self.assertRaises(errors.NotConflicted, conflicts.restore, 'hello')
92
        self.assertRaises(errors.NotConflicted,
93
                          conflicts.restore, 'hello.sploo')
1534.10.4 by Aaron Bentley
Implemented conflict serialization
94
1558.12.9 by Aaron Bentley
Handle resolving conflicts with directories properly
95
    def test_resolve_conflict_dir(self):
96
        tree = self.make_branch_and_tree('.')
4597.2.3 by Vincent Ladeuil
More cleanup.
97
        self.build_tree_contents([('hello', 'hello world4'),
98
                                  ('hello.THIS', 'hello world2'),
99
                                  ('hello.BASE', 'hello world1'),
100
                                  ])
101
        os.mkdir('hello.OTHER')
1558.12.9 by Aaron Bentley
Handle resolving conflicts with directories properly
102
        tree.add('hello', 'q')
4597.2.3 by Vincent Ladeuil
More cleanup.
103
        l = conflicts.ConflictList([conflicts.TextConflict('hello')])
1558.12.9 by Aaron Bentley
Handle resolving conflicts with directories properly
104
        l.remove_files(tree)
105
1551.15.58 by Aaron Bentley
Status honours selected paths for conflicts (#127606)
106
    def test_select_conflicts(self):
107
        tree = self.make_branch_and_tree('.')
4597.2.3 by Vincent Ladeuil
More cleanup.
108
        clist = conflicts.ConflictList
109
110
        def check_select(not_selected, selected, paths, **kwargs):
111
            self.assertEqual(
112
                (not_selected, selected),
113
                tree_conflicts.select_conflicts(tree, paths, **kwargs))
114
115
        foo = conflicts.ContentsConflict('foo')
116
        bar = conflicts.ContentsConflict('bar')
117
        tree_conflicts = clist([foo, bar])
118
119
        check_select(clist([bar]), clist([foo]), ['foo'])
120
        check_select(clist(), tree_conflicts,
121
                     [''], ignore_misses=True, recurse=True)
122
123
        foobaz  = conflicts.ContentsConflict('foo/baz')
124
        tree_conflicts = clist([foobaz, bar])
125
126
        check_select(clist([bar]), clist([foobaz]),
127
                     ['foo'], ignore_misses=True, recurse=True)
128
129
        qux = conflicts.PathConflict('qux', 'foo/baz')
130
        tree_conflicts = clist([qux])
131
132
        check_select(clist(), tree_conflicts,
133
                     ['foo'], ignore_misses=True, recurse=True)
134
        check_select (tree_conflicts, clist(), ['foo'], ignore_misses=True)
1551.15.58 by Aaron Bentley
Status honours selected paths for conflicts (#127606)
135
3017.2.1 by Aaron Bentley
Revert now resolves conflicts recursively (#102739)
136
    def test_resolve_conflicts_recursive(self):
137
        tree = self.make_branch_and_tree('.')
138
        self.build_tree(['dir/', 'dir/hello'])
139
        tree.add(['dir', 'dir/hello'])
4597.2.3 by Vincent Ladeuil
More cleanup.
140
141
        dirhello = conflicts.ConflictList([conflicts.TextConflict('dir/hello')])
142
        tree.set_conflicts(dirhello)
143
144
        conflicts.resolve(tree, ['dir'], recursive=False, ignore_misses=True)
145
        self.assertEqual(dirhello, tree.conflicts())
146
147
        conflicts.resolve(tree, ['dir'], recursive=True, ignore_misses=True)
148
        self.assertEqual(conflicts.ConflictList([]), tree.conflicts())
4773.1.1 by Vincent Ladeuil
Cleanup imports in test_conflicts
149
150
4597.3.43 by Vincent Ladeuil
Cleanups, ready to record.
151
class TestConflictStanzas(tests.TestCase):
152
153
    def test_stanza_roundtrip(self):
154
        # write and read our example stanza.
155
        stanza_iter = example_conflicts.to_stanzas()
156
        processed = conflicts.ConflictList.from_stanzas(stanza_iter)
157
        for o, p in zip(processed, example_conflicts):
158
            self.assertEqual(o, p)
159
160
            self.assertIsInstance(o.path, unicode)
161
162
            if o.file_id is not None:
163
                self.assertIsInstance(o.file_id, str)
164
165
            conflict_path = getattr(o, 'conflict_path', None)
166
            if conflict_path is not None:
167
                self.assertIsInstance(conflict_path, unicode)
168
169
            conflict_file_id = getattr(o, 'conflict_file_id', None)
170
            if conflict_file_id is not None:
171
                self.assertIsInstance(conflict_file_id, str)
172
173
    def test_stanzification(self):
174
        for stanza in example_conflicts.to_stanzas():
175
            if 'file_id' in stanza:
176
                # In Stanza form, the file_id has to be unicode.
177
                self.assertStartsWith(stanza['file_id'], u'\xeed')
178
            self.assertStartsWith(stanza['path'], u'p\xe5th')
179
            if 'conflict_path' in stanza:
180
                self.assertStartsWith(stanza['conflict_path'], u'p\xe5th')
181
            if 'conflict_file_id' in stanza:
182
                self.assertStartsWith(stanza['conflict_file_id'], u'\xeed')
183
184
4597.3.74 by Vincent Ladeuil
Add a FIXME about rewriting shell-like tests into real whitebox tests.
185
# FIXME: The shell-like tests should be converted to real whitebox tests... or
186
# moved to a blackbox module -- vila 20100205
187
4597.7.11 by Vincent Ladeuil
Fix #531967 by creating helpers for PathConflicts when a deletion
188
# FIXME: test missing for multiple conflicts
189
4597.3.31 by Vincent Ladeuil
Implement --interactive for MissingParent.
190
# FIXME: Tests missing for DuplicateID conflict type
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
191
class TestResolveConflicts(script.TestCaseWithTransportAndScript):
192
193
    preamble = None # The setup script set by daughter classes
194
195
    def setUp(self):
196
        super(TestResolveConflicts, self).setUp()
197
        self.run_script(self.preamble)
198
199
4597.10.11 by Vincent Ladeuil
Turn mirror_scenarios into a simple function.
200
def mirror_scenarios(base_scenarios):
201
    """Return a list of mirrored scenarios.
202
203
    Each scenario in base_scenarios is duplicated switching the roles of 'this'
204
    and 'other'
205
    """
206
    scenarios = []
4597.10.14 by Vincent Ladeuil
Some more cleanup and typos.
207
    for common, (lname, ldict), (rname, rdict) in base_scenarios:
4597.10.11 by Vincent Ladeuil
Turn mirror_scenarios into a simple function.
208
        a = tests.multiply_scenarios([(lname, dict(_this=ldict))],
209
                                     [(rname, dict(_other=rdict))])
210
        b = tests.multiply_scenarios([(rname, dict(_this=rdict))],
211
                                     [(lname, dict(_other=ldict))])
212
        # Inject the common parameters in all scenarios
213
        for name, d in a + b:
214
            d.update(common)
215
        scenarios.extend(a + b)
216
    return scenarios
217
218
4597.7.10 by Vincent Ladeuil
Define scenarios by test classes.
219
# FIXME: Get rid of parametrized (in the class name) once we delete
220
# TestResolveConflicts -- vila 20100308
4597.7.4 by Vincent Ladeuil
Abstract the test class some more to address more conflict
221
class TestParametrizedResolveConflicts(tests.TestCaseWithTransport):
4597.7.18 by Vincent Ladeuil
Start addressing Andrew's concerns.
222
    """This class provides a base to test single conflict resolution.
223
4597.10.7 by Vincent Ladeuil
Simplify scenarios mirroring and give a better docstring for TestParametrizedResolveConflicts.
224
    Since all conflict objects are created with specific semantics for their
225
    attributes, each class should implement the necessary functions and
226
    attributes described below.
227
228
    Each class should define the scenarios that create the expected (single)
229
    conflict.
230
231
    Each scenario describes:
232
    * how to create 'base' tree (and revision)
233
    * how to create 'left' tree (and revision, parent rev 'base')
234
    * how to create 'right' tree (and revision, parent rev 'base')
235
    * how to check that changes in 'base'->'left' have been taken
236
    * how to check that changes in 'base'->'right' have been taken
237
238
    From each base scenario, we generate two concrete scenarios where:
239
    * this=left, other=right
240
    * this=right, other=left
241
242
    Then the test case verifies each concrete scenario by:
243
    * creating a branch containing the 'base', 'this' and 'other' revisions
244
    * creating a working tree for the 'this' revision
245
    * performing the merge of 'other' into 'this'
246
    * verifying the expected conflict was generated
247
    * resolving with --take-this or --take-other, and running the corresponding
248
      checks (for either 'base'->'this', or 'base'->'other')
249
250
    :cvar _conflict_type: The expected class of the generated conflict.
251
252
    :cvar _assert_conflict: A method receiving the working tree and the
253
        conflict object and checking its attributes.
254
4597.10.9 by Vincent Ladeuil
More doc.
255
    :cvar _base_actions: The branchbuilder actions to create the 'base'
256
        revision.
257
258
    :cvar _this: The dict related to 'base' -> 'this'. It contains at least:
259
      * 'actions': The branchbuilder actions to create the 'this'
260
          revision.
4597.10.10 by Vincent Ladeuil
Fix typo.
261
      * 'check': how to check the changes after resolution with --take-this.
4597.10.9 by Vincent Ladeuil
More doc.
262
263
    :cvar _other: The dict related to 'base' -> 'other'. It contains at least:
264
      * 'actions': The branchbuilder actions to create the 'other'
265
          revision.
4597.10.10 by Vincent Ladeuil
Fix typo.
266
      * 'check': how to check the changes after resolution with --take-other.
4597.7.18 by Vincent Ladeuil
Start addressing Andrew's concerns.
267
    """
4597.2.23 by Vincent Ladeuil
Start translating blackbox tests into whitebox ones.
268
4597.7.16 by Vincent Ladeuil
Some cleanup.
269
    # Set by daughter classes
270
    _conflict_type = None
271
    _assert_conflict = None
272
4597.2.26 by Vincent Ladeuil
Fix bug #529968 by renaming the kept file on content conflicts.
273
    # Set by load_tests
4597.7.6 by Vincent Ladeuil
Cleanup TestParametrizedResolveConflicts some more.
274
    _base_actions = None
4597.10.7 by Vincent Ladeuil
Simplify scenarios mirroring and give a better docstring for TestParametrizedResolveConflicts.
275
    _this = None
276
    _other = None
4597.7.7 by Vincent Ladeuil
Reproduce bug #531967 on various aspects.
277
4597.13.3 by Vincent Ladeuil
Switch to load_tests_apply_scenarios.
278
    scenarios = []
279
    """The scenario list for the conflict type defined by the class.
280
281
    Each scenario is of the form:
282
    (common, (left_name, left_dict), (right_name, right_dict))
283
284
    * common is a dict
285
286
    * left_name and right_name are the scenario names that will be combined
287
288
    * left_dict and right_dict are the attributes specific to each half of
289
      the scenario. They should include at least 'actions' and 'check' and
290
      will be available as '_this' and '_other' test instance attributes.
291
292
    Daughters classes are free to add their specific attributes as they see
293
    fit in any of the three dicts.
294
295
    This is a class method so that load_tests can find it.
296
297
    '_base_actions' in the common dict, 'actions' and 'check' in the left
298
    and right dicts use names that map to methods in the test classes. Some
299
    prefixes are added to these names to get the correspong methods (see
300
    _get_actions() and _get_check()). The motivation here is to avoid
301
    collisions in the class namespace.
302
    """
4597.7.10 by Vincent Ladeuil
Define scenarios by test classes.
303
4597.2.23 by Vincent Ladeuil
Start translating blackbox tests into whitebox ones.
304
    def setUp(self):
4597.7.4 by Vincent Ladeuil
Abstract the test class some more to address more conflict
305
        super(TestParametrizedResolveConflicts, self).setUp()
4597.2.23 by Vincent Ladeuil
Start translating blackbox tests into whitebox ones.
306
        builder = self.make_branch_builder('trunk')
307
        builder.start_series()
4597.7.6 by Vincent Ladeuil
Cleanup TestParametrizedResolveConflicts some more.
308
4597.2.23 by Vincent Ladeuil
Start translating blackbox tests into whitebox ones.
309
        # Create an empty trunk
310
        builder.build_snapshot('start', None, [
311
                ('add', ('', 'root-id', 'directory', ''))])
312
        # Add a minimal base content
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
313
        base_actions = self._get_actions(self._base_actions)()
4597.10.7 by Vincent Ladeuil
Simplify scenarios mirroring and give a better docstring for TestParametrizedResolveConflicts.
314
        builder.build_snapshot('base', ['start'], base_actions)
4597.2.23 by Vincent Ladeuil
Start translating blackbox tests into whitebox ones.
315
        # Modify the base content in branch
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
316
        actions_other = self._get_actions(self._other['actions'])()
4597.7.10 by Vincent Ladeuil
Define scenarios by test classes.
317
        builder.build_snapshot('other', ['base'], actions_other)
4597.2.23 by Vincent Ladeuil
Start translating blackbox tests into whitebox ones.
318
        # Modify the base content in trunk
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
319
        actions_this = self._get_actions(self._this['actions'])()
4597.7.10 by Vincent Ladeuil
Define scenarios by test classes.
320
        builder.build_snapshot('this', ['base'], actions_this)
4597.7.7 by Vincent Ladeuil
Reproduce bug #531967 on various aspects.
321
        # builder.get_branch() tip is now 'this'
4597.7.6 by Vincent Ladeuil
Cleanup TestParametrizedResolveConflicts some more.
322
4597.2.23 by Vincent Ladeuil
Start translating blackbox tests into whitebox ones.
323
        builder.finish_series()
324
        self.builder = builder
325
4597.2.26 by Vincent Ladeuil
Fix bug #529968 by renaming the kept file on content conflicts.
326
    def _get_actions(self, name):
327
        return getattr(self, 'do_%s' % name)
328
329
    def _get_check(self, name):
330
        return getattr(self, 'check_%s' % name)
331
4597.2.24 by Vincent Ladeuil
Translate one more test.
332
    def _merge_other_into_this(self):
4597.2.23 by Vincent Ladeuil
Start translating blackbox tests into whitebox ones.
333
        b = self.builder.get_branch()
334
        wt = b.bzrdir.sprout('branch').open_workingtree()
335
        wt.merge_from_branch(b, 'other')
4597.2.24 by Vincent Ladeuil
Translate one more test.
336
        return wt
337
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
338
    def assertConflict(self, wt):
339
        confs = wt.conflicts()
340
        self.assertLength(1, confs)
341
        c = confs[0]
342
        self.assertIsInstance(c, self._conflict_type)
343
        self._assert_conflict(wt, c)
344
345
    def _get_resolve_path_arg(self, wt, action):
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
346
        raise NotImplementedError(self._get_resolve_path_arg)
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
347
348
    def check_resolved(self, wt, action):
349
        path = self._get_resolve_path_arg(wt, action)
350
        conflicts.resolve(wt, [path], action=action)
351
        # Check that we don't have any conflicts nor unknown left
352
        self.assertLength(0, wt.conflicts())
353
        self.assertLength(0, list(wt.unknowns()))
354
4597.2.24 by Vincent Ladeuil
Translate one more test.
355
    def test_resolve_taking_this(self):
356
        wt = self._merge_other_into_this()
4597.7.7 by Vincent Ladeuil
Reproduce bug #531967 on various aspects.
357
        self.assertConflict(wt)
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
358
        self.check_resolved(wt, 'take_this')
4597.10.7 by Vincent Ladeuil
Simplify scenarios mirroring and give a better docstring for TestParametrizedResolveConflicts.
359
        check_this = self._get_check(self._this['check'])
4597.2.26 by Vincent Ladeuil
Fix bug #529968 by renaming the kept file on content conflicts.
360
        check_this()
4597.2.24 by Vincent Ladeuil
Translate one more test.
361
362
    def test_resolve_taking_other(self):
363
        wt = self._merge_other_into_this()
4597.7.7 by Vincent Ladeuil
Reproduce bug #531967 on various aspects.
364
        self.assertConflict(wt)
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
365
        self.check_resolved(wt, 'take_other')
4597.10.7 by Vincent Ladeuil
Simplify scenarios mirroring and give a better docstring for TestParametrizedResolveConflicts.
366
        check_other = self._get_check(self._other['check'])
4597.2.26 by Vincent Ladeuil
Fix bug #529968 by renaming the kept file on content conflicts.
367
        check_other()
4597.3.28 by Vincent Ladeuil
Implement --interactive for ContentsConflict.
368
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
369
4597.14.2 by Vincent Ladeuil
Implements --take-this and --take-other when resolving text conflicts
370
class TestResolveTextConflicts(TestParametrizedResolveConflicts):
371
372
    _conflict_type = conflicts.TextConflict
373
374
    # Set by the scenarios
375
    # path and file-id for the file involved in the conflict
376
    _path = None
377
    _file_id = None
378
379
    scenarios = mirror_scenarios(
380
        [
381
            # File modified/deleted
382
            (dict(_base_actions='create_file',
383
                  _path='file', _file_id='file-id'),
384
             ('filed_modified_A',
385
              dict(actions='modify_file_A', check='file_has_content_A')),
386
             ('file_modified_B',
387
              dict(actions='modify_file_B', check='file_has_content_B')),),
388
            ])
389
390
    def do_create_file(self):
391
        return [('add', ('file', 'file-id', 'file', 'trunk content\n'))]
392
393
    def do_modify_file_A(self):
394
        return [('modify', ('file-id', 'trunk content\nfeature A\n'))]
395
396
    def do_modify_file_B(self):
397
        return [('modify', ('file-id', 'trunk content\nfeature B\n'))]
398
399
    def check_file_has_content_A(self):
400
        self.assertFileEqual('trunk content\nfeature A\n', 'branch/file')
401
402
    def check_file_has_content_B(self):
403
        self.assertFileEqual('trunk content\nfeature B\n', 'branch/file')
404
405
    def _get_resolve_path_arg(self, wt, action):
406
        return self._path
407
408
    def assertTextConflict(self, wt, c):
409
        self.assertEqual(self._file_id, c.file_id)
410
        self.assertEqual(self._path, c.path)
411
    _assert_conflict = assertTextConflict
412
413
4597.7.10 by Vincent Ladeuil
Define scenarios by test classes.
414
class TestResolveContentsConflict(TestParametrizedResolveConflicts):
415
4597.13.3 by Vincent Ladeuil
Switch to load_tests_apply_scenarios.
416
    _conflict_type = conflicts.ContentsConflict
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
417
4597.13.3 by Vincent Ladeuil
Switch to load_tests_apply_scenarios.
418
    # Set by the scenarios
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
419
    # path and file-id for the file involved in the conflict
420
    _path = None
421
    _file_id = None
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
422
4597.13.3 by Vincent Ladeuil
Switch to load_tests_apply_scenarios.
423
    scenarios = mirror_scenarios(
424
        [
4597.10.12 by Vincent Ladeuil
Some more doc.
425
            # File modified/deleted
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
426
            (dict(_base_actions='create_file',
427
                  _path='file', _file_id='file-id'),
4597.10.12 by Vincent Ladeuil
Some more doc.
428
             ('file_modified',
429
              dict(actions='modify_file', check='file_has_more_content')),
430
             ('file_deleted',
431
              dict(actions='delete_file', check='file_doesnt_exist')),),
4597.13.3 by Vincent Ladeuil
Switch to load_tests_apply_scenarios.
432
            ])
4597.7.10 by Vincent Ladeuil
Define scenarios by test classes.
433
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
434
    def do_create_file(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
435
        return [('add', ('file', 'file-id', 'file', 'trunk content\n'))]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
436
437
    def do_modify_file(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
438
        return [('modify', ('file-id', 'trunk content\nmore content\n'))]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
439
440
    def check_file_has_more_content(self):
441
        self.assertFileEqual('trunk content\nmore content\n', 'branch/file')
442
443
    def do_delete_file(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
444
        return [('unversion', 'file-id')]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
445
446
    def check_file_doesnt_exist(self):
447
        self.failIfExists('branch/file')
448
449
    def _get_resolve_path_arg(self, wt, action):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
450
        return self._path
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
451
4597.7.17 by Vincent Ladeuil
Add a scenario and activate the compatibility tests.
452
    def assertContentsConflict(self, wt, c):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
453
        self.assertEqual(self._file_id, c.file_id)
454
        self.assertEqual(self._path, c.path)
4597.7.16 by Vincent Ladeuil
Some cleanup.
455
    _assert_conflict = assertContentsConflict
456
4597.7.10 by Vincent Ladeuil
Define scenarios by test classes.
457
458
class TestResolvePathConflict(TestParametrizedResolveConflicts):
459
4597.13.3 by Vincent Ladeuil
Switch to load_tests_apply_scenarios.
460
    _conflict_type = conflicts.PathConflict
4597.7.16 by Vincent Ladeuil
Some cleanup.
461
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
462
    def do_nothing(self):
463
        return []
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
464
4597.13.3 by Vincent Ladeuil
Switch to load_tests_apply_scenarios.
465
    # Each side dict additionally defines:
466
    # - path path involved (can be '<deleted>')
467
    # - file-id involved
468
    scenarios = mirror_scenarios(
469
        [
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
470
            # File renamed/deleted
471
            (dict(_base_actions='create_file'),
472
             ('file_renamed',
473
              dict(actions='rename_file', check='file_renamed',
474
                   path='new-file', file_id='file-id')),
4597.7.17 by Vincent Ladeuil
Add a scenario and activate the compatibility tests.
475
             ('file_deleted',
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
476
              dict(actions='delete_file', check='file_doesnt_exist',
477
                   # PathConflicts deletion handling requires a special
478
                   # hard-coded value
479
                   path='<deleted>', file_id='file-id')),),
480
            # File renamed/renamed differently
481
            (dict(_base_actions='create_file'),
482
             ('file_renamed',
483
              dict(actions='rename_file', check='file_renamed',
484
                   path='new-file', file_id='file-id')),
4597.8.4 by Vincent Ladeuil
Delete PathConflict bloackbox tests.
485
             ('file_renamed2',
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
486
              dict(actions='rename_file2', check='file_renamed2',
487
                   path='new-file2', file_id='file-id')),),
488
            # Dir renamed/deleted
489
            (dict(_base_actions='create_dir'),
490
             ('dir_renamed',
491
              dict(actions='rename_dir', check='dir_renamed',
492
                   path='new-dir', file_id='dir-id')),
4597.7.17 by Vincent Ladeuil
Add a scenario and activate the compatibility tests.
493
             ('dir_deleted',
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
494
              dict(actions='delete_dir', check='dir_doesnt_exist',
495
                   # PathConflicts deletion handling requires a special
496
                   # hard-coded value
497
                   path='<deleted>', file_id='dir-id')),),
498
            # Dir renamed/renamed differently
499
            (dict(_base_actions='create_dir'),
500
             ('dir_renamed',
501
              dict(actions='rename_dir', check='dir_renamed',
502
                   path='new-dir', file_id='dir-id')),
4597.7.17 by Vincent Ladeuil
Add a scenario and activate the compatibility tests.
503
             ('dir_renamed2',
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
504
              dict(actions='rename_dir2', check='dir_renamed2',
505
                   path='new-dir2', file_id='dir-id')),),
4597.13.3 by Vincent Ladeuil
Switch to load_tests_apply_scenarios.
506
            ])
4597.7.17 by Vincent Ladeuil
Add a scenario and activate the compatibility tests.
507
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
508
    def do_create_file(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
509
        return [('add', ('file', 'file-id', 'file', 'trunk content\n'))]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
510
511
    def do_create_dir(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
512
        return [('add', ('dir', 'dir-id', 'directory', ''))]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
513
514
    def do_rename_file(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
515
        return [('rename', ('file', 'new-file'))]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
516
517
    def check_file_renamed(self):
518
        self.failIfExists('branch/file')
519
        self.failUnlessExists('branch/new-file')
520
521
    def do_rename_file2(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
522
        return [('rename', ('file', 'new-file2'))]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
523
524
    def check_file_renamed2(self):
525
        self.failIfExists('branch/file')
526
        self.failUnlessExists('branch/new-file2')
527
528
    def do_rename_dir(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
529
        return [('rename', ('dir', 'new-dir'))]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
530
531
    def check_dir_renamed(self):
532
        self.failIfExists('branch/dir')
533
        self.failUnlessExists('branch/new-dir')
534
535
    def do_rename_dir2(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
536
        return [('rename', ('dir', 'new-dir2'))]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
537
538
    def check_dir_renamed2(self):
539
        self.failIfExists('branch/dir')
540
        self.failUnlessExists('branch/new-dir2')
541
4597.7.17 by Vincent Ladeuil
Add a scenario and activate the compatibility tests.
542
    def do_delete_file(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
543
        return [('unversion', 'file-id')]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
544
545
    def check_file_doesnt_exist(self):
546
        self.failIfExists('branch/file')
547
548
    def do_delete_dir(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
549
        return [('unversion', 'dir-id')]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
550
551
    def check_dir_doesnt_exist(self):
552
        self.failIfExists('branch/dir')
553
554
    def _get_resolve_path_arg(self, wt, action):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
555
        tpath = self._this['path']
556
        opath = self._other['path']
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
557
        if tpath == '<deleted>':
558
            path = opath
559
        else:
560
            path = tpath
561
        return path
4597.7.17 by Vincent Ladeuil
Add a scenario and activate the compatibility tests.
562
563
    def assertPathConflict(self, wt, c):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
564
        tpath = self._this['path']
565
        tfile_id = self._this['file_id']
566
        opath = self._other['path']
567
        ofile_id = self._other['file_id']
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
568
        self.assertEqual(tfile_id, ofile_id) # Sanity check
569
        self.assertEqual(tfile_id, c.file_id)
570
        self.assertEqual(tpath, c.path)
571
        self.assertEqual(opath, c.conflict_path)
4597.7.16 by Vincent Ladeuil
Some cleanup.
572
    _assert_conflict = assertPathConflict
4597.7.10 by Vincent Ladeuil
Define scenarios by test classes.
573
574
4597.7.17 by Vincent Ladeuil
Add a scenario and activate the compatibility tests.
575
class TestResolvePathConflictBefore531967(TestResolvePathConflict):
4597.7.10 by Vincent Ladeuil
Define scenarios by test classes.
576
    """Same as TestResolvePathConflict but a specific conflict object.
577
    """
578
4597.7.16 by Vincent Ladeuil
Some cleanup.
579
    def assertPathConflict(self, c):
4597.7.17 by Vincent Ladeuil
Add a scenario and activate the compatibility tests.
580
        # We create a conflict object as it was created before the fix and
581
        # inject it into the working tree, the test will exercise the
582
        # compatibility code.
583
        old_c = conflicts.PathConflict('<deleted>', self._item_path,
584
                                       file_id=None)
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
585
        wt.set_conflicts(conflicts.ConflictList([old_c]))
4597.7.10 by Vincent Ladeuil
Define scenarios by test classes.
586
587
4597.8.5 by Vincent Ladeuil
Replace DuplicateEntry blackbox tests by whitebox ones.
588
class TestResolveDuplicateEntry(TestParametrizedResolveConflicts):
589
4597.13.3 by Vincent Ladeuil
Switch to load_tests_apply_scenarios.
590
    _conflict_type = conflicts.DuplicateEntry
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
591
4597.13.3 by Vincent Ladeuil
Switch to load_tests_apply_scenarios.
592
    scenarios = mirror_scenarios(
593
        [
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
594
            # File created with different file-ids
595
            (dict(_base_actions='nothing'),
596
             ('filea_created',
597
              dict(actions='create_file_a', check='file_content_a',
598
                   path='file', file_id='file-a-id')),
599
             ('fileb_created',
600
              dict(actions='create_file_b', check='file_content_b',
601
                   path='file', file_id='file-b-id')),),
4597.13.3 by Vincent Ladeuil
Switch to load_tests_apply_scenarios.
602
            ])
4597.8.5 by Vincent Ladeuil
Replace DuplicateEntry blackbox tests by whitebox ones.
603
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
604
    def do_nothing(self):
605
        return []
606
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
607
    def do_create_file_a(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
608
        return [('add', ('file', 'file-a-id', 'file', 'file a content\n'))]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
609
610
    def check_file_content_a(self):
611
        self.assertFileEqual('file a content\n', 'branch/file')
612
613
    def do_create_file_b(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
614
        return [('add', ('file', 'file-b-id', 'file', 'file b content\n'))]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
615
616
    def check_file_content_b(self):
617
        self.assertFileEqual('file b content\n', 'branch/file')
618
619
    def _get_resolve_path_arg(self, wt, action):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
620
        return self._this['path']
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
621
4597.8.5 by Vincent Ladeuil
Replace DuplicateEntry blackbox tests by whitebox ones.
622
    def assertDuplicateEntry(self, wt, c):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
623
        tpath = self._this['path']
624
        tfile_id = self._this['file_id']
625
        opath = self._other['path']
626
        ofile_id = self._other['file_id']
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
627
        self.assertEqual(tpath, opath) # Sanity check
628
        self.assertEqual(tfile_id, c.file_id)
629
        self.assertEqual(tpath + '.moved', c.path)
630
        self.assertEqual(tpath, c.conflict_path)
4597.8.5 by Vincent Ladeuil
Replace DuplicateEntry blackbox tests by whitebox ones.
631
    _assert_conflict = assertDuplicateEntry
4597.3.19 by Vincent Ladeuil
Some failing tests.
632
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
633
634
class TestResolveUnversionedParent(TestResolveConflicts):
635
4597.3.29 by Vincent Ladeuil
Fix bogus tests.
636
    # FIXME: Add the reverse tests: dir deleted in trunk, file added in branch
637
4597.3.30 by Vincent Ladeuil
Light changes learned while starting to understand multiple conflicts on
638
    # FIXME: While this *creates* UnversionedParent conflicts, this really only
639
    # tests MissingParent resolution :-/
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
640
    preamble = """
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
641
$ bzr init trunk
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
642
...
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
643
$ cd trunk
4597.3.29 by Vincent Ladeuil
Fix bogus tests.
644
$ mkdir dir
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
645
$ bzr add -q dir
646
$ bzr commit -m 'Create trunk' -q
4597.3.29 by Vincent Ladeuil
Fix bogus tests.
647
$ echo 'trunk content' >dir/file
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
648
$ bzr add -q dir/file
649
$ bzr commit -q -m 'Add dir/file in trunk'
650
$ bzr branch -q . -r 1 ../branch
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
651
$ cd ../branch
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
652
$ bzr rm dir -q
653
$ bzr commit -q -m 'Remove dir in branch'
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
654
$ bzr merge ../trunk
4597.3.29 by Vincent Ladeuil
Fix bogus tests.
655
2>+N  dir/
656
2>+N  dir/file
657
2>Conflict adding files to dir.  Created directory.
658
2>Conflict because dir is not versioned, but has versioned children.  Versioned directory.
659
2>2 conflicts encountered.
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
660
"""
661
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
662
    def test_take_this(self):
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
663
        self.run_script("""
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
664
$ bzr rm -q dir  --force
4597.3.29 by Vincent Ladeuil
Fix bogus tests.
665
$ bzr resolve dir
4597.9.19 by Vincent Ladeuil
resolve now reports conflicts resolved/remaining.
666
2>2 conflict(s) resolved, 0 remaining
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
667
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
668
""")
669
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
670
    def test_take_other(self):
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
671
        self.run_script("""
4597.3.29 by Vincent Ladeuil
Fix bogus tests.
672
$ bzr resolve dir
4597.9.19 by Vincent Ladeuil
resolve now reports conflicts resolved/remaining.
673
2>2 conflict(s) resolved, 0 remaining
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
674
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
675
""")
676
677
678
class TestResolveMissingParent(TestResolveConflicts):
679
680
    preamble = """
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
681
$ bzr init trunk
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
682
...
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
683
$ cd trunk
684
$ mkdir dir
685
$ echo 'trunk content' >dir/file
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
686
$ bzr add -q
687
$ bzr commit -m 'Create trunk' -q
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
688
$ echo 'trunk content' >dir/file2
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
689
$ bzr add -q dir/file2
690
$ bzr commit -q -m 'Add dir/file2 in branch'
691
$ bzr branch -q . -r 1 ../branch
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
692
$ cd ../branch
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
693
$ bzr rm -q dir/file --force
694
$ bzr rm -q dir
695
$ bzr commit -q -m 'Remove dir/file'
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
696
$ bzr merge ../trunk
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
697
2>+N  dir/
698
2>+N  dir/file2
699
2>Conflict adding files to dir.  Created directory.
700
2>Conflict because dir is not versioned, but has versioned children.  Versioned directory.
701
2>2 conflicts encountered.
702
"""
703
704
    def test_keep_them_all(self):
705
        self.run_script("""
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
706
$ bzr resolve dir
4597.9.19 by Vincent Ladeuil
resolve now reports conflicts resolved/remaining.
707
2>2 conflict(s) resolved, 0 remaining
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
708
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
709
""")
710
711
    def test_adopt_child(self):
712
        self.run_script("""
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
713
$ bzr mv -q dir/file2 file2
714
$ bzr rm -q dir --force
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
715
$ bzr resolve dir
4597.9.19 by Vincent Ladeuil
resolve now reports conflicts resolved/remaining.
716
2>2 conflict(s) resolved, 0 remaining
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
717
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
718
""")
719
720
    def test_kill_them_all(self):
721
        self.run_script("""
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
722
$ bzr rm -q dir --force
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
723
$ bzr resolve dir
4597.9.19 by Vincent Ladeuil
resolve now reports conflicts resolved/remaining.
724
2>2 conflict(s) resolved, 0 remaining
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
725
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
726
""")
727
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
728
    def test_resolve_taking_this(self):
4597.3.31 by Vincent Ladeuil
Implement --interactive for MissingParent.
729
        self.run_script("""
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
730
$ bzr resolve --take-this dir
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
731
2>...
732
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
4597.3.31 by Vincent Ladeuil
Implement --interactive for MissingParent.
733
""")
734
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
735
    def test_resolve_taking_other(self):
4597.3.31 by Vincent Ladeuil
Implement --interactive for MissingParent.
736
        self.run_script("""
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
737
$ bzr resolve --take-other dir
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
738
2>...
739
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
4597.3.31 by Vincent Ladeuil
Implement --interactive for MissingParent.
740
""")
741
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
742
743
class TestResolveDeletingParent(TestResolveConflicts):
744
745
    preamble = """
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
746
$ bzr init trunk
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
747
...
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
748
$ cd trunk
749
$ mkdir dir
750
$ echo 'trunk content' >dir/file
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
751
$ bzr add -q
752
$ bzr commit -m 'Create trunk' -q
753
$ bzr rm -q dir/file --force
754
$ bzr rm -q dir --force
755
$ bzr commit -q -m 'Remove dir/file'
756
$ bzr branch -q . -r 1 ../branch
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
757
$ cd ../branch
758
$ echo 'branch content' >dir/file2
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
759
$ bzr add -q dir/file2
760
$ bzr commit -q -m 'Add dir/file2 in branch'
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
761
$ bzr merge ../trunk
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
762
2>-D  dir/file
763
2>Conflict: can't delete dir because it is not empty.  Not deleting.
764
2>Conflict because dir is not versioned, but has versioned children.  Versioned directory.
765
2>2 conflicts encountered.
766
"""
767
768
    def test_keep_them_all(self):
769
        self.run_script("""
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
770
$ bzr resolve dir
4597.9.19 by Vincent Ladeuil
resolve now reports conflicts resolved/remaining.
771
2>2 conflict(s) resolved, 0 remaining
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
772
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
773
""")
774
775
    def test_adopt_child(self):
776
        self.run_script("""
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
777
$ bzr mv -q dir/file2 file2
778
$ bzr rm -q dir --force
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
779
$ bzr resolve dir
4597.9.19 by Vincent Ladeuil
resolve now reports conflicts resolved/remaining.
780
2>2 conflict(s) resolved, 0 remaining
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
781
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
782
""")
783
784
    def test_kill_them_all(self):
785
        self.run_script("""
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
786
$ bzr rm -q dir --force
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
787
$ bzr resolve dir
4597.9.19 by Vincent Ladeuil
resolve now reports conflicts resolved/remaining.
788
2>2 conflict(s) resolved, 0 remaining
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
789
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
790
""")
791
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
792
    def test_resolve_taking_this(self):
4597.3.32 by Vincent Ladeuil
Implement --interactive for DeletingParent noting the inconsistency.
793
        self.run_script("""
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
794
$ bzr resolve --take-this dir
4597.9.19 by Vincent Ladeuil
resolve now reports conflicts resolved/remaining.
795
2>2 conflict(s) resolved, 0 remaining
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
796
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
4597.3.32 by Vincent Ladeuil
Implement --interactive for DeletingParent noting the inconsistency.
797
""")
798
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
799
    def test_resolve_taking_other(self):
4597.3.32 by Vincent Ladeuil
Implement --interactive for DeletingParent noting the inconsistency.
800
        self.run_script("""
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
801
$ bzr resolve --take-other dir
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
802
2>deleted dir/file2
803
2>deleted dir
4597.9.19 by Vincent Ladeuil
resolve now reports conflicts resolved/remaining.
804
2>2 conflict(s) resolved, 0 remaining
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
805
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
4597.3.32 by Vincent Ladeuil
Implement --interactive for DeletingParent noting the inconsistency.
806
""")
807
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
808
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
809
class TestResolveParentLoop(TestParametrizedResolveConflicts):
810
4597.13.3 by Vincent Ladeuil
Switch to load_tests_apply_scenarios.
811
    _conflict_type = conflicts.ParentLoop
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
812
813
    _this_args = None
814
    _other_args = None
815
4597.13.3 by Vincent Ladeuil
Switch to load_tests_apply_scenarios.
816
    # Each side dict additionally defines:
817
    # - dir_id: the directory being moved
818
    # - target_id: The target directory
819
    # - xfail: whether the test is expected to fail if the action is
820
    #   involved as 'other'
821
    scenarios = mirror_scenarios(
822
        [
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
823
            # Dirs moved into each other
824
            (dict(_base_actions='create_dir1_dir2'),
825
             ('dir1_into_dir2',
826
              dict(actions='move_dir1_into_dir2', check='dir1_moved',
827
                   dir_id='dir1-id', target_id='dir2-id', xfail=False)),
828
             ('dir2_into_dir1',
829
              dict(actions='move_dir2_into_dir1', check='dir2_moved',
830
                   dir_id='dir2-id', target_id='dir1-id', xfail=False))),
831
            # Subdirs moved into each other
832
            (dict(_base_actions='create_dir1_4'),
833
             ('dir1_into_dir4',
834
              dict(actions='move_dir1_into_dir4', check='dir1_2_moved',
835
                   dir_id='dir1-id', target_id='dir4-id', xfail=True)),
836
             ('dir3_into_dir2',
837
              dict(actions='move_dir3_into_dir2', check='dir3_4_moved',
838
                   dir_id='dir3-id', target_id='dir2-id', xfail=True))),
4597.13.3 by Vincent Ladeuil
Switch to load_tests_apply_scenarios.
839
            ])
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
840
841
    def do_create_dir1_dir2(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
842
        return [('add', ('dir1', 'dir1-id', 'directory', '')),
843
                ('add', ('dir2', 'dir2-id', 'directory', '')),]
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
844
4597.8.8 by Vincent Ladeuil
Exhibit bug #537956.
845
    def do_move_dir1_into_dir2(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
846
        return [('rename', ('dir1', 'dir2/dir1'))]
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
847
848
    def check_dir1_moved(self):
849
        self.failIfExists('branch/dir1')
850
        self.failUnlessExists('branch/dir2/dir1')
851
4597.8.8 by Vincent Ladeuil
Exhibit bug #537956.
852
    def do_move_dir2_into_dir1(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
853
        return [('rename', ('dir2', 'dir1/dir2'))]
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
854
855
    def check_dir2_moved(self):
856
        self.failIfExists('branch/dir2')
857
        self.failUnlessExists('branch/dir1/dir2')
858
4597.8.8 by Vincent Ladeuil
Exhibit bug #537956.
859
    def do_create_dir1_4(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
860
        return [('add', ('dir1', 'dir1-id', 'directory', '')),
861
                ('add', ('dir1/dir2', 'dir2-id', 'directory', '')),
862
                ('add', ('dir3', 'dir3-id', 'directory', '')),
863
                ('add', ('dir3/dir4', 'dir4-id', 'directory', '')),]
4597.8.8 by Vincent Ladeuil
Exhibit bug #537956.
864
865
    def do_move_dir1_into_dir4(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
866
        return [('rename', ('dir1', 'dir3/dir4/dir1'))]
4597.8.8 by Vincent Ladeuil
Exhibit bug #537956.
867
868
    def check_dir1_2_moved(self):
869
        self.failIfExists('branch/dir1')
870
        self.failUnlessExists('branch/dir3/dir4/dir1')
871
        self.failUnlessExists('branch/dir3/dir4/dir1/dir2')
872
873
    def do_move_dir3_into_dir2(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
874
        return [('rename', ('dir3', 'dir1/dir2/dir3'))]
4597.8.8 by Vincent Ladeuil
Exhibit bug #537956.
875
876
    def check_dir3_4_moved(self):
877
        self.failIfExists('branch/dir3')
878
        self.failUnlessExists('branch/dir1/dir2/dir3')
879
        self.failUnlessExists('branch/dir1/dir2/dir3/dir4')
880
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
881
    def _get_resolve_path_arg(self, wt, action):
4597.10.9 by Vincent Ladeuil
More doc.
882
        # ParentLoop says: moving <conflict_path> into <path>. Cancelled move.
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
883
        # But since <path> doesn't exist in the working tree, we need to use
4597.10.9 by Vincent Ladeuil
More doc.
884
        # <conflict_path> instead, and that, in turn, is given by dir_id. Pfew.
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
885
        return wt.id2path(self._other['dir_id'])
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
886
887
    def assertParentLoop(self, wt, c):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
888
        self.assertEqual(self._other['dir_id'], c.file_id)
889
        self.assertEqual(self._other['target_id'], c.conflict_file_id)
4597.8.8 by Vincent Ladeuil
Exhibit bug #537956.
890
        # The conflict paths are irrelevant (they are deterministic but not
891
        # worth checking since they don't provide the needed information
892
        # anyway)
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
893
        if self._other['xfail']:
894
            # It's a bit hackish to raise from here relying on being called for
895
            # both tests but this avoid overriding test_resolve_taking_other
4597.10.4 by Vincent Ladeuil
Handle TestResolveParentLoop expected failures more precisely.
896
            raise tests.KnownFailure(
897
                "ParentLoop doesn't carry enough info to resolve --take-other")
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
898
    _assert_conflict = assertParentLoop
899
900
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
901
class TestResolveNonDirectoryParent(TestResolveConflicts):
902
903
    preamble = """
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
904
$ bzr init trunk
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
905
...
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
906
$ cd trunk
907
$ bzr mkdir foo
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
908
...
909
$ bzr commit -m 'Create trunk' -q
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
910
$ echo "Boing" >foo/bar
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
911
$ bzr add -q foo/bar
912
$ bzr commit -q -m 'Add foo/bar'
913
$ bzr branch -q . -r 1 ../branch
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
914
$ cd ../branch
915
$ rm -r foo
916
$ echo "Boo!" >foo
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
917
$ bzr commit -q -m 'foo is now a file'
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
918
$ bzr merge ../trunk
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
919
2>+N  foo.new/bar
920
2>RK  foo => foo.new/
921
# FIXME: The message is misleading, foo.new *is* a directory when the message
922
# is displayed -- vila 090916
923
2>Conflict: foo.new is not a directory, but has files in it.  Created directory.
924
2>1 conflicts encountered.
925
"""
926
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
927
    def test_take_this(self):
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
928
        self.run_script("""
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
929
$ bzr rm -q foo.new --force
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
930
# FIXME: Isn't it weird that foo is now unkown even if foo.new has been put
931
# aside ? -- vila 090916
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
932
$ bzr add -q foo
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
933
$ bzr resolve foo.new
4597.9.19 by Vincent Ladeuil
resolve now reports conflicts resolved/remaining.
934
2>1 conflict(s) resolved, 0 remaining
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
935
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
936
""")
937
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
938
    def test_take_other(self):
4597.3.35 by Vincent Ladeuil
Implement --interactive for NonDirectoryParent, sort of.
939
        self.run_script("""
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
940
$ bzr rm -q foo --force
941
$ bzr mv -q foo.new foo
4597.3.35 by Vincent Ladeuil
Implement --interactive for NonDirectoryParent, sort of.
942
$ bzr resolve foo
4597.9.19 by Vincent Ladeuil
resolve now reports conflicts resolved/remaining.
943
2>1 conflict(s) resolved, 0 remaining
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
944
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
4597.3.35 by Vincent Ladeuil
Implement --interactive for NonDirectoryParent, sort of.
945
""")
946
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
947
    def test_resolve_taking_this(self):
4597.3.35 by Vincent Ladeuil
Implement --interactive for NonDirectoryParent, sort of.
948
        self.run_script("""
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
949
$ bzr resolve --take-this foo.new
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
950
2>...
951
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
4597.3.35 by Vincent Ladeuil
Implement --interactive for NonDirectoryParent, sort of.
952
""")
953
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
954
    def test_resolve_taking_other(self):
4597.3.35 by Vincent Ladeuil
Implement --interactive for NonDirectoryParent, sort of.
955
        self.run_script("""
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
956
$ bzr resolve --take-other foo.new
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
957
2>...
958
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
4597.3.35 by Vincent Ladeuil
Implement --interactive for NonDirectoryParent, sort of.
959
""")
960
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
961
962
class TestMalformedTransform(script.TestCaseWithTransportAndScript):
963
964
    def test_bug_430129(self):
965
        # This is nearly like TestResolveNonDirectoryParent but with branch and
966
        # trunk switched. As such it should certainly produce the same
967
        # conflict.
968
        self.run_script("""
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
969
$ bzr init trunk
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
970
...
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
971
$ cd trunk
972
$ bzr mkdir foo
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
973
...
974
$ bzr commit -m 'Create trunk' -q
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
975
$ rm -r foo
976
$ echo "Boo!" >foo
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
977
$ bzr commit -m 'foo is now a file' -q
978
$ bzr branch -q . -r 1 ../branch -q
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
979
$ cd ../branch
980
$ echo "Boing" >foo/bar
5422.3.4 by Martin Pool
Update test_resolve to pass --quiet or ignore command output it doesn't care about
981
$ bzr add -q foo/bar -q
982
$ bzr commit -m 'Add foo/bar' -q
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
983
$ bzr merge ../trunk
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
984
2>bzr: ERROR: Tree transform is malformed [('unversioned executability', 'new-1')]
985
""")
4597.3.51 by Vincent Ladeuil
Implement conflicts.ResolveActionOption.
986
987
988
class TestResolveActionOption(tests.TestCase):
989
990
    def setUp(self):
991
        super(TestResolveActionOption, self).setUp()
992
        self.options = [conflicts.ResolveActionOption()]
993
        self.parser = option.get_optparser(dict((o.name, o)
994
                                                for o in self.options))
995
996
    def parse(self, args):
997
        return self.parser.parse_args(args)
998
999
    def test_unknown_action(self):
1000
        self.assertRaises(errors.BadOptionValue,
1001
                          self.parse, ['--action', 'take-me-to-the-moon'])
1002
1003
    def test_done(self):
1004
        opts, args = self.parse(['--action', 'done'])
1005
        self.assertEqual({'action':'done'}, opts)
1006
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
1007
    def test_take_this(self):
1008
        opts, args = self.parse(['--action', 'take-this'])
1009
        self.assertEqual({'action': 'take_this'}, opts)
1010
        opts, args = self.parse(['--take-this'])
1011
        self.assertEqual({'action': 'take_this'}, opts)
4597.3.51 by Vincent Ladeuil
Implement conflicts.ResolveActionOption.
1012
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
1013
    def test_take_other(self):
1014
        opts, args = self.parse(['--action', 'take-other'])
1015
        self.assertEqual({'action': 'take_other'}, opts)
1016
        opts, args = self.parse(['--take-other'])
1017
        self.assertEqual({'action': 'take_other'}, opts)