~bzr-pqm/bzr/bzr.dev

2255.2.217 by Martin Pool
docs
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
2
#
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.
7
#
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.
12
#
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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
1185.1.41 by Robert Collins
massive patch from Alexander Belchenko - many PEP8 fixes, removes unused function uuid
17
import os
1551.2.23 by Aaron Bentley
Got merge_inner's ignore_zero parameter working
18
from StringIO import StringIO
1185.1.41 by Robert Collins
massive patch from Alexander Belchenko - many PEP8 fixes, removes unused function uuid
19
2221.4.16 by Aaron Bentley
Add tests for get_merge_type_registry
20
from bzrlib import (
21
    conflicts,
1551.15.72 by Aaron Bentley
remove builtins._merge_helper
22
    errors,
3062.1.9 by Aaron Bentley
Move PlanMerge into merge and _PlanMergeVersionedFile into versionedfile
23
    knit,
2221.4.16 by Aaron Bentley
Add tests for get_merge_type_registry
24
    merge as _mod_merge,
25
    option,
1551.15.72 by Aaron Bentley
remove builtins._merge_helper
26
    progress,
3008.1.21 by Aaron Bentley
Make compute_transform private, test make_preview_transform
27
    transform,
3062.1.9 by Aaron Bentley
Move PlanMerge into merge and _PlanMergeVersionedFile into versionedfile
28
    versionedfile,
2221.4.16 by Aaron Bentley
Add tests for get_merge_type_registry
29
    )
974.1.56 by aaron.bentley at utoronto
Added merge test
30
from bzrlib.branch import Branch
1551.7.10 by Aaron Bentley
Remerge doesn't clear unrelated conflicts
31
from bzrlib.conflicts import ConflictList, TextConflict
1185.24.3 by Aaron Bentley
Integrated reprocessing into the rest of the merge stuff
32
from bzrlib.errors import UnrelatedBranches, NoCommits, BzrCommandError
3062.1.13 by Aaron Bentley
Make _PlanMerge an implementation detail of _PlanMergeVersionedFile
33
from bzrlib.merge import transform_tree, merge_inner, _PlanMerge
1959.4.6 by Aaron Bentley
Ensure merge works across kind changes
34
from bzrlib.osutils import pathjoin, file_kind
3062.1.9 by Aaron Bentley
Move PlanMerge into merge and _PlanMergeVersionedFile into versionedfile
35
from bzrlib.tests import TestCaseWithTransport, TestCaseWithMemoryTransport
1551.2.23 by Aaron Bentley
Got merge_inner's ignore_zero parameter working
36
from bzrlib.trace import (enable_test_log, disable_test_log)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
37
from bzrlib.workingtree import WorkingTree
38
39
40
class TestMerge(TestCaseWithTransport):
974.1.56 by aaron.bentley at utoronto
Added merge test
41
    """Test appending more than one revision"""
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
42
974.1.56 by aaron.bentley at utoronto
Added merge test
43
    def test_pending(self):
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
44
        wt = self.make_branch_and_tree('.')
1908.6.11 by Robert Collins
Remove usage of tree.pending_merges().
45
        rev_a = wt.commit("lala!")
46
        self.assertEqual([rev_a], wt.get_parent_ids())
1551.15.72 by Aaron Bentley
remove builtins._merge_helper
47
        self.assertRaises(errors.PointlessMerge, wt.merge_from_branch,
48
                          wt.branch)
1908.6.11 by Robert Collins
Remove usage of tree.pending_merges().
49
        self.assertEqual([rev_a], wt.get_parent_ids())
1551.15.72 by Aaron Bentley
remove builtins._merge_helper
50
        return wt
974.1.80 by Aaron Bentley
Improved merge error handling and testing
51
1558.4.11 by Aaron Bentley
Allow merge against self, make fetching self a noop
52
    def test_undo(self):
53
        wt = self.make_branch_and_tree('.')
54
        wt.commit("lala!")
55
        wt.commit("haha!")
56
        wt.commit("blabla!")
1551.15.72 by Aaron Bentley
remove builtins._merge_helper
57
        wt.merge_from_branch(wt.branch, wt.branch.get_rev_id(2),
58
                             wt.branch.get_rev_id(1))
1558.4.11 by Aaron Bentley
Allow merge against self, make fetching self a noop
59
974.1.80 by Aaron Bentley
Improved merge error handling and testing
60
    def test_nocommits(self):
1551.15.72 by Aaron Bentley
remove builtins._merge_helper
61
        wt = self.test_pending()
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
62
        wt2 = self.make_branch_and_tree('branch2')
1551.15.72 by Aaron Bentley
remove builtins._merge_helper
63
        self.assertRaises(NoCommits, wt.merge_from_branch, wt2.branch)
64
        return wt, wt2
974.1.80 by Aaron Bentley
Improved merge error handling and testing
65
66
    def test_unrelated(self):
1551.15.72 by Aaron Bentley
remove builtins._merge_helper
67
        wt, wt2 = self.test_nocommits()
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
68
        wt2.commit("blah")
1551.15.72 by Aaron Bentley
remove builtins._merge_helper
69
        self.assertRaises(UnrelatedBranches, wt.merge_from_branch, wt2.branch)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
70
        return wt2
974.1.80 by Aaron Bentley
Improved merge error handling and testing
71
1908.6.11 by Robert Collins
Remove usage of tree.pending_merges().
72
    def test_merge_one_file(self):
73
        """Do a partial merge of a tree which should not affect tree parents."""
1645.1.1 by Aaron Bentley
Implement single-file merge
74
        wt1 = self.make_branch_and_tree('branch1')
1908.6.11 by Robert Collins
Remove usage of tree.pending_merges().
75
        tip = wt1.commit('empty commit')
1645.1.1 by Aaron Bentley
Implement single-file merge
76
        wt2 = self.make_branch_and_tree('branch2')
77
        wt2.pull(wt1.branch)
78
        file('branch1/foo', 'wb').write('foo')
79
        file('branch1/bar', 'wb').write('bar')
80
        wt1.add('foo')
81
        wt1.add('bar')
82
        wt1.commit('add foobar')
83
        os.chdir('branch2')
2530.3.1 by Martin Pool
Cleanup old variations on run_bzr in the test suite
84
        self.run_bzr('merge ../branch1/baz', retcode=3)
85
        self.run_bzr('merge ../branch1/foo')
1645.1.1 by Aaron Bentley
Implement single-file merge
86
        self.failUnlessExists('foo')
87
        self.failIfExists('bar')
1908.6.11 by Robert Collins
Remove usage of tree.pending_merges().
88
        wt2 = WorkingTree.open('.') # opens branch2
89
        self.assertEqual([tip], wt2.get_parent_ids())
1908.6.9 by Robert Collins
Fix status to not use pending_merges.
90
        
974.1.88 by Aaron Bentley
Set a pending_merge if the merge base is forced to revno 0
91
    def test_pending_with_null(self):
1551.8.25 by Aaron Bentley
Fix deprecated use of pending_merges
92
        """When base is forced to revno 0, parent_ids are set"""
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
93
        wt2 = self.test_unrelated()
1508.1.19 by Robert Collins
Give format3 working trees their own last-revision marker.
94
        wt1 = WorkingTree.open('.')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
95
        br1 = wt1.branch
1534.1.31 by Robert Collins
Deprecated fetch.fetch and fetch.greedy_fetch for branch.fetch, and move the Repository.fetch internals to InterRepo and InterWeaveRepo.
96
        br1.fetch(wt2.branch)
1390 by Robert Collins
pair programming worx... merge integration and weave
97
        # merge all of branch 2 into branch 1 even though they 
98
        # are not related.
1551.15.72 by Aaron Bentley
remove builtins._merge_helper
99
        wt1.merge_from_branch(wt2.branch, wt2.last_revision(), 'null:')
1908.6.11 by Robert Collins
Remove usage of tree.pending_merges().
100
        self.assertEqual([br1.last_revision(), wt2.branch.last_revision()],
101
            wt1.get_parent_ids())
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
102
        return (wt1, wt2.branch)
974.1.89 by Aaron Bentley
Fixed merging with multiple roots, by using null as graph root.
103
104
    def test_two_roots(self):
105
        """Merge base is sane when two unrelated branches are merged"""
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
106
        wt1, br2 = self.test_pending_with_null()
107
        wt1.commit("blah")
3228.4.15 by John Arbash Meinel
Stop using common_ancestor
108
        wt1.lock_read()
109
        try:
110
            last = wt1.branch.last_revision()
111
            last2 = br2.last_revision()
112
            graph = wt1.branch.repository.get_graph()
113
            self.assertEqual(last2, graph.find_unique_lca(last, last2))
114
        finally:
115
            wt1.unlock()
1185.46.1 by Aaron Bentley
Test case when file to be renamed is also deleted
116
117
    def test_create_rename(self):
118
        """Rename an inventory entry while creating the file"""
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
119
        tree =self.make_branch_and_tree('.')
1185.46.1 by Aaron Bentley
Test case when file to be renamed is also deleted
120
        file('name1', 'wb').write('Hello')
121
        tree.add('name1')
122
        tree.commit(message="hello")
123
        tree.rename_one('name1', 'name2')
124
        os.unlink('name2')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
125
        transform_tree(tree, tree.branch.basis_tree())
1185.46.2 by Aaron Bentley
Added test for renaming both parent and child
126
127
    def test_layered_rename(self):
