/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
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,
3062.1.9 by Aaron Bentley
Move PlanMerge into merge and _PlanMergeVersionedFile into versionedfile
27
    versionedfile,
2221.4.16 by Aaron Bentley
Add tests for get_merge_type_registry
28
    )
974.1.56 by aaron.bentley at utoronto
Added merge test
29
from bzrlib.branch import Branch
1551.7.10 by Aaron Bentley
Remerge doesn't clear unrelated conflicts
30
from bzrlib.conflicts import ConflictList, TextConflict
1185.24.3 by Aaron Bentley
Integrated reprocessing into the rest of the merge stuff
31
from bzrlib.errors import UnrelatedBranches, NoCommits, BzrCommandError
3062.1.13 by Aaron Bentley
Make _PlanMerge an implementation detail of _PlanMergeVersionedFile
32
from bzrlib.merge import transform_tree, merge_inner, _PlanMerge
1959.4.6 by Aaron Bentley
Ensure merge works across kind changes
33
from bzrlib.osutils import pathjoin, file_kind
1534.4.28 by Robert Collins
first cut at merge from integration.
34
from bzrlib.revision import common_ancestor
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")
108
        last = wt1.branch.last_revision()
1908.6.11 by Robert Collins
Remove usage of tree.pending_merges().
109
        self.assertEqual(common_ancestor(last, last, wt1.branch.repository), last)
1185.46.1 by Aaron Bentley
Test case when file to be renamed is also deleted
110
111
    def test_create_rename(self):
112
        """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.
113
        tree =self.make_branch_and_tree('.')
1185.46.1 by Aaron Bentley
Test case when file to be renamed is also deleted
114
        file('name1', 'wb').write('Hello')
115
        tree.add('name1')
116
        tree.commit(message="hello")
117
        tree.rename_one('name1', 'name2')
118
        os.unlink('name2')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
119
        transform_tree(tree, tree.branch.basis_tree())
1185.46.2 by Aaron Bentley
Added test for renaming both parent and child
120
121
    def test_layered_rename(self):
122
        """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.
123
        tree =self.make_branch_and_tree('.')
1185.46.2 by Aaron Bentley
Added test for renaming both parent and child
124
        os.mkdir('dirname1')
125
        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 \
126
        filename = pathjoin('dirname1', 'name1')
1185.46.2 by Aaron Bentley
Added test for renaming both parent and child
127
        file(filename, 'wb').write('Hello')
128
        tree.add(filename)
129
        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 \
130
        filename2 = pathjoin('dirname1', 'name2')
1185.46.2 by Aaron Bentley
Added test for renaming both parent and child
131
        tree.rename_one(filename, filename2)
132
        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.
133
        transform_tree(tree, tree.branch.basis_tree())
1551.2.23 by Aaron Bentley
Got merge_inner's ignore_zero parameter working
134
135
    def test_ignore_zero_merge_inner(self):
1907.4.1 by Matthieu Moy
Fixed merge to work nicely with -r revno:N:path
136
        # Test that merge_inner's ignore zero parameter is effective
1551.2.23 by Aaron Bentley
Got merge_inner's ignore_zero parameter working
137
        tree_a =self.make_branch_and_tree('a')
138
        tree_a.commit(message="hello")
139
        dir_b = tree_a.bzrdir.sprout('b')
140
        tree_b = dir_b.open_workingtree()
3146.4.4 by Aaron Bentley
Add write lock, so merge_inner works properly
141
        tree_b.lock_write()
142
        self.addCleanup(tree_b.unlock)
1551.2.23 by Aaron Bentley
Got merge_inner's ignore_zero parameter working
143
        tree_a.commit(message="hello again")
144
        log = StringIO()
145
        merge_inner(tree_b.branch, tree_a, tree_b.basis_tree(), 
146
                    this_tree=tree_b, ignore_zero=True)
1927.3.1 by Carl Friedrich Bolz
Throw away on-disk logfile when possible.
147
        log = self._get_log(keep_log_file=True)
