~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_conflicts.py

  • Committer: Vincent Ladeuil
  • Date: 2010-02-10 15:46:03 UTC
  • mfrom: (4985.3.21 update)
  • mto: This revision was merged to the branch mainline in revision 5021.
  • Revision ID: v.ladeuil+lp@free.fr-20100210154603-k4no1gvfuqpzrw7p
Update performs two merges in a more logical order but stop on conflicts

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007, 2008, 2009 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
 
18
18
import os
19
19
 
20
 
from bzrlib import bzrdir
21
 
from bzrlib.tests import TestCaseWithTransport, TestCase
22
 
from bzrlib.branch import Branch
23
 
from bzrlib.conflicts import (
24
 
    ConflictList,
25
 
    ContentsConflict,
26
 
    DuplicateID,
27
 
    DuplicateEntry,
28
 
    MissingParent,
29
 
    NonDirectoryParent,
30
 
    ParentLoop,
31
 
    PathConflict,
32
 
    TextConflict,
33
 
    UnversionedParent,
34
 
    resolve,
35
 
    restore,
 
20
from bzrlib import (
 
21
    bzrdir,
 
22
    conflicts,
 
23
    errors,
 
24
    option,
 
25
    tests,
36
26
    )
37
 
from bzrlib.errors import NotConflicted
 
27
from bzrlib.tests import script
38
28
 
39
29
 
40
30
# TODO: Test commit with some added, and added-but-missing files
44
34
# be a sorted list.
45
35
# u'\xe5' == a with circle
46
36
# '\xc3\xae' == u'\xee' == i with hat
47
 
# So these are u'pathg' and 'idg' only with a circle and a hat. (shappo?)
48
 
example_conflicts = ConflictList([ 
49
 
    MissingParent('Not deleting', u'p\xe5thg', '\xc3\xaedg'),
50
 
    ContentsConflict(u'p\xe5tha', None, '\xc3\xaeda'), 
51
 
    TextConflict(u'p\xe5tha'),
52
 
    PathConflict(u'p\xe5thb', u'p\xe5thc', '\xc3\xaedb'),
53
 
    DuplicateID('Unversioned existing file', u'p\xe5thc', u'p\xe5thc2',
54
 
                '\xc3\xaedc', '\xc3\xaedc'),
55
 
    DuplicateEntry('Moved existing file to',  u'p\xe5thdd.moved', u'p\xe5thd',
56
 
                   '\xc3\xaedd', None),
57
 
    ParentLoop('Cancelled move', u'p\xe5the', u'p\xe5th2e',
58
 
               None, '\xc3\xaed2e'),
59
 
    UnversionedParent('Versioned directory', u'p\xe5thf', '\xc3\xaedf'),
60
 
    NonDirectoryParent('Created directory', u'p\xe5thg', '\xc3\xaedg'),
 
37
# So these are u'path' and 'id' only with a circle and a hat. (shappo?)
 
38
example_conflicts = conflicts.ConflictList(
 
39
    [conflicts.MissingParent('Not deleting', u'p\xe5thg', '\xc3\xaedg'),
 
40
     conflicts.ContentsConflict(u'p\xe5tha', None, '\xc3\xaeda'),
 
41
     conflicts.TextConflict(u'p\xe5tha'),
 
42
     conflicts.PathConflict(u'p\xe5thb', u'p\xe5thc', '\xc3\xaedb'),
 
43
     conflicts.DuplicateID('Unversioned existing file',
 
44
                           u'p\xe5thc', u'p\xe5thc2',
 
45
                           '\xc3\xaedc', '\xc3\xaedc'),
 
46
    conflicts.DuplicateEntry('Moved existing file to',
 
47
                             u'p\xe5thdd.moved', u'p\xe5thd',
 
48
                             '\xc3\xaedd', None),
 
49
    conflicts.ParentLoop('Cancelled move', u'p\xe5the', u'p\xe5th2e',
 
50
                         None, '\xc3\xaed2e'),
 
51
    conflicts.UnversionedParent('Versioned directory',
 
52
                                u'p\xe5thf', '\xc3\xaedf'),
 
53
    conflicts.NonDirectoryParent('Created directory',
 
54
                                 u'p\xe5thg', '\xc3\xaedg'),
61
55
])
62
56
 
63
57
 
64
 
class TestConflicts(TestCaseWithTransport):
 
58
class TestConflicts(tests.TestCaseWithTransport):
65
59
 
66
60
    def test_conflicts(self):
67
61
        """Conflicts are detected properly"""
68
 
        tree = self.make_branch_and_tree('.',
69
 
            format=bzrdir.BzrDirFormat6())
70
 
        b = tree.branch
71
 
        file('hello', 'w').write('hello world4')
72
 
        file('hello.THIS', 'w').write('hello world2')
73
 
        file('hello.BASE', 'w').write('hello world1')
74
 
        file('hello.OTHER', 'w').write('hello world3')
75
 
        file('hello.sploo.BASE', 'w').write('yellow world')
76
 
        file('hello.sploo.OTHER', 'w').write('yellow world2')
 
62
        # Use BzrDirFormat6 so we can fake conflicts
 
63
        tree = self.make_branch_and_tree('.', format=bzrdir.BzrDirFormat6())
 
64
        self.build_tree_contents([('hello', 'hello world4'),
 
65
                                  ('hello.THIS', 'hello world2'),
 
66
                                  ('hello.BASE', 'hello world1'),
 
67
                                  ('hello.OTHER', 'hello world3'),
 
68
                                  ('hello.sploo.BASE', 'yellowworld'),
 
69
                                  ('hello.sploo.OTHER', 'yellowworld2'),
 
70
                                  ])
77
71
        tree.lock_read()
78
 
        self.assertEqual(len(list(tree.list_files())), 6)
 
72
        self.assertEqual(6, len(list(tree.list_files())))
79
73
        tree.unlock()
80
 
        conflicts = tree.conflicts()
81
 
        self.assertEqual(len(conflicts), 2)
82
 
        self.assert_('hello' in conflicts[0].path)
83
 
        self.assert_('hello.sploo' in conflicts[1].path)
84
 
        restore('hello')
85
 
        restore('hello.sploo')
86
 
        self.assertEqual(len(tree.conflicts()), 0)
 
74
        tree_conflicts = tree.conflicts()
 
75
        self.assertEqual(2, len(tree_conflicts))
 
76
        self.assertTrue('hello' in tree_conflicts[0].path)
 
77
        self.assertTrue('hello.sploo' in tree_conflicts[1].path)
 
78
        conflicts.restore('hello')
 
79
        conflicts.restore('hello.sploo')
 
80
        self.assertEqual(0, len(tree.conflicts()))
87
81
        self.assertFileEqual('hello world2', 'hello')
88
82
        self.assertFalse(os.path.lexists('hello.sploo'))
89
 
        self.assertRaises(NotConflicted, restore, 'hello')
90
 
        self.assertRaises(NotConflicted, restore, 'hello.sploo')
 
83
        self.assertRaises(errors.NotConflicted, conflicts.restore, 'hello')
 
84
        self.assertRaises(errors.NotConflicted,
 
85
                          conflicts.restore, 'hello.sploo')
91
86
 
92
87
    def test_resolve_conflict_dir(self):
93
88
        tree = self.make_branch_and_tree('.')
94
 
        b = tree.branch
95
 
        file('hello', 'w').write('hello world4')
 
89
        self.build_tree_contents([('hello', 'hello world4'),
 
90
                                  ('hello.THIS', 'hello world2'),
 
91
                                  ('hello.BASE', 'hello world1'),
 
92
                                  ])
 
93
        os.mkdir('hello.OTHER')
96
94
        tree.add('hello', 'q')
97
 
        file('hello.THIS', 'w').write('hello world2')
98
 
        file('hello.BASE', 'w').write('hello world1')
99
 
        os.mkdir('hello.OTHER')
100
 
        l = ConflictList([TextConflict('hello')])
 
95
        l = conflicts.ConflictList([conflicts.TextConflict('hello')])
101
96
        l.remove_files(tree)
102
97
 
103
98
    def test_select_conflicts(self):
104
99
        tree = self.make_branch_and_tree('.')
105
 
        tree_conflicts = ConflictList([ContentsConflict('foo'),
106
 
                                       ContentsConflict('bar')])
107
 
        self.assertEqual((ConflictList([ContentsConflict('bar')]),
108
 
                          ConflictList([ContentsConflict('foo')])),
109
 
                         tree_conflicts.select_conflicts(tree, ['foo']))
110
 
        self.assertEqual((ConflictList(), tree_conflicts),
111
 
                         tree_conflicts.select_conflicts(tree, [''],
112
 
                         ignore_misses=True, recurse=True))
113
 
        tree_conflicts = ConflictList([ContentsConflict('foo/baz'),
114
 
                                       ContentsConflict('bar')])
115
 
        self.assertEqual((ConflictList([ContentsConflict('bar')]),
116
 
                          ConflictList([ContentsConflict('foo/baz')])),
117
 
                         tree_conflicts.select_conflicts(tree, ['foo'],
118
 
                                                         recurse=True,
119
 
                                                         ignore_misses=True))
120
 
        tree_conflicts = ConflictList([PathConflict('qux', 'foo/baz')])
121
 
        self.assertEqual((ConflictList(), tree_conflicts),
122
 
                         tree_conflicts.select_conflicts(tree, ['foo'],
123
 
                                                         recurse=True,
124
 
                                                         ignore_misses=True))
125
 
        self.assertEqual((tree_conflicts, ConflictList()),
126
 
                         tree_conflicts.select_conflicts(tree, ['foo'],
127
 
                                                         ignore_misses=True))
 
100
        clist = conflicts.ConflictList
 
101
 
 
102
        def check_select(not_selected, selected, paths, **kwargs):
 
103
            self.assertEqual(
 
104
                (not_selected, selected),
 
105
                tree_conflicts.select_conflicts(tree, paths, **kwargs))
 
106
 
 
107
        foo = conflicts.ContentsConflict('foo')
 
108
        bar = conflicts.ContentsConflict('bar')
 
109
        tree_conflicts = clist([foo, bar])
 
110
 
 
111
        check_select(clist([bar]), clist([foo]), ['foo'])
 
112
        check_select(clist(), tree_conflicts,
 
113
                     [''], ignore_misses=True, recurse=True)
 
114
 
 
115
        foobaz  = conflicts.ContentsConflict('foo/baz')
 
116
        tree_conflicts = clist([foobaz, bar])
 
117
 
 
118
        check_select(clist([bar]), clist([foobaz]),
 
119
                     ['foo'], ignore_misses=True, recurse=True)
 
120
 
 
121
        qux = conflicts.PathConflict('qux', 'foo/baz')
 
122
        tree_conflicts = clist([qux])
 
123
 
 
124
        check_select(clist(), tree_conflicts,
 
125
                     ['foo'], ignore_misses=True, recurse=True)
 
126
        check_select (tree_conflicts, clist(), ['foo'], ignore_misses=True)
128
127
 
129
128
    def test_resolve_conflicts_recursive(self):
130
129
        tree = self.make_branch_and_tree('.')
131
130
        self.build_tree(['dir/', 'dir/hello'])
132
131
        tree.add(['dir', 'dir/hello'])
133
 
        tree.set_conflicts(ConflictList([TextConflict('dir/hello')]))
134
 
        resolve(tree, ['dir'], recursive=False, ignore_misses=True)
135
 
        self.assertEqual(ConflictList([TextConflict('dir/hello')]),
136
 
                         tree.conflicts())
137
 
        resolve(tree, ['dir'], recursive=True, ignore_misses=True)
138
 
        self.assertEqual(ConflictList([]),
139
 
                         tree.conflicts())
140
 
 
141
 
 
142
 
class TestConflictStanzas(TestCase):
 
132
 
 
133
        dirhello = conflicts.ConflictList([conflicts.TextConflict('dir/hello')])
 
134
        tree.set_conflicts(dirhello)
 
135
 
 
136
        conflicts.resolve(tree, ['dir'], recursive=False, ignore_misses=True)
 
137
        self.assertEqual(dirhello, tree.conflicts())
 
138
 
 
139
        conflicts.resolve(tree, ['dir'], recursive=True, ignore_misses=True)
 
140
        self.assertEqual(conflicts.ConflictList([]), tree.conflicts())
 
141
 
 
142
 
 
143
class TestConflictStanzas(tests.TestCase):
143
144
 
144
145
    def test_stanza_roundtrip(self):
145
146
        # write and read our example stanza.
146
147
        stanza_iter = example_conflicts.to_stanzas()
147
 
        processed = ConflictList.from_stanzas(stanza_iter)
 
148
        processed = conflicts.ConflictList.from_stanzas(stanza_iter)
148
149
        for o, p in zip(processed, example_conflicts):
149
150
            self.assertEqual(o, p)
150
151
 
171
172
                self.assertStartsWith(stanza['conflict_path'], u'p\xe5th')
172
173
            if 'conflict_file_id' in stanza:
173
174
                self.assertStartsWith(stanza['conflict_file_id'], u'\xeed')
 
175
 
 
176
 
 
177
# FIXME: The shell-like tests should be converted to real whitebox tests... or
 
178
# moved to a blackbox module -- vila 20100205
 
179
 
 
180
# FIXME: Tests missing for DuplicateID conflict type
 
181
class TestResolveConflicts(script.TestCaseWithTransportAndScript):
 
182
 
 
183
    preamble = None # The setup script set by daughter classes
 
184
 
 
185
    def setUp(self):
 
186
        super(TestResolveConflicts, self).setUp()
 
187
        self.run_script(self.preamble)
 
188
 
 
189
 
 
190
class TestResolveTextConflicts(TestResolveConflicts):
 
191
    # TBC
 
192
    pass
 
193
 
 
194
 
 
195
class TestResolveContentConflicts(TestResolveConflicts):
 
196
 
 
197
    # FIXME: We need to add the reverse case (delete in trunk, modify in
 
198
    # branch) but that could wait until the resolution mechanism is implemented.
 
199
 
 
200
    preamble = """
 
201
$ bzr init trunk
 
202
$ cd trunk
 
203
$ echo 'trunk content' >file
 
204
$ bzr add file
 
205
$ bzr commit -m 'Create trunk'
 
206
 
 
207
$ bzr branch . ../branch
 
208
$ cd ../branch
 
209
$ bzr rm file
 
210
$ bzr commit -m 'Delete file'
 
211
 
 
212
$ cd ../trunk
 
213
$ echo 'more content' >>file
 
214
$ bzr commit -m 'Modify file'
 
215
 
 
216
$ cd ../branch
 
217
$ bzr merge ../trunk
 
218
2>+N  file.OTHER
 
219
2>Contents conflict in file
 
220
2>1 conflicts encountered.
 
221
"""
 
222
 
 
223
    def test_take_this(self):
 
224
        self.run_script("""
 
225
$ bzr rm file.OTHER --force # a simple rm file.OTHER is valid too
 
226
$ bzr resolve file
 
227
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
228
""")
 
229
 
 
230
    def test_take_other(self):
 
231
        self.run_script("""
 
232
$ bzr mv file.OTHER file
 
233
$ bzr resolve file
 
234
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
235
""")
 
236
 
 
237
    def test_resolve_taking_this(self):
 
238
        self.run_script("""
 
239
$ bzr resolve --take-this file
 
240
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
241
""")
 
242
 
 
243
    def test_resolve_taking_other(self):
 
244
        self.run_script("""
 
245
$ bzr resolve --take-other file
 
246
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
247
""")
 
248
 
 
249
 
 
250
class TestResolveDuplicateEntry(TestResolveConflicts):
 
251
 
 
252
    preamble = """
 
253
$ bzr init trunk
 
254
$ cd trunk
 
255
$ echo 'trunk content' >file
 
256
$ bzr add file
 
257
$ bzr commit -m 'Create trunk'
 
258
$ echo 'trunk content too' >file2
 
259
$ bzr add file2
 
260
$ bzr commit -m 'Add file2 in trunk'
 
261
 
 
262
$ bzr branch . -r 1 ../branch
 
263
$ cd ../branch
 
264
$ echo 'branch content' >file2
 
265
$ bzr add file2
 
266
$ bzr commit -m 'Add file2 in branch'
 
267
 
 
268
$ bzr merge ../trunk
 
269
2>+N  file2
 
270
2>R   file2 => file2.moved
 
271
2>Conflict adding file file2.  Moved existing file to file2.moved.
 
272
2>1 conflicts encountered.
 
273
"""
 
274
 
 
275
    def test_keep_this(self):
 
276
        self.run_script("""
 
277
$ bzr rm file2  --force
 
278
$ bzr mv file2.moved file2
 
279
$ bzr resolve file2
 
280
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
281
""")
 
282
 
 
283
    def test_keep_other(self):
 
284
        self.failIfExists('branch/file2.moved')
 
285
        self.run_script("""
 
286
$ bzr rm file2.moved --force
 
287
$ bzr resolve file2
 
288
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
289
""")
 
290
        self.failIfExists('branch/file2.moved')
 
291
 
 
292
    def test_resolve_taking_this(self):
 
293
        self.run_script("""
 
294
$ bzr resolve --take-this file2
 
295
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
296
""")
 
297
 
 
298
    def test_resolve_taking_other(self):
 
299
        self.run_script("""
 
300
$ bzr resolve --take-other file2
 
301
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
302
""")
 
303
 
 
304
 
 
305
class TestResolveUnversionedParent(TestResolveConflicts):
 
306
 
 
307
    # FIXME: Add the reverse tests: dir deleted in trunk, file added in branch
 
308
 
 
309
    # FIXME: While this *creates* UnversionedParent conflicts, this really only
 
310
    # tests MissingParent resolution :-/
 
311
    preamble = """
 
312
$ bzr init trunk
 
313
$ cd trunk
 
314
$ mkdir dir
 
315
$ bzr add dir
 
316
$ bzr commit -m 'Create trunk'
 
317
$ echo 'trunk content' >dir/file
 
318
$ bzr add dir/file
 
319
$ bzr commit -m 'Add dir/file in trunk'
 
320
 
 
321
$ bzr branch . -r 1 ../branch
 
322
$ cd ../branch
 
323
$ bzr rm dir
 
324
$ bzr commit -m 'Remove dir in branch'
 
325
 
 
326
$ bzr merge ../trunk
 
327
2>+N  dir/
 
328
2>+N  dir/file
 
329
2>Conflict adding files to dir.  Created directory.
 
330
2>Conflict because dir is not versioned, but has versioned children.  Versioned directory.
 
331
2>2 conflicts encountered.
 
332
"""
 
333
 
 
334
    def test_take_this(self):
 
335
        self.run_script("""
 
336
$ bzr rm dir  --force
 
337
$ bzr resolve dir
 
338
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
339
""")
 
340
 
 
341
    def test_take_other(self):
 
342
        self.run_script("""
 
343
$ bzr resolve dir
 
344
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
345
""")
 
346
 
 
347
 
 
348
class TestResolveMissingParent(TestResolveConflicts):
 
349
 
 
350
    preamble = """
 
351
$ bzr init trunk
 
352
$ cd trunk
 
353
$ mkdir dir
 
354
$ echo 'trunk content' >dir/file
 
355
$ bzr add
 
356
$ bzr commit -m 'Create trunk'
 
357
$ echo 'trunk content' >dir/file2
 
358
$ bzr add dir/file2
 
359
$ bzr commit -m 'Add dir/file2 in branch'
 
360
 
 
361
$ bzr branch . -r 1 ../branch
 
362
$ cd ../branch
 
363
$ bzr rm dir/file --force
 
364
$ bzr rm dir
 
365
$ bzr commit -m 'Remove dir/file'
 
366
 
 
367
$ bzr merge ../trunk
 
368
2>+N  dir/
 
369
2>+N  dir/file2
 
370
2>Conflict adding files to dir.  Created directory.
 
371
2>Conflict because dir is not versioned, but has versioned children.  Versioned directory.
 
372
2>2 conflicts encountered.
 
373
"""
 
374
 
 
375
    def test_keep_them_all(self):
 
376
        self.run_script("""
 
377
$ bzr resolve dir
 
378
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
379
""")
 
380
 
 
381
    def test_adopt_child(self):
 
382
        self.run_script("""
 
383
$ bzr mv dir/file2 file2
 
384
$ bzr rm dir --force
 
385
$ bzr resolve dir
 
386
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
387
""")
 
388
 
 
389
    def test_kill_them_all(self):
 
390
        self.run_script("""
 
391
$ bzr rm dir --force
 
392
$ bzr resolve dir
 
393
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
394
""")
 
395
 
 
396
    def test_resolve_taking_this(self):
 
397
        self.run_script("""
 
398
$ bzr resolve --take-this dir
 
399
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
400
""")
 
401
 
 
402
    def test_resolve_taking_other(self):
 
403
        self.run_script("""
 
404
$ bzr resolve --take-other dir
 
405
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
406
""")
 
407
 
 
408
 
 
409
class TestResolveDeletingParent(TestResolveConflicts):
 
410
 
 
411
    preamble = """
 
412
$ bzr init trunk
 
413
$ cd trunk
 
414
$ mkdir dir
 
415
$ echo 'trunk content' >dir/file
 
416
$ bzr add
 
417
$ bzr commit -m 'Create trunk'
 
418
$ bzr rm dir/file --force
 
419
$ bzr rm dir --force
 
420
$ bzr commit -m 'Remove dir/file'
 
421
 
 
422
$ bzr branch . -r 1 ../branch
 
423
$ cd ../branch
 
424
$ echo 'branch content' >dir/file2
 
425
$ bzr add dir/file2
 
426
$ bzr commit -m 'Add dir/file2 in branch'
 
427
 
 
428
$ bzr merge ../trunk
 
429
2>-D  dir/file
 
430
2>Conflict: can't delete dir because it is not empty.  Not deleting.
 
431
2>Conflict because dir is not versioned, but has versioned children.  Versioned directory.
 
432
2>2 conflicts encountered.
 
433
"""
 
434
 
 
435
    def test_keep_them_all(self):
 
436
        self.run_script("""
 
437
$ bzr resolve dir
 
438
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
439
""")
 
440
 
 
441
    def test_adopt_child(self):
 
442
        self.run_script("""
 
443
$ bzr mv dir/file2 file2
 
444
$ bzr rm dir --force
 
445
$ bzr resolve dir
 
446
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
447
""")
 
448
 
 
449
    def test_kill_them_all(self):
 
450
        self.run_script("""
 
451
$ bzr rm dir --force
 
452
$ bzr resolve dir
 
453
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
454
""")
 
455
 
 
456
    def test_resolve_taking_this(self):
 
457
        self.run_script("""
 
458
$ bzr resolve --take-this dir
 
459
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
460
""")
 
461
 
 
462
    def test_resolve_taking_other(self):
 
463
        self.run_script("""
 
464
$ bzr resolve --take-other dir
 
465
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
466
""")
 
467
 
 
468
 
 
469
class TestResolvePathConflict(TestResolveConflicts):
 
470
 
 
471
    preamble = """
 
472
$ bzr init trunk
 
473
$ cd trunk
 
474
$ echo 'Boo!' >file
 
475
$ bzr add
 
476
$ bzr commit -m 'Create trunk'
 
477
$ bzr mv file file-in-trunk
 
478
$ bzr commit -m 'Renamed to file-in-trunk'
 
479
 
 
480
$ bzr branch . -r 1 ../branch
 
481
$ cd ../branch
 
482
$ bzr mv file file-in-branch
 
483
$ bzr commit -m 'Renamed to file-in-branch'
 
484
 
 
485
$ bzr merge ../trunk
 
486
2>R   file-in-branch => file-in-trunk
 
487
2>Path conflict: file-in-branch / file-in-trunk
 
488
2>1 conflicts encountered.
 
489
"""
 
490
 
 
491
    def test_keep_source(self):
 
492
        self.run_script("""
 
493
$ bzr resolve file-in-trunk
 
494
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
495
""")
 
496
 
 
497
    def test_keep_target(self):
 
498
        self.run_script("""
 
499
$ bzr mv file-in-trunk file-in-branch
 
500
$ bzr resolve file-in-branch
 
501
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
502
""")
 
503
 
 
504
    def test_resolve_taking_this(self):
 
505
        self.run_script("""
 
506
$ bzr resolve --take-this file-in-branch
 
507
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
508
""")
 
509
 
 
510
    def test_resolve_taking_other(self):
 
511
        self.run_script("""
 
512
$ bzr resolve --take-other file-in-branch
 
513
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
514
""")
 
515
 
 
516
 
 
517
class TestResolveParentLoop(TestResolveConflicts):
 
518
 
 
519
    preamble = """
 
520
$ bzr init trunk
 
521
$ cd trunk
 
522
$ bzr mkdir dir1
 
523
$ bzr mkdir dir2
 
524
$ bzr commit -m 'Create trunk'
 
525
$ bzr mv dir2 dir1
 
526
$ bzr commit -m 'Moved dir2 into dir1'
 
527
 
 
528
$ bzr branch . -r 1 ../branch
 
529
$ cd ../branch
 
530
$ bzr mv dir1 dir2
 
531
$ bzr commit -m 'Moved dir1 into dir2'
 
532
 
 
533
$ bzr merge ../trunk
 
534
2>Conflict moving dir2/dir1 into dir2.  Cancelled move.
 
535
2>1 conflicts encountered.
 
536
"""
 
537
 
 
538
    def test_take_this(self):
 
539
        self.run_script("""
 
540
$ bzr resolve dir2
 
541
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
542
""")
 
543
 
 
544
    def test_take_other(self):
 
545
        self.run_script("""
 
546
$ bzr mv dir2/dir1 dir1
 
547
$ bzr mv dir2 dir1
 
548
$ bzr resolve dir2
 
549
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
550
""")
 
551
 
 
552
    def test_resolve_taking_this(self):
 
553
        self.run_script("""
 
554
$ bzr resolve --take-this dir2
 
555
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
556
""")
 
557
        self.failUnlessExists('dir2')
 
558
 
 
559
    def test_resolve_taking_other(self):
 
560
        self.run_script("""
 
561
$ bzr resolve --take-other dir2
 
562
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
563
""")
 
564
        self.failUnlessExists('dir1')
 
565
 
 
566
 
 
567
class TestResolveNonDirectoryParent(TestResolveConflicts):
 
568
 
 
569
    preamble = """
 
570
$ bzr init trunk
 
571
$ cd trunk
 
572
$ bzr mkdir foo
 
573
$ bzr commit -m 'Create trunk'
 
574
$ echo "Boing" >foo/bar
 
575
$ bzr add foo/bar
 
576
$ bzr commit -m 'Add foo/bar'
 
577
 
 
578
$ bzr branch . -r 1 ../branch
 
579
$ cd ../branch
 
580
$ rm -r foo
 
581
$ echo "Boo!" >foo
 
582
$ bzr commit -m 'foo is now a file'
 
583
 
 
584
$ bzr merge ../trunk
 
585
2>+N  foo.new/bar
 
586
2>RK  foo => foo.new/
 
587
# FIXME: The message is misleading, foo.new *is* a directory when the message
 
588
# is displayed -- vila 090916
 
589
2>Conflict: foo.new is not a directory, but has files in it.  Created directory.
 
590
2>1 conflicts encountered.
 
591
"""
 
592
 
 
593
    def test_take_this(self):
 
594
        self.run_script("""
 
595
$ bzr rm foo.new --force
 
596
# FIXME: Isn't it weird that foo is now unkown even if foo.new has been put
 
597
# aside ? -- vila 090916
 
598
$ bzr add foo
 
599
$ bzr resolve foo.new
 
600
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
601
""")
 
602
 
 
603
    def test_take_other(self):
 
604
        self.run_script("""
 
605
$ bzr rm foo --force
 
606
$ bzr mv foo.new foo
 
607
$ bzr resolve foo
 
608
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
609
""")
 
610
 
 
611
    def test_resolve_taking_this(self):
 
612
        self.run_script("""
 
613
$ bzr resolve --take-this foo.new
 
614
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
615
""")
 
616
 
 
617
    def test_resolve_taking_other(self):
 
618
        self.run_script("""
 
619
$ bzr resolve --take-other foo.new
 
620
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
621
""")
 
622
 
 
623
 
 
624
class TestMalformedTransform(script.TestCaseWithTransportAndScript):
 
625
 
 
626
    def test_bug_430129(self):
 
627
        # This is nearly like TestResolveNonDirectoryParent but with branch and
 
628
        # trunk switched. As such it should certainly produce the same
 
629
        # conflict.
 
630
        self.run_script("""
 
631
$ bzr init trunk
 
632
$ cd trunk
 
633
$ bzr mkdir foo
 
634
$ bzr commit -m 'Create trunk'
 
635
$ rm -r foo
 
636
$ echo "Boo!" >foo
 
637
$ bzr commit -m 'foo is now a file'
 
638
 
 
639
$ bzr branch . -r 1 ../branch
 
640
$ cd ../branch
 
641
$ echo "Boing" >foo/bar
 
642
$ bzr add foo/bar
 
643
$ bzr commit -m 'Add foo/bar'
 
644
 
 
645
$ bzr merge ../trunk
 
646
2>bzr: ERROR: Tree transform is malformed [('unversioned executability', 'new-1')]
 
647
""")
 
648
 
 
649
 
 
650
class TestResolveActionOption(tests.TestCase):
 
651
 
 
652
    def setUp(self):
 
653
        super(TestResolveActionOption, self).setUp()
 
654
        self.options = [conflicts.ResolveActionOption()]
 
655
        self.parser = option.get_optparser(dict((o.name, o)
 
656
                                                for o in self.options))
 
657
 
 
658
    def parse(self, args):
 
659
        return self.parser.parse_args(args)
 
660
 
 
661
    def test_unknown_action(self):
 
662
        self.assertRaises(errors.BadOptionValue,
 
663
                          self.parse, ['--action', 'take-me-to-the-moon'])
 
664
 
 
665
    def test_done(self):
 
666
        opts, args = self.parse(['--action', 'done'])
 
667
        self.assertEqual({'action':'done'}, opts)
 
668
 
 
669
    def test_take_this(self):
 
670
        opts, args = self.parse(['--action', 'take-this'])
 
671
        self.assertEqual({'action': 'take_this'}, opts)
 
672
        opts, args = self.parse(['--take-this'])
 
673
        self.assertEqual({'action': 'take_this'}, opts)
 
674
 
 
675
    def test_take_other(self):
 
676
        opts, args = self.parse(['--action', 'take-other'])
 
677
        self.assertEqual({'action': 'take_other'}, opts)
 
678
        opts, args = self.parse(['--take-other'])
 
679
        self.assertEqual({'action': 'take_other'}, opts)