128
        """Rename both child and parent at same time"""
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
129
        tree =self.make_branch_and_tree('.')
1185.46.2 by Aaron Bentley
Added test for renaming both parent and child
130
        os.mkdir('dirname1')
131
        tree.add('dirname1')
1185.31.32 by John Arbash Meinel
Updated the bzr sourcecode to use bzrlib.osutils.pathjoin rather than os.path.join to enforce internal use of / instead of \
132
        filename = pathjoin('dirname1', 'name1')
1185.46.2 by Aaron Bentley
Added test for renaming both parent and child
133
        file(filename, 'wb').write('Hello')
134
        tree.add(filename)
135
        tree.commit(message="hello")
1185.31.32 by John Arbash Meinel
Updated the bzr sourcecode to use bzrlib.osutils.pathjoin rather than os.path.join to enforce internal use of / instead of \
136
        filename2 = pathjoin('dirname1', 'name2')
1185.46.2 by Aaron Bentley
Added test for renaming both parent and child
137
        tree.rename_one(filename, filename2)
138
        tree.rename_one('dirname1', 'dirname2')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
139
        transform_tree(tree, tree.branch.basis_tree())
1551.2.23 by Aaron Bentley
Got merge_inner's ignore_zero parameter working
140
141
    def test_ignore_zero_merge_inner(self):
1907.4.1 by Matthieu Moy
Fixed merge to work nicely with -r revno:N:path
142
        # Test that merge_inner's ignore zero parameter is effective
1551.2.23 by Aaron Bentley
Got merge_inner's ignore_zero parameter working
143
        tree_a =self.make_branch_and_tree('a')
144
        tree_a.commit(message="hello")
145
        dir_b = tree_a.bzrdir.sprout('b')
146
        tree_b = dir_b.open_workingtree()
3146.4.4 by Aaron Bentley
Add write lock, so merge_inner works properly
147
        tree_b.lock_write()
148
        self.addCleanup(tree_b.unlock)
1551.2.23 by Aaron Bentley
Got merge_inner's ignore_zero parameter working
149
        tree_a.commit(message="hello again")
150
        log = StringIO()
151
        merge_inner(tree_b.branch, tree_a, tree_b.basis_tree(), 
152
                    this_tree=tree_b, ignore_zero=True)
1927.3.1 by Carl Friedrich Bolz
Throw away on-disk logfile when possible.
153
        log = self._get_log(keep_log_file=True)
1551.4.1 by Aaron Bentley
Workaround for silly _get_log behaviour in test
154
        self.failUnless('All changes applied successfully.\n' not in log)
2796.1.3 by Aaron Bentley
update new test case
155
        tree_b.revert()
1551.2.23 by Aaron Bentley
Got merge_inner's ignore_zero parameter working
156
        merge_inner(tree_b.branch, tree_a, tree_b.basis_tree(), 
157
                    this_tree=tree_b, ignore_zero=False)
1927.3.1 by Carl Friedrich Bolz
Throw away on-disk logfile when possible.
158
        log = self._get_log(keep_log_file=True)
1551.4.1 by Aaron Bentley
Workaround for silly _get_log behaviour in test
159
        self.failUnless('All changes applied successfully.\n' in log)
1551.7.10 by Aaron Bentley
Remerge doesn't clear unrelated conflicts
160
161
    def test_merge_inner_conflicts(self):
162
        tree_a = self.make_branch_and_tree('a')
163
        tree_a.set_conflicts(ConflictList([TextConflict('patha')]))
1551.7.11 by Aaron Bentley
Add WorkingTree.add_conflicts
164
        merge_inner(tree_a.branch, tree_a, tree_a, this_tree=tree_a)
1551.7.13 by Aaron Bentley
Switched from actual, expected to expected, actual, for John.
165
        self.assertEqual(1, len(tree_a.conflicts()))
1551.8.22 by Aaron Bentley
Improve message when OTHER deletes an in-use tree
166
167
    def test_rmdir_conflict(self):
168
        tree_a = self.make_branch_and_tree('a')
169
        self.build_tree(['a/b/'])
170
        tree_a.add('b', 'b-id')
171
        tree_a.commit('added b')
2255.7.12 by John Arbash Meinel
Some comments on merge code, fix merge tests that
172
        # basis_tree() is only guaranteed to be valid as long as it is actually
173
        # the basis tree. This mutates the tree after grabbing basis, so go to
174
        # the repository.
175
        base_tree = tree_a.branch.repository.revision_tree(tree_a.last_revision())
1551.8.22 by Aaron Bentley
Improve message when OTHER deletes an in-use tree
176
        tree_z = tree_a.bzrdir.sprout('z').open_workingtree()
177
        self.build_tree(['a/b/c'])
178
        tree_a.add('b/c')
179
        tree_a.commit('added c')
180
        os.rmdir('z/b')
181
        tree_z.commit('removed b')
182
        merge_inner(tree_z.branch, tree_a, base_tree, this_tree=tree_z)
183
        self.assertEqual([
184
            conflicts.MissingParent('Created directory', 'b', 'b-id'),
185
            conflicts.UnversionedParent('Versioned directory', 'b', 'b-id')],
186
            tree_z.conflicts())
2255.2.216 by Robert Collins
simplify merge_nested tests.
187
        merge_inner(tree_a.branch, tree_z.basis_tree(), base_tree,
1551.8.22 by Aaron Bentley
Improve message when OTHER deletes an in-use tree
188
                    this_tree=tree_a)
189
        self.assertEqual([
190
            conflicts.DeletingParent('Not deleting', 'b', 'b-id'),
191
            conflicts.UnversionedParent('Versioned directory', 'b', 'b-id')],
192
            tree_a.conflicts())
1551.10.2 by Aaron Bentley
Handle merge with dangling inventory entries
193
2100.3.29 by Aaron Bentley
Get merge working initially
194
    def test_nested_merge(self):
2255.2.194 by Robert Collins
[BROKEN] Many updates to stop using experimental formats in tests.
195
        tree = self.make_branch_and_tree('tree',
196
            format='dirstate-with-subtree')
2100.3.29 by Aaron Bentley
Get merge working initially
197
        sub_tree = self.make_branch_and_tree('tree/sub-tree',
2255.2.194 by Robert Collins
[BROKEN] Many updates to stop using experimental formats in tests.
198
            format='dirstate-with-subtree')
2100.3.29 by Aaron Bentley
Get merge working initially
199
        sub_tree.set_root_id('sub-tree-root')
200
        self.build_tree_contents([('tree/sub-tree/file', 'text1')])
201
        sub_tree.add('file')
202
        sub_tree.commit('foo')
203
        tree.add_reference(sub_tree)
204
        tree.commit('set text to 1')
205
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
2255.2.217 by Martin Pool
docs
206
        # modify the file in the subtree
2100.3.29 by Aaron Bentley
Get merge working initially
207
        self.build_tree_contents([('tree2/sub-tree/file', 'text2')])
2255.2.217 by Martin Pool
docs
208
        # and merge the changes from the diverged subtree into the containing
209
        # tree
2255.2.216 by Robert Collins
simplify merge_nested tests.
210
        tree2.commit('changed file text')
2100.3.29 by Aaron Bentley
Get merge working initially
211
        tree.merge_from_branch(tree2.branch)
212
        self.assertFileEqual('text2', 'tree/sub-tree/file')
213
1551.10.2 by Aaron Bentley
Handle merge with dangling inventory entries
214
    def test_merge_with_missing(self):
215
        tree_a = self.make_branch_and_tree('tree_a')
216
        self.build_tree_contents([('tree_a/file', 'content_1')])
217
        tree_a.add('file')
218
        tree_a.commit('commit base')
2255.7.12 by John Arbash Meinel
Some comments on merge code, fix merge tests that
219
        # basis_tree() is only guaranteed to be valid as long as it is actually
220
        # the basis tree. This mutates the tree after grabbing basis, so go to
221
        # the repository.
222
        base_tree = tree_a.branch.repository.revision_tree(tree_a.last_revision())
1551.10.2 by Aaron Bentley
Handle merge with dangling inventory entries
223
        tree_b = tree_a.bzrdir.sprout('tree_b').open_workingtree()
224
        self.build_tree_contents([('tree_a/file', 'content_2')])
225
        tree_a.commit('commit other')
226
        other_tree = tree_a.basis_tree()
227
        os.unlink('tree_b/file')
228
        merge_inner(tree_b.branch, other_tree, base_tree, this_tree=tree_b)
1959.4.6 by Aaron Bentley
Ensure merge works across kind changes
229
230
    def test_merge_kind_change(self):
231
        tree_a = self.make_branch_and_tree('tree_a')
232
        self.build_tree_contents([('tree_a/file', 'content_1')])
233
        tree_a.add('file', 'file-id')
234
        tree_a.commit('added file')
235
        tree_b = tree_a.bzrdir.sprout('tree_b').open_workingtree()
236
        os.unlink('tree_a/file')
237
        self.build_tree(['tree_a/file/'])
238
        tree_a.commit('changed file to directory')
239
        tree_b.merge_from_branch(tree_a.branch)
240
        self.assertEqual('directory', file_kind('tree_b/file'))
2748.3.2 by Aaron Bentley
Fix revert, remove-tree, and various tests to use None for 'no files specified'
241
        tree_b.revert()