1551.4.1 by Aaron Bentley
Workaround for silly _get_log behaviour in test
148
        self.failUnless('All changes applied successfully.\n' not in log)
2796.1.3 by Aaron Bentley
update new test case
149
        tree_b.revert()
1551.2.23 by Aaron Bentley
Got merge_inner's ignore_zero parameter working
150
        merge_inner(tree_b.branch, tree_a, tree_b.basis_tree(), 
151
                    this_tree=tree_b, ignore_zero=False)
1927.3.1 by Carl Friedrich Bolz
Throw away on-disk logfile when possible.
152
        log = self._get_log(keep_log_file=True)
1551.4.1 by Aaron Bentley
Workaround for silly _get_log behaviour in test
153
        self.failUnless('All changes applied successfully.\n' in log)
1551.7.10 by Aaron Bentley
Remerge doesn't clear unrelated conflicts
154
155
    def test_merge_inner_conflicts(self):
156
        tree_a = self.make_branch_and_tree('a')
157
        tree_a.set_conflicts(ConflictList([TextConflict('patha')]))
1551.7.11 by Aaron Bentley
Add WorkingTree.add_conflicts
158
        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.
159
        self.assertEqual(1, len(tree_a.conflicts()))
1551.8.22 by Aaron Bentley
Improve message when OTHER deletes an in-use tree
160
161
    def test_rmdir_conflict(self):
162
        tree_a = self.make_branch_and_tree('a')
163
        self.build_tree(['a/b/'])
164
        tree_a.add('b', 'b-id')
165
        tree_a.commit('added b')
2255.7.12 by John Arbash Meinel
Some comments on merge code, fix merge tests that
166
        # basis_tree() is only guaranteed to be valid as long as it is actually
167
        # the basis tree. This mutates the tree after grabbing basis, so go to
168
        # the repository.
169
        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
170
        tree_z = tree_a.bzrdir.sprout('z').open_workingtree()
171
        self.build_tree(['a/b/c'])
172
        tree_a.add('b/c')
173
        tree_a.commit('added c')
174
        os.rmdir('z/b')
175
        tree_z.commit('removed b')
176
        merge_inner(tree_z.branch, tree_a, base_tree, this_tree=tree_z)
177
        self.assertEqual([
178
            conflicts.MissingParent('Created directory', 'b', 'b-id'),
179
            conflicts.UnversionedParent('Versioned directory', 'b', 'b-id')],
180
            tree_z.conflicts())
2255.2.216 by Robert Collins
simplify merge_nested tests.
181
        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
182
                    this_tree=tree_a)
183
        self.assertEqual([
184
            conflicts.DeletingParent('Not deleting', 'b', 'b-id'),
185
            conflicts.UnversionedParent('Versioned directory', 'b', 'b-id')],
186
            tree_a.conflicts())
1551.10.2 by Aaron Bentley
Handle merge with dangling inventory entries
187
2100.3.29 by Aaron Bentley
Get merge working initially
188
    def test_nested_merge(self):
2255.2.194 by Robert Collins
[BROKEN] Many updates to stop using experimental formats in tests.
189
        tree = self.make_branch_and_tree('tree',
190
            format='dirstate-with-subtree')
2100.3.29 by Aaron Bentley
Get merge working initially
191
        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.
192
            format='dirstate-with-subtree')
2100.3.29 by Aaron Bentley
Get merge working initially
193
        sub_tree.set_root_id('sub-tree-root')
194
        self.build_tree_contents([('tree/sub-tree/file', 'text1')])
195
        sub_tree.add('file')
196
        sub_tree.commit('foo')
197
        tree.add_reference(sub_tree)
198
        tree.commit('set text to 1')
199
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
2255.2.217 by Martin Pool
docs
200
        # modify the file in the subtree
2100.3.29 by Aaron Bentley
Get merge working initially
201
        self.build_tree_contents([('tree2/sub-tree/file', 'text2')])
