/brz/remove-bazaar

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