1959.4.6 by Aaron Bentley
Ensure merge works across kind changes
242
        self.assertEqual('file', file_kind('tree_b/file'))
243
        self.build_tree_contents([('tree_b/file', 'content_2')])
244
        tree_b.commit('content change')
245
        tree_b.merge_from_branch(tree_a.branch)
246
        self.assertEqual(tree_b.conflicts(),
247
                         [conflicts.ContentsConflict('file',
248
                          file_id='file-id')])
2221.4.16 by Aaron Bentley
Add tests for get_merge_type_registry
249
    
250
    def test_merge_type_registry(self):
251
        merge_type_option = option.Option.OPTIONS['merge-type']
252
        self.assertFalse('merge4' in [x[0] for x in 
253
                        merge_type_option.iter_switches()])
254
        registry = _mod_merge.get_merge_type_registry()
255
        registry.register_lazy('merge4', 'bzrlib.merge', 'Merge4Merger',
256
                               'time-travelling merge')
257
        self.assertTrue('merge4' in [x[0] for x in 
258
                        merge_type_option.iter_switches()])
259
        registry.remove('merge4')
260
        self.assertFalse('merge4' in [x[0] for x in 
261
                        merge_type_option.iter_switches()])
1551.16.2 by Aaron Bentley
Don't crash on merging renamed deleted files (#110279)
262
1551.16.3 by Aaron Bentley
Rename test case
263
    def test_merge_other_moves_we_deleted(self):
1551.16.2 by Aaron Bentley
Don't crash on merging renamed deleted files (#110279)
264
        tree_a = self.make_branch_and_tree('A')
265
        tree_a.lock_write()
266
        self.addCleanup(tree_a.unlock)
267
        self.build_tree(['A/a'])
268
        tree_a.add('a')
269
        tree_a.commit('1', rev_id='rev-1')
270
        tree_a.flush()
271
        tree_a.rename_one('a', 'b')
272
        tree_a.commit('2')
273
        bzrdir_b = tree_a.bzrdir.sprout('B', revision_id='rev-1')
274
        tree_b = bzrdir_b.open_workingtree()
275
        tree_b.lock_write()
276
        self.addCleanup(tree_b.unlock)
277
        os.unlink('B/a')
278
        tree_b.commit('3')
279
        try:
280
            tree_b.merge_from_branch(tree_a.branch)
281
        except AttributeError:
282
            self.fail('tried to join a path when name was None')
2644.1.1 by Wouter van Heyst
Fix bug #127115 by checking for self.other_rev_id being None in Merger.set_pending()
283
2644.1.2 by Wouter van Heyst
As Aaron explained #127115 is more general, failing whenever other's basis is an ancestor of this' basis.
284
    def test_merge_uncommitted_otherbasis_ancestor_of_thisbasis(self):
2644.1.1 by Wouter van Heyst
Fix bug #127115 by checking for self.other_rev_id being None in Merger.set_pending()
285
        tree_a = self.make_branch_and_tree('a')
2644.1.2 by Wouter van Heyst
As Aaron explained #127115 is more general, failing whenever other's basis is an ancestor of this' basis.
286
        self.build_tree(['a/file_1', 'a/file_2'])
2644.1.1 by Wouter van Heyst
Fix bug #127115 by checking for self.other_rev_id being None in Merger.set_pending()
287
        tree_a.add(['file_1'])
288
        tree_a.commit('commit 1')
2644.1.2 by Wouter van Heyst
As Aaron explained #127115 is more general, failing whenever other's basis is an ancestor of this' basis.
289
        tree_a.add(['file_2'])
290
        tree_a.commit('commit 2')
2644.1.1 by Wouter van Heyst
Fix bug #127115 by checking for self.other_rev_id being None in Merger.set_pending()
291
        tree_b = tree_a.bzrdir.sprout('b').open_workingtree()
2644.1.2 by Wouter van Heyst
As Aaron explained #127115 is more general, failing whenever other's basis is an ancestor of this' basis.
292
        tree_b.rename_one('file_1', 'renamed')
1551.15.72 by Aaron Bentley
remove builtins._merge_helper
293
        merger = _mod_merge.Merger.from_uncommitted(tree_a, tree_b,
294
                                                    progress.DummyProgress())
295
        merger.merge_type = _mod_merge.Merge3Merger
296
        merger.do_merge()
2644.1.2 by Wouter van Heyst
As Aaron explained #127115 is more general, failing whenever other's basis is an ancestor of this' basis.
297
        self.assertEqual(tree_a.get_parent_ids(), [tree_b.last_revision()])
3062.1.9 by Aaron Bentley
Move PlanMerge into merge and _PlanMergeVersionedFile into versionedfile
298
3146.5.1 by Aaron Bentley
Make merge --uncommitted work with merge-type weave
299
    def test_merge_uncommitted_otherbasis_ancestor_of_thisbasis_weave(self):
300
        tree_a = self.make_branch_and_tree('a')
301
        self.build_tree(['a/file_1', 'a/file_2'])
302
        tree_a.add(['file_1'])
303
        tree_a.commit('commit 1')
304
        tree_a.add(['file_2'])
305
        tree_a.commit('commit 2')
306
        tree_b = tree_a.bzrdir.sprout('b').open_workingtree()
307
        tree_b.rename_one('file_1', 'renamed')
308
        merger = _mod_merge.Merger.from_uncommitted(tree_a, tree_b,
309
                                                    progress.DummyProgress())
310
        merger.merge_type = _mod_merge.WeaveMerger
311
        merger.do_merge()
312
        self.assertEqual(tree_a.get_parent_ids(), [tree_b.last_revision()])
313
3062.2.7 by Aaron Bentley
Prevent reverse cherry-picking with weave
314
    def prepare_cherrypick(self):
3062.2.13 by Aaron Bentley
Update prepare_cherrypick docstring
315
        """Prepare a pair of trees for cherrypicking tests.
316
317
        Both trees have a file, 'file'.
318
        rev1 sets content to 'a'.
319
        rev2b adds 'b'.
320
        rev3b adds 'c'.
321
        A full merge of rev2b and rev3b into this_tree would add both 'b' and
322
        'c'.  A successful cherrypick of rev2b-rev3b into this_tree will add
323
        'c', but not 'b'.
324
        """
3062.2.6 by Aaron Bentley
Get cherrypick-on-weave working
325
        this_tree = self.make_branch_and_tree('this')
326
        self.build_tree_contents([('this/file', "a\n")])
327
        this_tree.add('file')
328
        this_tree.commit('rev1')
329
        other_tree = this_tree.bzrdir.sprout('other').open_workingtree()
330
        self.build_tree_contents([('other/file', "a\nb\n")])
331
        other_tree.commit('rev2b', rev_id='rev2b')
332
        self.build_tree_contents([('other/file', "c\na\nb\n")])
333
        other_tree.commit('rev3b', rev_id='rev3b')
334
        this_tree.lock_write()
335
        self.addCleanup(this_tree.unlock)
3062.2.7 by Aaron Bentley
Prevent reverse cherry-picking with weave
336
        return this_tree, other_tree
337
338
    def test_weave_cherrypick(self):
339
        this_tree, other_tree = self.prepare_cherrypick()
3062.2.6 by Aaron Bentley
Get cherrypick-on-weave working
340
        merger = _mod_merge.Merger.from_revision_ids(progress.DummyProgress(),
341
            this_tree, 'rev3b', 'rev2b', other_tree.branch)
342
        merger.merge_type = _mod_merge.WeaveMerger
343
        merger.do_merge()
344
        self.assertFileEqual('c\na\n', 'this/file')
345
3062.2.7 by Aaron Bentley
Prevent reverse cherry-picking with weave
346
    def test_weave_cannot_reverse_cherrypick(self):
347
        this_tree, other_tree = self.prepare_cherrypick()
348
        merger = _mod_merge.Merger.from_revision_ids(progress.DummyProgress(),
349
            this_tree, 'rev2b', 'rev3b', other_tree.branch)
350
        merger.merge_type = _mod_merge.WeaveMerger
351
        self.assertRaises(errors.CannotReverseCherrypick, merger.do_merge)
352
353
    def test_merge3_can_reverse_cherrypick(self):
354
        this_tree, other_tree = self.prepare_cherrypick()
355
        merger = _mod_merge.Merger.from_revision_ids(progress.DummyProgress(),
356
            this_tree, 'rev2b', 'rev3b', other_tree.branch)
357
        merger.merge_type = _mod_merge.Merge3Merger
358
        merger.do_merge()
359
3249.3.1 by John Arbash Meinel
Implement cherrypick support for Merge3
360
    def test_merge3_will_detect_cherrypick(self):
361
        this_tree = self.make_branch_and_tree('this')
362
        self.build_tree_contents([('this/file', "a\n")])
363
        this_tree.add('file')
364
        this_tree.commit('rev1')
365
        other_tree = this_tree.bzrdir.sprout('other').open_workingtree()
366
        self.build_tree_contents([('other/file', "a\nb\n")])
367
        other_tree.commit('rev2b', rev_id='rev2b')
368
        self.build_tree_contents([('other/file', "a\nb\nc\n")])
369
        other_tree.commit('rev3b', rev_id='rev3b')
370
        this_tree.lock_write()
371
        self.addCleanup(this_tree.unlock)
372
373
        merger = _mod_merge.Merger.from_revision_ids(progress.DummyProgress(),
374
            this_tree, 'rev3b', 'rev2b', other_tree.branch)