2255.2.217 by Martin Pool
docs
202
        # and merge the changes from the diverged subtree into the containing
203
        # tree
2255.2.216 by Robert Collins
simplify merge_nested tests.
204
        tree2.commit('changed file text')
2100.3.29 by Aaron Bentley
Get merge working initially
205
        tree.merge_from_branch(tree2.branch)
206
        self.assertFileEqual('text2', 'tree/sub-tree/file')
207
1551.10.2 by Aaron Bentley
Handle merge with dangling inventory entries
208
    def test_merge_with_missing(self):
209
        tree_a = self.make_branch_and_tree('tree_a')
210
        self.build_tree_contents([('tree_a/file', 'content_1')])
211
        tree_a.add('file')
212
        tree_a.commit('commit base')
2255.7.12 by John Arbash Meinel
Some comments on merge code, fix merge tests that
213
        # basis_tree() is only guaranteed to be valid as long as it is actually
214
        # the basis tree. This mutates the tree after grabbing basis, so go to
215
        # the repository.
216
        base_tree = tree_a.branch.repository.revision_tree(tree_a.last_revision())
1551.10.2 by Aaron Bentley
Handle merge with dangling inventory entries
217
        tree_b = tree_a.bzrdir.sprout('tree_b').open_workingtree()
218
        self.build_tree_contents([('tree_a/file', 'content_2')])
219
        tree_a.commit('commit other')
220
        other_tree = tree_a.basis_tree()
221
        os.unlink('tree_b/file')
222
        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
223
224
    def test_merge_kind_change(self):
225
        tree_a = self.make_branch_and_tree('tree_a')
226
        self.build_tree_contents([('tree_a/file', 'content_1')])
227
        tree_a.add('file', 'file-id')
228
        tree_a.commit('added file')
229
        tree_b = tree_a.bzrdir.sprout('tree_b').open_workingtree()
230
        os.unlink('tree_a/file')
231
        self.build_tree(['tree_a/file/'])
232
        tree_a.commit('changed file to directory')
233
        tree_b.merge_from_branch(tree_a.branch)
234
        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'
235
        tree_b.revert()
1959.4.6 by Aaron Bentley
Ensure merge works across kind changes
236
        self.assertEqual('file', file_kind('tree_b/file'))
237
        self.build_tree_contents([('tree_b/file', 'content_2')])
238
        tree_b.commit('content change')
239
        tree_b.merge_from_branch(tree_a.branch)
240
        self.assertEqual(tree_b.conflicts(),
241
                         [conflicts.ContentsConflict('file',
242
                          file_id='file-id')])
2221.4.16 by Aaron Bentley
Add tests for get_merge_type_registry
243
    
244
    def test_merge_type_registry(self):
245
        merge_type_option = option.Option.OPTIONS['merge-type']
246
        self.assertFalse('merge4' in [x[0] for x in 
247
                        merge_type_option.iter_switches()])
248
        registry = _mod_merge.get_merge_type_registry()
249
        registry.register_lazy('merge4', 'bzrlib.merge', 'Merge4Merger',
250
                               'time-travelling merge')
251
        self.assertTrue('merge4' in [x[0] for x in 
252
                        merge_type_option.iter_switches()])
253
        registry.remove('merge4')
254
        self.assertFalse('merge4' in [x[0] for x in 
255
                        merge_type_option.iter_switches()])
1551.16.2 by Aaron Bentley
Don't crash on merging renamed deleted files (#110279)
256
1551.16.3 by Aaron Bentley
Rename test case
257
    def test_merge_other_moves_we_deleted(self):
1551.16.2 by Aaron Bentley
Don't crash on merging renamed deleted files (#110279)
258
        tree_a = self.make_branch_and_tree('A')
259
        tree_a.lock_write()
260
        self.addCleanup(tree_a.unlock)
261
        self.build_tree(['A/a'])
262
        tree_a.add('a')
263
        tree_a.commit('1', rev_id='rev-1')
264
        tree_a.flush()