375
        merger.merge_type = _mod_merge.Merge3Merger
376
        merger.do_merge()
377
        self.assertFileEqual('a\n'
378
                             '<<<<<<< TREE\n'
379
                             '=======\n'
380
                             'c\n'
381
                             '>>>>>>> MERGE-SOURCE\n',
382
                             'this/file')
383
3008.1.21 by Aaron Bentley
Make compute_transform private, test make_preview_transform
384
    def test_make_merger(self):
385
        this_tree = self.make_branch_and_tree('this')
386
        this_tree.commit('rev1', rev_id='rev1')
387
        other_tree = this_tree.bzrdir.sprout('other').open_workingtree()
388
        this_tree.commit('rev2', rev_id='rev2a')
389
        other_tree.commit('rev2', rev_id='rev2b')
390
        this_tree.lock_write()
391
        self.addCleanup(this_tree.unlock)
392
        merger = _mod_merge.Merger.from_revision_ids(progress.DummyProgress,
393
            this_tree, 'rev2b', other_branch=other_tree.branch)
394
        merger.merge_type = _mod_merge.Merge3Merger
395
        tree_merger = merger.make_merger()
396
        self.assertIs(_mod_merge.Merge3Merger, tree_merger.__class__)
397
        self.assertEqual('rev2b', tree_merger.other_tree.get_revision_id())
398
        self.assertEqual('rev1', tree_merger.base_tree.get_revision_id())
399
400
    def test_make_preview_transform(self):
401
        this_tree = self.make_branch_and_tree('this')
402
        self.build_tree_contents([('this/file', '1\n')])
403
        this_tree.add('file', 'file-id')
404
        this_tree.commit('rev1', rev_id='rev1')
405
        other_tree = this_tree.bzrdir.sprout('other').open_workingtree()
406
        self.build_tree_contents([('this/file', '1\n2a\n')])
407
        this_tree.commit('rev2', rev_id='rev2a')
408
        self.build_tree_contents([('other/file', '2b\n1\n')])
409
        other_tree.commit('rev2', rev_id='rev2b')
410
        this_tree.lock_write()
411
        self.addCleanup(this_tree.unlock)
412
        merger = _mod_merge.Merger.from_revision_ids(progress.DummyProgress(),
413
            this_tree, 'rev2b', other_branch=other_tree.branch)
414
        merger.merge_type = _mod_merge.Merge3Merger
415
        tree_merger = merger.make_merger()
416
        tt = tree_merger.make_preview_transform()
3199.1.5 by Vincent Ladeuil
Fix two more leaking tmp dirs, by reworking TransformPreview lock handling.
417
        self.addCleanup(tt.finalize)
3008.1.21 by Aaron Bentley
Make compute_transform private, test make_preview_transform
418
        preview_tree = tt.get_preview_tree()
419
        tree_file = this_tree.get_file('file-id')
420
        try:
421
            self.assertEqual('1\n2a\n', tree_file.read())
422
        finally:
423
            tree_file.close()
424
        preview_file = preview_tree.get_file('file-id')
425
        try:
426
            self.assertEqual('2b\n1\n2a\n', preview_file.read())
427
        finally:
428
            preview_file.close()
429
3008.1.22 by Aaron Bentley
Get do_merge under test
430
    def test_do_merge(self):
431
        this_tree = self.make_branch_and_tree('this')
432
        self.build_tree_contents([('this/file', '1\n')])
433
        this_tree.add('file', 'file-id')
434
        this_tree.commit('rev1', rev_id='rev1')
435
        other_tree = this_tree.bzrdir.sprout('other').open_workingtree()
436
        self.build_tree_contents([('this/file', '1\n2a\n')])
437
        this_tree.commit('rev2', rev_id='rev2a')
438
        self.build_tree_contents([('other/file', '2b\n1\n')])
439
        other_tree.commit('rev2', rev_id='rev2b')
440
        this_tree.lock_write()
441
        self.addCleanup(this_tree.unlock)
442
        merger = _mod_merge.Merger.from_revision_ids(progress.DummyProgress(),
443
            this_tree, 'rev2b', other_branch=other_tree.branch)
444
        merger.merge_type = _mod_merge.Merge3Merger
445
        tree_merger = merger.make_merger()
446
        tt = tree_merger.do_merge()
447
        tree_file = this_tree.get_file('file-id')
448
        try:
449
            self.assertEqual('2b\n1\n2a\n', tree_file.read())
450
        finally:
451
            tree_file.close()
452
1551.19.32 by Aaron Bentley
Don't traceback when adding files to a deleted root (abentley, #210092)
453
    def test_merge_add_into_deleted_root(self):
454
        # Yes, people actually do this.  And report bugs if it breaks.
455
        source = self.make_branch_and_tree('source', format='rich-root-pack')
456
        self.build_tree(['source/foo/'])
457
        source.add('foo', 'foo-id')
458
        source.commit('Add foo')
459
        target = source.bzrdir.sprout('target').open_workingtree()
460
        subtree = target.extract('foo-id')
461
        subtree.commit('Delete root')
462
        self.build_tree(['source/bar'])
463
        source.add('bar', 'bar-id')
464
        source.commit('Add bar')
465
        subtree.merge_from_branch(source.branch)
466
3649.3.1 by Jelmer Vernooij
Merging from a previously joined branch will no longer cause a traceback.
467
    def test_merge_joined_branch(self):
468
        source = self.make_branch_and_tree('source', format='rich-root-pack')
469
        self.build_tree(['source/foo'])
470
        source.add('foo')
471
        source.commit('Add foo')
472
        target = self.make_branch_and_tree('target', format='rich-root-pack')
473
        self.build_tree(['target/bla'])
474
        target.add('bla')
475
        target.commit('Add bla')
476
        nested = source.bzrdir.sprout('target/subtree').open_workingtree()
477
        target.subsume(nested)
478
        target.commit('Join nested')
479
        self.build_tree(['source/bar'])
480
        source.add('bar')
481
        source.commit('Add bar')
482
        target.merge_from_branch(source.branch)
483
        target.commit('Merge source')
484
3062.1.9 by Aaron Bentley
Move PlanMerge into merge and _PlanMergeVersionedFile into versionedfile
485
486
class TestPlanMerge(TestCaseWithMemoryTransport):
487
488
    def setUp(self):
489
        TestCaseWithMemoryTransport.setUp(self)
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
490
        mapper = versionedfile.PrefixMapper()
491
        factory = knit.make_file_factory(True, mapper)
492
        self.vf = factory(self.get_transport())
493
        self.plan_merge_vf = versionedfile._PlanMergeVersionedFile('root')
494
        self.plan_merge_vf.fallback_versionedfiles.append(self.vf)
495
496
    def add_version(self, key, parents, text):
497
        self.vf.add_lines(key, parents, [c+'\n' for c in text])
498
3514.2.10 by John Arbash Meinel
Handle more edge cases.
499
    def add_rev(self, prefix, revision_id, parents, text):
500
        self.add_version((prefix, revision_id), [(prefix, p) for p in parents],
501
                         text)
502
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
503
    def add_uncommitted_version(self, key, parents, text):
504
        self.plan_merge_vf.add_lines(key, parents,
3062.1.9 by Aaron Bentley
Move PlanMerge into merge and _PlanMergeVersionedFile into versionedfile
505
                                     [c+'\n' for c in text])
506
507
    def setup_plan_merge(self):
3514.2.17 by John Arbash Meinel
On Ian's suggestion, change the 'plan_merge' tests to use the clearer 'add_rev' instead of 'add_version'
508
        self.add_rev('root', 'A', [], 'abc')
509
        self.add_rev('root', 'B', ['A'], 'acehg')
510
        self.add_rev('root', 'C', ['A'], 'fabg')
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
511
        return _PlanMerge('B', 'C', self.plan_merge_vf, ('root',))
3062.1.9 by Aaron Bentley
Move PlanMerge into merge and _PlanMergeVersionedFile into versionedfile
512
513
    def setup_plan_merge_uncommitted(self):
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
514
        self.add_version(('root', 'A'), [], 'abc')
515
        self.add_uncommitted_version(('root', 'B:'), [('root', 'A')], 'acehg')
516
        self.add_uncommitted_version(('root', 'C:'), [('root', 'A')], 'fabg')
517
        return _PlanMerge('B:', 'C:', self.plan_merge_vf, ('root',))
3062.1.9 by Aaron Bentley
Move PlanMerge into merge and _PlanMergeVersionedFile into versionedfile
518
519
    def test_unique_lines(self):
520
        plan = self.setup_plan_merge()
521
        self.assertEqual(plan._unique_lines(
522
            plan._get_matching_blocks('B', 'C')),
523
            ([1, 2, 3], [0, 2]))
524
3514.2.6 by John Arbash Meinel
Write a (failing) test for complex ancestry.
525
    def test_plan_merge(self):
526
        self.setup_plan_merge()
527
        plan = self.plan_merge_vf.plan_merge('B', 'C')
528
        self.assertEqual([
529
                          ('new-b', 'f\n'),
530
                          ('unchanged', 'a\n'),
531
                          ('killed-a', 'b\n'),
532
                          ('killed-b', 'c\n'),
533
                          ('new-a', 'e\n'),
534
                          ('new-a', 'h\n'),
3514.2.8 by John Arbash Meinel
The insertion ordering into the weave has an impact on conflicts.
535
                          ('new-a', 'g\n'),
536
                          ('new-b', 'g\n')],
3514.2.6 by John Arbash Meinel
Write a (failing) test for complex ancestry.
537
                         list(plan))
538
3514.2.2 by John Arbash Meinel
Restore a real weave merge to 'bzr merge --weave'.
539
    def test_plan_merge_cherrypick(self):
3514.2.17 by John Arbash Meinel
On Ian's suggestion, change the 'plan_merge' tests to use the clearer 'add_rev' instead of 'add_version'
540
        self.add_rev('root', 'A', [], 'abc')
541
        self.add_rev('root', 'B', ['A'], 'abcde')
542
        self.add_rev('root', 'C', ['A'], 'abcefg')
543
        self.add_rev('root', 'D', ['A', 'B', 'C'], 'abcdegh')
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
544
        my_plan = _PlanMerge('B', 'D', self.plan_merge_vf, ('root',))
3514.2.11 by John Arbash Meinel
Shortcut the case when one revision is in the ancestry of the other.
545
        # We shortcut when one text supersedes the other in the per-file graph.
546
        # We don't actually need to compare the texts at this point.
3514.2.2 by John Arbash Meinel
Restore a real weave merge to 'bzr merge --weave'.
547
        self.assertEqual([
3514.2.11 by John Arbash Meinel
Shortcut the case when one revision is in the ancestry of the other.
548
                          ('new-b', 'a\n'),
549
                          ('new-b', 'b\n'),
550
                          ('new-b', 'c\n'),
551
                          ('new-b', 'd\n'),
552
                          ('new-b', 'e\n'),
3514.2.2 by John Arbash Meinel
Restore a real weave merge to 'bzr merge --weave'.
553
                          ('new-b', 'g\n'),
554
                          ('new-b', 'h\n')],
555
                          list(my_plan.plan_merge()))
3062.1.9 by Aaron Bentley
Move PlanMerge into merge and _PlanMergeVersionedFile into versionedfile
556
3514.2.2 by John Arbash Meinel
Restore a real weave merge to 'bzr merge --weave'.
557
    def test_plan_merge_no_common_ancestor(self):
3514.2.17 by John Arbash Meinel
On Ian's suggestion, change the 'plan_merge' tests to use the clearer 'add_rev' instead of 'add_version'
558
        self.add_rev('root', 'A', [], 'abc')
559
        self.add_rev('root', 'B', [], 'xyz')
3514.2.2 by John Arbash Meinel
Restore a real weave merge to 'bzr merge --weave'.
560
        my_plan = _PlanMerge('A', 'B', self.plan_merge_vf, ('root',))
561
        self.assertEqual([
3514.2.8 by John Arbash Meinel
The insertion ordering into the weave has an impact on conflicts.
562
                          ('new-a', 'a\n'),
563
                          ('new-a', 'b\n'),
564
                          ('new-a', 'c\n'),
3514.2.2 by John Arbash Meinel
Restore a real weave merge to 'bzr merge --weave'.
565
                          ('new-b', 'x\n'),
566
                          ('new-b', 'y\n'),
3514.2.8 by John Arbash Meinel
The insertion ordering into the weave has an impact on conflicts.
567
                          ('new-b', 'z\n')],
3514.2.2 by John Arbash Meinel
Restore a real weave merge to 'bzr merge --weave'.
568
                          list(my_plan.plan_merge()))
3062.1.9 by Aaron Bentley
Move PlanMerge into merge and _PlanMergeVersionedFile into versionedfile
569
3514.2.10 by John Arbash Meinel
Handle more edge cases.
570
    def test_plan_merge_tail_ancestors(self):
571
        # The graph looks like this:
572
        #       A       # Common to all ancestors
573
        #      / \
574
        #     B   C     # Ancestors of E, only common to one side
575
        #     |\ /|
576
        #     D E F     # D, F are unique to G, H respectively
577
        #     |/ \|     # E is the LCA for G & H, and the unique LCA for
578
        #     G   H     # I, J
579
        #     |\ /|
580
        #     | X |
581
        #     |/ \|
582
        #     I   J     # criss-cross merge of G, H
583
        #
584
        # In this situation, a simple pruning of ancestors of E will leave D &
585
        # F "dangling", which looks like they introduce lines different from
586
        # the ones in E, but in actuality C&B introduced the lines, and they
587
        # are already present in E
588
589
        # Introduce the base text
590
        self.add_rev('root', 'A', [], 'abc')
591
        # Introduces a new line B
592
        self.add_rev('root', 'B', ['A'], 'aBbc')
593
        # Introduces a new line C
594
        self.add_rev('root', 'C', ['A'], 'abCc')
595
        # Introduce new line D
596
        self.add_rev('root', 'D', ['B'], 'DaBbc')
597
        # Merges B and C by just incorporating both
598
        self.add_rev('root', 'E', ['B', 'C'], 'aBbCc')
599
        # Introduce new line F
600
        self.add_rev('root', 'F', ['C'], 'abCcF')
601
        # Merge D & E by just combining the texts
602
        self.add_rev('root', 'G', ['D', 'E'], 'DaBbCc')
603
        # Merge F & E by just combining the texts
604
        self.add_rev('root', 'H', ['F', 'E'], 'aBbCcF')
605
        # Merge G & H by just combining texts
606
        self.add_rev('root', 'I', ['G', 'H'], 'DaBbCcF')
607
        # Merge G & H but supersede an old line in B
608
        self.add_rev('root', 'J', ['H', 'G'], 'DaJbCcF')
609
        plan = self.plan_merge_vf.plan_merge('I', 'J')
610
        self.assertEqual([
611
                          ('unchanged', 'D\n'),
612
                          ('unchanged', 'a\n'),
613
                          ('killed-b', 'B\n'),
614
                          ('new-b', 'J\n'),
615
                          ('unchanged', 'b\n'),
616
                          ('unchanged', 'C\n'),
617
                          ('unchanged', 'c\n'),
618
                          ('unchanged', 'F\n')],
619
                         list(plan))
620
621
    def test_plan_merge_tail_triple_ancestors(self):
622
        # The graph looks like this:
623
        #       A       # Common to all ancestors
624
        #      / \
625
        #     B   C     # Ancestors of E, only common to one side
626
        #     |\ /|
627
        #     D E F     # D, F are unique to G, H respectively
628
        #     |/|\|     # E is the LCA for G & H, and the unique LCA for
629
        #     G Q H     # I, J
630
        #     |\ /|     # Q is just an extra node which is merged into both
631
        #     | X |     # I and J
632
        #     |/ \|
633
        #     I   J     # criss-cross merge of G, H
634
        #
635
        # This is the same as the test_plan_merge_tail_ancestors, except we add
636
        # a third LCA that doesn't add new lines, but will trigger our more
637
        # involved ancestry logic
638
639
        self.add_rev('root', 'A', [], 'abc')
640
        self.add_rev('root', 'B', ['A'], 'aBbc')
641
        self.add_rev('root', 'C', ['A'], 'abCc')
642
        self.add_rev('root', 'D', ['B'], 'DaBbc')
643
        self.add_rev('root', 'E', ['B', 'C'], 'aBbCc')
644
        self.add_rev('root', 'F', ['C'], 'abCcF')
645
        self.add_rev('root', 'G', ['D', 'E'], 'DaBbCc')
646
        self.add_rev('root', 'H', ['F', 'E'], 'aBbCcF')
647
        self.add_rev('root', 'Q', ['E'], 'aBbCc')
648
        self.add_rev('root', 'I', ['G', 'Q', 'H'], 'DaBbCcF')
649
        # Merge G & H but supersede an old line in B
650
        self.add_rev('root', 'J', ['H', 'Q', 'G'], 'DaJbCcF')
651
        plan = self.plan_merge_vf.plan_merge('I', 'J')
652
        self.assertEqual([
653
                          ('unchanged', 'D\n'),
654
                          ('unchanged', 'a\n'),
655
                          ('killed-b', 'B\n'),
656
                          ('new-b', 'J\n'),
657
                          ('unchanged', 'b\n'),
658
                          ('unchanged', 'C\n'),
659
                          ('unchanged', 'c\n'),
660
                          ('unchanged', 'F\n')],
661
                         list(plan))
662
3514.2.14 by John Arbash Meinel
Bring in the code to collapse linear portions of the graph.
663
    def test_plan_merge_2_tail_triple_ancestors(self):
664
        # The graph looks like this:
665
        #     A   B     # 2 tails going back to NULL
666
        #     |\ /|
667
        #     D E F     # D, is unique to G, F to H
668
        #     |/|\|     # E is the LCA for G & H, and the unique LCA for
669
        #     G Q H     # I, J
670
        #     |\ /|     # Q is just an extra node which is merged into both
671
        #     | X |     # I and J
672
        #     |/ \|
673
        #     I   J     # criss-cross merge of G, H (and Q)
674
        #
675
676
        # This is meant to test after hitting a 3-way LCA, and multiple tail
677
        # ancestors (only have NULL_REVISION in common)
678
679
        self.add_rev('root', 'A', [], 'abc')
680
        self.add_rev('root', 'B', [], 'def')
681
        self.add_rev('root', 'D', ['A'], 'Dabc')
682
        self.add_rev('root', 'E', ['A', 'B'], 'abcdef')