265
        tree_a.rename_one('a', 'b')
266
        tree_a.commit('2')
267
        bzrdir_b = tree_a.bzrdir.sprout('B', revision_id='rev-1')
268
        tree_b = bzrdir_b.open_workingtree()
269
        tree_b.lock_write()
270
        self.addCleanup(tree_b.unlock)
271
        os.unlink('B/a')
272
        tree_b.commit('3')
273
        try:
274
            tree_b.merge_from_branch(tree_a.branch)
275
        except AttributeError:
276
            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()
277
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.
278
    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()
279
        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.
280
        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()
281
        tree_a.add(['file_1'])
282
        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.
283
        tree_a.add(['file_2'])
284
        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()
285
        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.
286
        tree_b.rename_one('file_1', 'renamed')
1551.15.72 by Aaron Bentley
remove builtins._merge_helper
287
        merger = _mod_merge.Merger.from_uncommitted(tree_a, tree_b,
288
                                                    progress.DummyProgress())
289
        merger.merge_type = _mod_merge.Merge3Merger
290
        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.
291
        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
292
3146.5.1 by Aaron Bentley
Make merge --uncommitted work with merge-type weave
293
    def test_merge_uncommitted_otherbasis_ancestor_of_thisbasis_weave(self):
294
        tree_a = self.make_branch_and_tree('a')
295
        self.build_tree(['a/file_1', 'a/file_2'])
296
        tree_a.add(['file_1'])
297
        tree_a.commit('commit 1')
298
        tree_a.add(['file_2'])
299
        tree_a.commit('commit 2')
300
        tree_b = tree_a.bzrdir.sprout('b').open_workingtree()
301
        tree_b.rename_one('file_1', 'renamed')
302
        merger = _mod_merge.Merger.from_uncommitted(tree_a, tree_b,
303
                                                    progress.DummyProgress())
304
        merger.merge_type = _mod_merge.WeaveMerger
305
        merger.do_merge()
306
        self.assertEqual(tree_a.get_parent_ids(), [tree_b.last_revision()])
307
3062.2.7 by Aaron Bentley
Prevent reverse cherry-picking with weave
308
    def prepare_cherrypick(self):
3062.2.13 by Aaron Bentley
Update prepare_cherrypick docstring
309
        """Prepare a pair of trees for cherrypicking tests.
310
311
        Both trees have a file, 'file'.
312
        rev1 sets content to 'a'.
313
        rev2b adds 'b'.
314
        rev3b adds 'c'.
315
        A full merge of rev2b and rev3b into this_tree would add both 'b' and
316
        'c'.  A successful cherrypick of rev2b-rev3b into this_tree will add
317
        'c', but not 'b'.
318
        """
3062.2.6 by Aaron Bentley
Get cherrypick-on-weave working
319
        this_tree = self.make_branch_and_tree('this')
320
        self.build_tree_contents([('this/file', "a\n")])
321
        this_tree.add('file')
322
        this_tree.commit('rev1')
323
        other_tree = this_tree.bzrdir.sprout('other').open_workingtree()
324
        self.build_tree_contents([('other/file', "a\nb\n")])
325
        other_tree.commit('rev2b', rev_id='rev2b')
326
        self.build_tree_contents([('other/file', "c\na\nb\n")])
327
        other_tree.commit('rev3b', rev_id='rev3b')
328
        this_tree.lock_write()
329
        self.addCleanup(this_tree.unlock)
3062.2.7 by Aaron Bentley
Prevent reverse cherry-picking with weave
330
        return this_tree, other_tree
331
332
    def test_weave_cherrypick(self):
333
        this_tree, other_tree = self.prepare_cherrypick()
3062.2.6 by Aaron Bentley
Get cherrypick-on-weave working
334
        merger = _mod_merge.Merger.from_revision_ids(progress.DummyProgress(),
335
            this_tree, 'rev3b', 'rev2b', other_tree.branch)
336
        merger.merge_type = _mod_merge.WeaveMerger
337
        merger.do_merge()
338
        self.assertFileEqual('c\na\n', 'this/file')
339
3062.2.7 by Aaron Bentley
Prevent reverse cherry-picking with weave
340
    def test_weave_cannot_reverse_cherrypick(self):
341
        this_tree, other_tree = self.prepare_cherrypick()
342
        merger = _mod_merge.Merger.from_revision_ids(progress.DummyProgress(),
343
            this_tree, 'rev2b', 'rev3b', other_tree.branch)
344
        merger.merge_type = _mod_merge.WeaveMerger
345
        self.assertRaises(errors.CannotReverseCherrypick, merger.do_merge)
346
347
    def test_merge3_can_reverse_cherrypick(self):
348
        this_tree, other_tree = self.prepare_cherrypick()
349
        merger = _mod_merge.Merger.from_revision_ids(progress.DummyProgress(),
350
            this_tree, 'rev2b', 'rev3b', other_tree.branch)
351
        merger.merge_type = _mod_merge.Merge3Merger
352
        merger.do_merge()
353
3062.1.9 by Aaron Bentley
Move PlanMerge into merge and _PlanMergeVersionedFile into versionedfile
354
355
class TestPlanMerge(TestCaseWithMemoryTransport):
356
357
    def setUp(self):
358
        TestCaseWithMemoryTransport.setUp(self)
359
        self.vf = knit.KnitVersionedFile('root', self.get_transport(),
360
                                         create=True)
361
        self.plan_merge_vf = versionedfile._PlanMergeVersionedFile('root',
362
                                                                   [self.vf])
363
364
    def add_version(self, version_id, parents, text):
365
        self.vf.add_lines(version_id, parents, [c+'\n' for c in text])
366
367
    def add_uncommitted_version(self, version_id, parents, text):
368
        self.plan_merge_vf.add_lines(version_id, parents,
369
                                     [c+'\n' for c in text])
370
371
    def setup_plan_merge(self):
372
        self.add_version('A', [], 'abc')
373
        self.add_version('B', ['A'], 'acehg')
374
        self.add_version('C', ['A'], 'fabg')
3062.1.13 by Aaron Bentley
Make _PlanMerge an implementation detail of _PlanMergeVersionedFile
375
        return _PlanMerge('B', 'C', self.plan_merge_vf)
3062.1.9 by Aaron Bentley
Move PlanMerge into merge and _PlanMergeVersionedFile into versionedfile
376
377
    def setup_plan_merge_uncommitted(self):
378
        self.add_version('A', [], 'abc')
379
        self.add_uncommitted_version('B:', ['A'], 'acehg')
380
        self.add_uncommitted_version('C:', ['A'], 'fabg')
3062.1.13 by Aaron Bentley
Make _PlanMerge an implementation detail of _PlanMergeVersionedFile
381
        return _PlanMerge('B:', 'C:', self.plan_merge_vf)
3062.1.9 by Aaron Bentley
Move PlanMerge into merge and _PlanMergeVersionedFile into versionedfile
382
383
    def test_unique_lines(self):
384
        plan = self.setup_plan_merge()
385
        self.assertEqual(plan._unique_lines(
386
            plan._get_matching_blocks('B', 'C')),
387
            ([1, 2, 3], [0, 2]))
388
389
    def test_find_new(self):
390
        plan = self.setup_plan_merge()
391
        self.assertEqual(set([2, 3, 4]), plan._find_new('B'))
392
        self.assertEqual(set([0, 3]), plan._find_new('C'))
393
394
    def test_find_new2(self):
395
        self.add_version('A', [], 'abc')
396
        self.add_version('B', ['A'], 'abcde')
397
        self.add_version('C', ['A'], 'abcefg')
398
        self.add_version('D', ['A', 'B', 'C'], 'abcdegh')
3062.1.13 by Aaron Bentley
Make _PlanMerge an implementation detail of _PlanMergeVersionedFile
399
        my_plan = _PlanMerge('B', 'D', self.plan_merge_vf)