683
        self.add_rev('root', 'F', ['B'], 'defF')
684
        self.add_rev('root', 'G', ['D', 'E'], 'Dabcdef')
685
        self.add_rev('root', 'H', ['F', 'E'], 'abcdefF')
686
        self.add_rev('root', 'Q', ['E'], 'abcdef')
687
        self.add_rev('root', 'I', ['G', 'Q', 'H'], 'DabcdefF')
688
        # Merge G & H but supersede an old line in B
689
        self.add_rev('root', 'J', ['H', 'Q', 'G'], 'DabcdJfF')
690
        plan = self.plan_merge_vf.plan_merge('I', 'J')
691
        self.assertEqual([
692
                          ('unchanged', 'D\n'),
693
                          ('unchanged', 'a\n'),
694
                          ('unchanged', 'b\n'),
695
                          ('unchanged', 'c\n'),
696
                          ('unchanged', 'd\n'),
697
                          ('killed-b', 'e\n'),
698
                          ('new-b', 'J\n'),
699
                          ('unchanged', 'f\n'),
700
                          ('unchanged', 'F\n')],
701
                         list(plan))
702
3062.1.9 by Aaron Bentley
Move PlanMerge into merge and _PlanMergeVersionedFile into versionedfile
703
    def test_plan_merge_uncommitted_files(self):
3062.1.13 by Aaron Bentley
Make _PlanMerge an implementation detail of _PlanMergeVersionedFile
704
        self.setup_plan_merge_uncommitted()
705
        plan = self.plan_merge_vf.plan_merge('B:', 'C:')
3062.1.9 by Aaron Bentley
Move PlanMerge into merge and _PlanMergeVersionedFile into versionedfile
706
        self.assertEqual([
707
                          ('new-b', 'f\n'),
708
                          ('unchanged', 'a\n'),
3514.2.2 by John Arbash Meinel
Restore a real weave merge to 'bzr merge --weave'.
709
                          ('killed-a', 'b\n'),
3062.1.9 by Aaron Bentley
Move PlanMerge into merge and _PlanMergeVersionedFile into versionedfile
710
                          ('killed-b', 'c\n'),
711
                          ('new-a', 'e\n'),
712
                          ('new-a', 'h\n'),
3514.2.8 by John Arbash Meinel
The insertion ordering into the weave has an impact on conflicts.
713
                          ('new-a', 'g\n'),
714
                          ('new-b', 'g\n')],
715
                         list(plan))
716
717
    def test_plan_merge_insert_order(self):
718
        """Weave merges are sensitive to the order of insertion.
719
        
720
        Specifically for overlapping regions, it effects which region gets put
721
        'first'. And when a user resolves an overlapping merge, if they use the
722
        same ordering, then the lines match the parents, if they don't only
723
        *some* of the lines match.
724
        """
3514.2.17 by John Arbash Meinel
On Ian's suggestion, change the 'plan_merge' tests to use the clearer 'add_rev' instead of 'add_version'
725
        self.add_rev('root', 'A', [], 'abcdef')
726
        self.add_rev('root', 'B', ['A'], 'abwxcdef')
727
        self.add_rev('root', 'C', ['A'], 'abyzcdef')
3514.2.8 by John Arbash Meinel
The insertion ordering into the weave has an impact on conflicts.
728
        # Merge, and resolve the conflict by adding *both* sets of lines
729
        # If we get the ordering wrong, these will look like new lines in D,
730
        # rather than carried over from B, C
3514.2.17 by John Arbash Meinel
On Ian's suggestion, change the 'plan_merge' tests to use the clearer 'add_rev' instead of 'add_version'
731
        self.add_rev('root', 'D', ['B', 'C'],
3514.2.8 by John Arbash Meinel
The insertion ordering into the weave has an impact on conflicts.
732
                         'abwxyzcdef')
733
        # Supersede the lines in B and delete the lines in C, which will
734
        # conflict if they are treated as being in D
3514.2.17 by John Arbash Meinel
On Ian's suggestion, change the 'plan_merge' tests to use the clearer 'add_rev' instead of 'add_version'
735
        self.add_rev('root', 'E', ['C', 'B'],
3514.2.8 by John Arbash Meinel
The insertion ordering into the weave has an impact on conflicts.
736
                         'abnocdef')
737
        # Same thing for the lines in C
3514.2.17 by John Arbash Meinel
On Ian's suggestion, change the 'plan_merge' tests to use the clearer 'add_rev' instead of 'add_version'
738
        self.add_rev('root', 'F', ['C'], 'abpqcdef')
3514.2.8 by John Arbash Meinel
The insertion ordering into the weave has an impact on conflicts.
739
        plan = self.plan_merge_vf.plan_merge('D', 'E')
740
        self.assertEqual([
741
                          ('unchanged', 'a\n'),
742
                          ('unchanged', 'b\n'),
743
                          ('killed-b', 'w\n'),
744
                          ('killed-b', 'x\n'),
745
                          ('killed-b', 'y\n'),
746
                          ('killed-b', 'z\n'),
747
                          ('new-b', 'n\n'),
748
                          ('new-b', 'o\n'),
749
                          ('unchanged', 'c\n'),
750
                          ('unchanged', 'd\n'),
751
                          ('unchanged', 'e\n'),
752
                          ('unchanged', 'f\n')],
753
                         list(plan))
754
        plan = self.plan_merge_vf.plan_merge('E', 'D')
755
        # Going in the opposite direction shows the effect of the opposite plan
756
        self.assertEqual([
757
                          ('unchanged', 'a\n'),
758
                          ('unchanged', 'b\n'),
759
                          ('new-b', 'w\n'),
760
                          ('new-b', 'x\n'),
761
                          ('killed-a', 'y\n'),
762
                          ('killed-a', 'z\n'),
763
                          ('killed-both', 'w\n'),
764
                          ('killed-both', 'x\n'),
765
                          ('new-a', 'n\n'),
766
                          ('new-a', 'o\n'),
767
                          ('unchanged', 'c\n'),
768
                          ('unchanged', 'd\n'),
769
                          ('unchanged', 'e\n'),
770
                          ('unchanged', 'f\n')],
3062.1.9 by Aaron Bentley
Move PlanMerge into merge and _PlanMergeVersionedFile into versionedfile
771
                         list(plan))
3062.2.1 by Aaron Bentley
Add support for plan-merge with a base
772
3514.2.6 by John Arbash Meinel
Write a (failing) test for complex ancestry.
773
    def test_plan_merge_criss_cross(self):
774
        # This is specificly trying to trigger problems when using limited
775
        # ancestry and weaves. The ancestry graph looks like:
3514.2.8 by John Arbash Meinel
The insertion ordering into the weave has an impact on conflicts.
776
        #       XX      unused ancestor, should not show up in the weave
777
        #       |
3514.2.6 by John Arbash Meinel
Write a (failing) test for complex ancestry.
778
        #       A       Unique LCA
779
        #       |\
780
        #       B \     Introduces a line 'foo'
781
        #      / \ \
782
        #     C   D E   C & D both have 'foo', E has different changes
783
        #     |\ /| |
784
        #     | X | |
785
        #     |/ \|/
786
        #     F   G      All of C, D, E are merged into F and G, so they are
787
        #                all common ancestors.
788
        #
789
        # The specific issue with weaves:
790
        #   B introduced a text ('foo') that is present in both C and D.
791
        #   If we do not include B (because it isn't an ancestor of E), then
792
        #   the A=>C and A=>D look like both sides independently introduce the
793
        #   text ('foo'). If F does not modify the text, it would still appear
794
        #   to have deleted on of the versions from C or D. If G then modifies
795
        #   'foo', it should appear as superseding the value in F (since it
796
        #   came from B), rather than conflict because of the resolution during
797
        #   C & D.
3514.2.17 by John Arbash Meinel
On Ian's suggestion, change the 'plan_merge' tests to use the clearer 'add_rev' instead of 'add_version'
798
        self.add_rev('root', 'XX', [], 'qrs')
799
        self.add_rev('root', 'A', ['XX'], 'abcdef')
800
        self.add_rev('root', 'B', ['A'], 'axcdef')
801
        self.add_rev('root', 'C', ['B'], 'axcdefg')
802
        self.add_rev('root', 'D', ['B'], 'haxcdef')
803
        self.add_rev('root', 'E', ['A'], 'abcdyf')
804
        # Simple combining of all texts
805
        self.add_rev('root', 'F', ['C', 'D', 'E'], 'haxcdyfg')
806
        # combine and supersede 'x'
807
        self.add_rev('root', 'G', ['C', 'D', 'E'], 'hazcdyfg')
3514.2.6 by John Arbash Meinel
Write a (failing) test for complex ancestry.
808
        plan = self.plan_merge_vf.plan_merge('F', 'G')
809
        self.assertEqual([
810
                          ('unchanged', 'h\n'),
811
                          ('unchanged', 'a\n'),
3514.2.7 by John Arbash Meinel
Fix the failing test by implementing the fallback logic.
812
                          ('killed-base', 'b\n'),
3514.2.6 by John Arbash Meinel
Write a (failing) test for complex ancestry.
813
                          ('killed-b', 'x\n'),
814
                          ('new-b', 'z\n'),
815
                          ('unchanged', 'c\n'),
816
                          ('unchanged', 'd\n'),
817
                          ('killed-base', 'e\n'),
818
                          ('unchanged', 'y\n'),
819
                          ('unchanged', 'f\n'),
820
                          ('unchanged', 'g\n')],
821
                         list(plan))
822
3514.2.12 by John Arbash Meinel
Start refactoring into helper functions
823
    def assertRemoveExternalReferences(self, filtered_parent_map,
824
                                       child_map, tails, parent_map):
825
        """Assert results for _PlanMerge._remove_external_references."""
826
        (act_filtered_parent_map, act_child_map,
827
         act_tails) = _PlanMerge._remove_external_references(parent_map)
828
829
        # The parent map *should* preserve ordering, but the ordering of
830
        # children is not strictly defined
831
        # child_map = dict((k, sorted(children))
832
        #                  for k, children in child_map.iteritems())
833
        # act_child_map = dict(k, sorted(children)
834
        #                      for k, children in act_child_map.iteritems())
835
        self.assertEqual(filtered_parent_map, act_filtered_parent_map)
836
        self.assertEqual(child_map, act_child_map)
837
        self.assertEqual(sorted(tails), sorted(act_tails))
838
839
    def test__remove_external_references(self):
840
        # First, nothing to remove
841
        self.assertRemoveExternalReferences({3: [2], 2: [1], 1: []},
842
            {1: [2], 2: [3], 3: []}, [1], {3: [2], 2: [1], 1: []})
843
        # The reverse direction
844
        self.assertRemoveExternalReferences({1: [2], 2: [3], 3: []},
845
            {3: [2], 2: [1], 1: []}, [3], {1: [2], 2: [3], 3: []})
846
        # Extra references
847
        self.assertRemoveExternalReferences({3: [2], 2: [1], 1: []},
848
            {1: [2], 2: [3], 3: []}, [1], {3: [2, 4], 2: [1, 5], 1: [6]})
849
        # Multiple tails
850
        self.assertRemoveExternalReferences(
851
            {4: [2, 3], 3: [], 2: [1], 1: []},
852
            {1: [2], 2: [4], 3: [4], 4: []},
853
            [1, 3],
854
            {4: [2, 3], 3: [5], 2: [1], 1: [6]})
855
        # Multiple children
856
        self.assertRemoveExternalReferences(
857
            {1: [3], 2: [3, 4], 3: [], 4: []},
858
            {1: [], 2: [], 3: [1, 2], 4: [2]},
859
            [3, 4],
860
            {1: [3], 2: [3, 4], 3: [5], 4: []})
861
3514.2.13 by John Arbash Meinel
Add the ability to prune extra tails from the parent_map.
862
    def assertPruneTails(self, pruned_map, tails, parent_map):
863
        child_map = {}
864
        for key, parent_keys in parent_map.iteritems():
865
            child_map.setdefault(key, [])
866
            for pkey in parent_keys:
867
                child_map.setdefault(pkey, []).append(key)
868
        _PlanMerge._prune_tails(parent_map, child_map, tails)
869
        self.assertEqual(pruned_map, parent_map)
870
871
    def test__prune_tails(self):
872
        # Nothing requested to prune
873
        self.assertPruneTails({1: [], 2: [], 3: []}, [],
874
                              {1: [], 2: [], 3: []})
875
        # Prune a single entry
876
        self.assertPruneTails({1: [], 3: []}, [2],
877
                              {1: [], 2: [], 3: []})
878
        # Prune a chain
879
        self.assertPruneTails({1: []}, [3],
880
                              {1: [], 2: [3], 3: []})
881
        # Prune a chain with a diamond
882
        self.assertPruneTails({1: []}, [5],
883
                              {1: [], 2: [3, 4], 3: [5], 4: [5], 5: []})
884
        # Prune a partial chain
885
        self.assertPruneTails({1: [6], 6:[]}, [5],
886
                              {1: [2, 6], 2: [3, 4], 3: [5], 4: [5], 5: [],
887
                               6: []})
888
        # Prune a chain with multiple tips, that pulls out intermediates
889
        self.assertPruneTails({1:[3], 3:[]}, [4, 5],
890
                              {1: [2, 3], 2: [4, 5], 3: [], 4:[], 5:[]})
891
        self.assertPruneTails({1:[3], 3:[]}, [5, 4],
892
                              {1: [2, 3], 2: [4, 5], 3: [], 4:[], 5:[]})
893
3062.2.1 by Aaron Bentley
Add support for plan-merge with a base
894
    def test_subtract_plans(self):
895
        old_plan = [
896
        ('unchanged', 'a\n'),
897
        ('new-a', 'b\n'),
898
        ('killed-a', 'c\n'),
899
        ('new-b', 'd\n'),
900
        ('new-b', 'e\n'),
901
        ('killed-b', 'f\n'),
902
        ('killed-b', 'g\n'),
903
        ]
904
        new_plan = [
905
        ('unchanged', 'a\n'),
906
        ('new-a', 'b\n'),
907
        ('killed-a', 'c\n'),
908
        ('new-b', 'd\n'),
909
        ('new-b', 'h\n'),
910
        ('killed-b', 'f\n'),
911
        ('killed-b', 'i\n'),
912
        ]
913
        subtracted_plan = [
914
        ('unchanged', 'a\n'),
915
        ('new-a', 'b\n'),
916
        ('killed-a', 'c\n'),
917
        ('new-b', 'h\n'),
918
        ('unchanged', 'f\n'),
919
        ('killed-b', 'i\n'),
920
        ]
921
        self.assertEqual(subtracted_plan,
3062.2.3 by Aaron Bentley
Sync up with bzr.dev API changes
922
            list(_PlanMerge._subtract_plans(old_plan, new_plan)))
3062.2.1 by Aaron Bentley
Add support for plan-merge with a base
923
3144.3.1 by Aaron Bentley
Implement LCA merge, with problematic conflict markers
924
    def setup_merge_with_base(self):
3514.2.17 by John Arbash Meinel
On Ian's suggestion, change the 'plan_merge' tests to use the clearer 'add_rev' instead of 'add_version'
925
        self.add_rev('root', 'COMMON', [], 'abc')
926
        self.add_rev('root', 'THIS', ['COMMON'], 'abcd')
927
        self.add_rev('root', 'BASE', ['COMMON'], 'eabc')
928
        self.add_rev('root', 'OTHER', ['BASE'], 'eafb')
3144.3.1 by Aaron Bentley
Implement LCA merge, with problematic conflict markers
929
930
    def test_plan_merge_with_base(self):
931
        self.setup_merge_with_base()
3062.2.3 by Aaron Bentley
Sync up with bzr.dev API changes
932
        plan = self.plan_merge_vf.plan_merge('THIS', 'OTHER', 'BASE')
3062.2.1 by Aaron Bentley
Add support for plan-merge with a base
933
        self.assertEqual([('unchanged', 'a\n'),
934
                          ('new-b', 'f\n'),
935
                          ('unchanged', 'b\n'),
936
                          ('killed-b', 'c\n'),
937
                          ('new-a', 'd\n')
938
                         ], list(plan))
3144.3.1 by Aaron Bentley
Implement LCA merge, with problematic conflict markers
939
940
    def test_plan_lca_merge(self):
941
        self.setup_plan_merge()
942
        plan = self.plan_merge_vf.plan_lca_merge('B', 'C')
943
        self.assertEqual([
944
                          ('new-b', 'f\n'),
945
                          ('unchanged', 'a\n'),
946
                          ('killed-b', 'c\n'),
947
                          ('new-a', 'e\n'),
948
                          ('new-a', 'h\n'),
949
                          ('killed-a', 'b\n'),
950
                          ('unchanged', 'g\n')],
951
                         list(plan))
952
953
    def test_plan_lca_merge_uncommitted_files(self):
954
        self.setup_plan_merge_uncommitted()
955
        plan = self.plan_merge_vf.plan_lca_merge('B:', 'C:')
956
        self.assertEqual([
957
                          ('new-b', 'f\n'),
958
                          ('unchanged', 'a\n'),
959
                          ('killed-b', 'c\n'),
960
                          ('new-a', 'e\n'),
961
                          ('new-a', 'h\n'),
962
                          ('killed-a', 'b\n'),
963
                          ('unchanged', 'g\n')],
964
                         list(plan))
965
966
    def test_plan_lca_merge_with_base(self):
967
        self.setup_merge_with_base()
968
        plan = self.plan_merge_vf.plan_lca_merge('THIS', 'OTHER', 'BASE')
969
        self.assertEqual([('unchanged', 'a\n'),
970
                          ('new-b', 'f\n'),
971
                          ('unchanged', 'b\n'),
972
                          ('killed-b', 'c\n'),
973
                          ('new-a', 'd\n')
974
                         ], list(plan))
975
976
    def test_plan_lca_merge_with_criss_cross(self):
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
977
        self.add_version(('root', 'ROOT'), [], 'abc')
3144.3.1 by Aaron Bentley
Implement LCA merge, with problematic conflict markers
978
        # each side makes a change
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
979
        self.add_version(('root', 'REV1'), [('root', 'ROOT')], 'abcd')
980
        self.add_version(('root', 'REV2'), [('root', 'ROOT')], 'abce')
3144.3.1 by Aaron Bentley
Implement LCA merge, with problematic conflict markers
981
        # both sides merge, discarding others' changes
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
982
        self.add_version(('root', 'LCA1'),
983
            [('root', 'REV1'), ('root', 'REV2')], 'abcd')