3062.1.9 by Aaron Bentley
Move PlanMerge into merge and _PlanMergeVersionedFile into versionedfile
400
        self.assertEqual(set([5, 6]), my_plan._find_new('D'))
401
        self.assertEqual(set(), my_plan._find_new('A'))
402
403
    def test_find_new_no_ancestors(self):
404
        self.add_version('A', [], 'abc')
405
        self.add_version('B', [], 'xyz')
3062.1.13 by Aaron Bentley
Make _PlanMerge an implementation detail of _PlanMergeVersionedFile
406
        my_plan = _PlanMerge('A', 'B', self.vf)
3062.1.9 by Aaron Bentley
Move PlanMerge into merge and _PlanMergeVersionedFile into versionedfile
407
        self.assertEqual(set([0, 1, 2]), my_plan._find_new('A'))
408
409
    def test_plan_merge(self):
3062.1.13 by Aaron Bentley
Make _PlanMerge an implementation detail of _PlanMergeVersionedFile
410
        self.setup_plan_merge()
411
        plan = self.plan_merge_vf.plan_merge('B', 'C')
3062.1.9 by Aaron Bentley
Move PlanMerge into merge and _PlanMergeVersionedFile into versionedfile
412
        self.assertEqual([
413
                          ('new-b', 'f\n'),
414
                          ('unchanged', 'a\n'),
415
                          ('killed-b', 'c\n'),
416
                          ('new-a', 'e\n'),
417
                          ('new-a', 'h\n'),
418
                          ('killed-a', 'b\n'),
419
                          ('unchanged', 'g\n')],
420
                         list(plan))
421
422
    def test_plan_merge_uncommitted_files(self):
3062.1.13 by Aaron Bentley
Make _PlanMerge an implementation detail of _PlanMergeVersionedFile
423
        self.setup_plan_merge_uncommitted()
424
        plan = self.plan_merge_vf.plan_merge('B:', 'C:')
3062.1.9 by Aaron Bentley
Move PlanMerge into merge and _PlanMergeVersionedFile into versionedfile
425
        self.assertEqual([
426
                          ('new-b', 'f\n'),
427
                          ('unchanged', 'a\n'),
428
                          ('killed-b', 'c\n'),
429
                          ('new-a', 'e\n'),
430
                          ('new-a', 'h\n'),
431
                          ('killed-a', 'b\n'),
432
                          ('unchanged', 'g\n')],
433
                         list(plan))
3062.2.1 by Aaron Bentley
Add support for plan-merge with a base
434
435
    def test_subtract_plans(self):
436
        old_plan = [
437
        ('unchanged', 'a\n'),
438
        ('new-a', 'b\n'),
439
        ('killed-a', 'c\n'),
440
        ('new-b', 'd\n'),
441
        ('new-b', 'e\n'),
442
        ('killed-b', 'f\n'),
443
        ('killed-b', 'g\n'),
444
        ]
445
        new_plan = [
446
        ('unchanged', 'a\n'),
447
        ('new-a', 'b\n'),
448
        ('killed-a', 'c\n'),
449
        ('new-b', 'd\n'),
450
        ('new-b', 'h\n'),
451
        ('killed-b', 'f\n'),
452
        ('killed-b', 'i\n'),
453
        ]
454
        subtracted_plan = [
455
        ('unchanged', 'a\n'),
456
        ('new-a', 'b\n'),
457
        ('killed-a', 'c\n'),
458
        ('new-b', 'h\n'),
459
        ('unchanged', 'f\n'),
460
        ('killed-b', 'i\n'),
461
        ]
462
        self.assertEqual(subtracted_plan,
3062.2.3 by Aaron Bentley
Sync up with bzr.dev API changes
463
            list(_PlanMerge._subtract_plans(old_plan, new_plan)))
3062.2.1 by Aaron Bentley
Add support for plan-merge with a base
464
3144.3.1 by Aaron Bentley
Implement LCA merge, with problematic conflict markers
465
    def setup_merge_with_base(self):