984
        self.add_version(('root', 'LCA2'),
985
            [('root', 'REV1'), ('root', 'REV2')], 'fabce')
3144.3.1 by Aaron Bentley
Implement LCA merge, with problematic conflict markers
986
        plan = self.plan_merge_vf.plan_lca_merge('LCA1', 'LCA2')
3144.3.10 by Aaron Bentley
Use correct index when emitting conflicted-b
987
        self.assertEqual([('new-b', 'f\n'),
988
                          ('unchanged', 'a\n'),
3144.3.1 by Aaron Bentley
Implement LCA merge, with problematic conflict markers
989
                          ('unchanged', 'b\n'),
990
                          ('unchanged', 'c\n'),
3144.3.3 by Aaron Bentley
Update test for new conflicted types
991
                          ('conflicted-a', 'd\n'),
992
                          ('conflicted-b', 'e\n'),
3144.3.1 by Aaron Bentley
Implement LCA merge, with problematic conflict markers
993
                         ], list(plan))
3144.5.3 by Aaron Bentley
Test interesting_files for LCA merge
994
3287.17.1 by John Arbash Meinel
Fix bug #235715 by using the empty list as the text for a base of NULL_REVISION.
995
    def test_plan_lca_merge_with_null(self):
3350.6.5 by Robert Collins
Update to bzr.dev.
996
        self.add_version(('root', 'A'), [], 'ab')
997
        self.add_version(('root', 'B'), [], 'bc')
3287.17.1 by John Arbash Meinel
Fix bug #235715 by using the empty list as the text for a base of NULL_REVISION.
998
        plan = self.plan_merge_vf.plan_lca_merge('A', 'B')
999
        self.assertEqual([('new-a', 'a\n'),
1000
                          ('unchanged', 'b\n'),
1001
                          ('new-b', 'c\n'),
1002
                         ], list(plan))
1003
3514.2.1 by Aaron Bentley
Test for correct conflicts on delete + change
1004
    def test_plan_merge_with_delete_and_change(self):
3514.2.17 by John Arbash Meinel
On Ian's suggestion, change the 'plan_merge' tests to use the clearer 'add_rev' instead of 'add_version'
1005
        self.add_rev('root', 'C', [], 'a')
1006
        self.add_rev('root', 'A', ['C'], 'b')
1007
        self.add_rev('root', 'B', ['C'], '')
3514.2.1 by Aaron Bentley
Test for correct conflicts on delete + change
1008
        plan = self.plan_merge_vf.plan_merge('A', 'B')
3514.2.2 by John Arbash Meinel
Restore a real weave merge to 'bzr merge --weave'.
1009
        self.assertEqual([('killed-both', 'a\n'),
1010
                          ('new-a', 'b\n'),
1011
                         ], list(plan))
1012
1013
    def test_plan_merge_with_move_and_change(self):
3514.2.17 by John Arbash Meinel
On Ian's suggestion, change the 'plan_merge' tests to use the clearer 'add_rev' instead of 'add_version'
1014
        self.add_rev('root', 'C', [], 'abcd')
1015
        self.add_rev('root', 'A', ['C'], 'acbd')
1016
        self.add_rev('root', 'B', ['C'], 'aBcd')
3514.2.2 by John Arbash Meinel
Restore a real weave merge to 'bzr merge --weave'.
1017
        plan = self.plan_merge_vf.plan_merge('A', 'B')
1018
        self.assertEqual([('unchanged', 'a\n'),
1019
                          ('new-a', 'c\n'),
1020
                          ('killed-b', 'b\n'),
1021
                          ('new-b', 'B\n'),
1022
                          ('killed-a', 'c\n'),
1023
                          ('unchanged', 'd\n'),
3514.2.1 by Aaron Bentley
Test for correct conflicts on delete + change
1024
                         ], list(plan))
1025
3144.5.3 by Aaron Bentley
Test interesting_files for LCA merge
1026
1027
class TestMergeImplementation(object):
1028
1029
    def do_merge(self, target_tree, source_tree, **kwargs):
1030
        merger = _mod_merge.Merger.from_revision_ids(progress.DummyProgress(),
1031
            target_tree, source_tree.last_revision(),
1032
            other_branch=source_tree.branch)
1033
        merger.merge_type=self.merge_type
1034
        for name, value in kwargs.items():
1035
            setattr(merger, name, value)
1036
        merger.do_merge()
1037
1038
    def test_merge_specific_file(self):
1039
        this_tree = self.make_branch_and_tree('this')
1040
        this_tree.lock_write()
1041
        self.addCleanup(this_tree.unlock)
1042
        self.build_tree_contents([
1043
            ('this/file1', 'a\nb\n'),
1044
            ('this/file2', 'a\nb\n')
1045
        ])
1046
        this_tree.add(['file1', 'file2'])
1047
        this_tree.commit('Added files')
1048
        other_tree = this_tree.bzrdir.sprout('other').open_workingtree()
1049
        self.build_tree_contents([
1050
            ('other/file1', 'a\nb\nc\n'),
1051
            ('other/file2', 'a\nb\nc\n')
1052
        ])
1053
        other_tree.commit('modified both')
1054
        self.build_tree_contents([
1055
            ('this/file1', 'd\na\nb\n'),
1056
            ('this/file2', 'd\na\nb\n')
1057
        ])
1058
        this_tree.commit('modified both')
1059
        self.do_merge(this_tree, other_tree, interesting_files=['file1'])
1060
        self.assertFileEqual('d\na\nb\nc\n', 'this/file1')
1061
        self.assertFileEqual('d\na\nb\n', 'this/file2')
1062
3514.2.2 by John Arbash Meinel
Restore a real weave merge to 'bzr merge --weave'.
1063
    def test_merge_move_and_change(self):
3514.2.1 by Aaron Bentley
Test for correct conflicts on delete + change
1064
        this_tree = self.make_branch_and_tree('this')
1065
        this_tree.lock_write()
1066
        self.addCleanup(this_tree.unlock)
1067
        self.build_tree_contents([
3514.2.2 by John Arbash Meinel
Restore a real weave merge to 'bzr merge --weave'.
1068
            ('this/file1', 'line 1\nline 2\nline 3\nline 4\n'),
3514.2.1 by Aaron Bentley
Test for correct conflicts on delete + change
1069
        ])
1070
        this_tree.add('file1',)
1071
        this_tree.commit('Added file')
1072
        other_tree = this_tree.bzrdir.sprout('other').open_workingtree()
1073
        self.build_tree_contents([
3514.2.2 by John Arbash Meinel
Restore a real weave merge to 'bzr merge --weave'.
1074
            ('other/file1', 'line 1\nline 2 to 2.1\nline 3\nline 4\n'),
3514.2.1 by Aaron Bentley
Test for correct conflicts on delete + change
1075
        ])
3514.2.16 by John Arbash Meinel
Review feedback from Ian.
1076
        other_tree.commit('Changed 2 to 2.1')
3514.2.1 by Aaron Bentley
Test for correct conflicts on delete + change
1077
        self.build_tree_contents([
3514.2.2 by John Arbash Meinel
Restore a real weave merge to 'bzr merge --weave'.
1078
            ('this/file1', 'line 1\nline 3\nline 2\nline 4\n'),
3514.2.1 by Aaron Bentley
Test for correct conflicts on delete + change
1079
        ])
3514.2.16 by John Arbash Meinel
Review feedback from Ian.
1080
        this_tree.commit('Swapped 2 & 3')
3514.2.1 by Aaron Bentley
Test for correct conflicts on delete + change
1081
        self.do_merge(this_tree, other_tree)
3514.2.2 by John Arbash Meinel
Restore a real weave merge to 'bzr merge --weave'.
1082
        self.assertFileEqual('line 1\n'
3514.2.1 by Aaron Bentley
Test for correct conflicts on delete + change
1083
            '<<<<<<< TREE\n'
3514.2.2 by John Arbash Meinel
Restore a real weave merge to 'bzr merge --weave'.
1084
            'line 3\n'
1085
            'line 2\n'
3514.2.1 by Aaron Bentley
Test for correct conflicts on delete + change
1086
            '=======\n'
3514.2.2 by John Arbash Meinel
Restore a real weave merge to 'bzr merge --weave'.
1087
            'line 2 to 2.1\n'
1088
            'line 3\n'
1089
            '>>>>>>> MERGE-SOURCE\n'
1090
            'line 4\n', 'this/file1')
3514.2.1 by Aaron Bentley
Test for correct conflicts on delete + change
1091
3144.5.3 by Aaron Bentley
Test interesting_files for LCA merge
1092
1093
class TestMerge3Merge(TestCaseWithTransport, TestMergeImplementation):
1094
1095
    merge_type = _mod_merge.Merge3Merger
1096
1097
1098
class TestWeaveMerge(TestCaseWithTransport, TestMergeImplementation):
1099
1100
    merge_type = _mod_merge.WeaveMerger
1101
1102
1103
class TestLCAMerge(TestCaseWithTransport, TestMergeImplementation):
1104
1105
    merge_type = _mod_merge.LCAMerger
3514.2.2 by John Arbash Meinel
Restore a real weave merge to 'bzr merge --weave'.
1106
1107
    def test_merge_move_and_change(self):
1108
        self.expectFailure("lca merge doesn't conflict for move and change",
1109
            super(TestLCAMerge, self).test_merge_move_and_change)