3062.2.1 by Aaron Bentley
Add support for plan-merge with a base
466
        self.add_version('COMMON', [], 'abc')
467
        self.add_version('THIS', ['COMMON'], 'abcd')
468
        self.add_version('BASE', ['COMMON'], 'eabc')
469
        self.add_version('OTHER', ['BASE'], 'eafb')
3144.3.1 by Aaron Bentley
Implement LCA merge, with problematic conflict markers
470
471
    def test_plan_merge_with_base(self):
472
        self.setup_merge_with_base()
3062.2.3 by Aaron Bentley
Sync up with bzr.dev API changes
473
        plan = self.plan_merge_vf.plan_merge('THIS', 'OTHER', 'BASE')
3062.2.1 by Aaron Bentley
Add support for plan-merge with a base
474
        self.assertEqual([('unchanged', 'a\n'),
475
                          ('new-b', 'f\n'),
476
                          ('unchanged', 'b\n'),
477
                          ('killed-b', 'c\n'),
478
                          ('new-a', 'd\n')
479
                         ], list(plan))
3144.3.1 by Aaron Bentley
Implement LCA merge, with problematic conflict markers
480
481
    def test_plan_lca_merge(self):
482
        self.setup_plan_merge()
483
        plan = self.plan_merge_vf.plan_lca_merge('B', 'C')
484
        self.assertEqual([
485
                          ('new-b', 'f\n'),
486
                          ('unchanged', 'a\n'),
487
                          ('killed-b', 'c\n'),
488
                          ('new-a', 'e\n'),
489
                          ('new-a', 'h\n'),
490
                          ('killed-a', 'b\n'),
491
                          ('unchanged', 'g\n')],
492
                         list(plan))
493
494
    def test_plan_lca_merge_uncommitted_files(self):
495
        self.setup_plan_merge_uncommitted()
496
        plan = self.plan_merge_vf.plan_lca_merge('B:', 'C:')
497
        self.assertEqual([
498
                          ('new-b', 'f\n'),
499
                          ('unchanged', 'a\n'),
500
                          ('killed-b', 'c\n'),
501
                          ('new-a', 'e\n'),
502
                          ('new-a', 'h\n'),
503
                          ('killed-a', 'b\n'),
504
                          ('unchanged', 'g\n')],
505
                         list(plan))
506
507
    def test_plan_lca_merge_with_base(self):
508
        self.setup_merge_with_base()
509
        plan = self.plan_merge_vf.plan_lca_merge('THIS', 'OTHER', 'BASE')
510
        self.assertEqual([('unchanged', 'a\n'),
511
                          ('new-b', 'f\n'),
512
                          ('unchanged', 'b\n'),
513
                          ('killed-b', 'c\n'),
514
                          ('new-a', 'd\n')
515
                         ], list(plan))
516
517
    def test_plan_lca_merge_with_criss_cross(self):
518
        self.add_version('ROOT', [], 'abc')
519
        # each side makes a change
520
        self.add_version('REV1', ['ROOT'], 'abcd')
521
        self.add_version('REV2', ['ROOT'], 'abce')
522
        # both sides merge, discarding others' changes
523
        self.add_version('LCA1', ['REV1', 'REV2'], 'abcd')
524
        self.add_version('LCA2', ['REV1', 'REV2'], 'abce')
525
        plan = self.plan_merge_vf.plan_lca_merge('LCA1', 'LCA2')
526
        self.assertEqual([('unchanged', 'a\n'),
527
                          ('unchanged', 'b\n'),
528
                          ('unchanged', 'c\n'),
3144.3.3 by Aaron Bentley
Update test for new conflicted types
529
                          ('conflicted-a', 'd\n'),
530
                          ('conflicted-b', 'e\n'),
3144.3.1 by Aaron Bentley
Implement LCA merge, with problematic conflict markers
531
                         ], list(plan))