~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_merge.py

  • Committer: Robert Collins
  • Date: 2007-07-04 08:08:13 UTC
  • mfrom: (2572 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2587.
  • Revision ID: robertc@robertcollins.net-20070704080813-wzebx0r88fvwj5rq
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 by Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
17
17
import os
18
18
from StringIO import StringIO
19
19
 
20
 
from bzrlib import conflicts
 
20
from bzrlib import (
 
21
    conflicts,
 
22
    merge as _mod_merge,
 
23
    option,
 
24
    )
21
25
from bzrlib.branch import Branch
22
26
from bzrlib.builtins import merge
23
27
from bzrlib.conflicts import ConflictList, TextConflict
24
28
from bzrlib.errors import UnrelatedBranches, NoCommits, BzrCommandError
25
29
from bzrlib.merge import transform_tree, merge_inner
26
 
from bzrlib.osutils import pathjoin
 
30
from bzrlib.osutils import pathjoin, file_kind
27
31
from bzrlib.revision import common_ancestor
28
32
from bzrlib.tests import TestCaseWithTransport
29
33
from bzrlib.trace import (enable_test_log, disable_test_log)
73
77
        wt1.add('bar')
74
78
        wt1.commit('add foobar')
75
79
        os.chdir('branch2')
76
 
        self.run_bzr('merge', '../branch1/baz', retcode=3)
77
 
        self.run_bzr('merge', '../branch1/foo')
 
80
        self.run_bzr('merge ../branch1/baz', retcode=3)
 
81
        self.run_bzr('merge ../branch1/foo')
78
82
        self.failUnlessExists('foo')
79
83
        self.failIfExists('bar')
80
84
        wt2 = WorkingTree.open('.') # opens branch2
155
159
        self.build_tree(['a/b/'])
156
160
        tree_a.add('b', 'b-id')
157
161
        tree_a.commit('added b')
158
 
        base_tree = tree_a.basis_tree()
 
162
        # basis_tree() is only guaranteed to be valid as long as it is actually
 
163
        # the basis tree. This mutates the tree after grabbing basis, so go to
 
164
        # the repository.
 
165
        base_tree = tree_a.branch.repository.revision_tree(tree_a.last_revision())
159
166
        tree_z = tree_a.bzrdir.sprout('z').open_workingtree()
160
167
        self.build_tree(['a/b/c'])
161
168
        tree_a.add('b/c')
167
174
            conflicts.MissingParent('Created directory', 'b', 'b-id'),
168
175
            conflicts.UnversionedParent('Versioned directory', 'b', 'b-id')],
169
176
            tree_z.conflicts())
170
 
        merge_inner(tree_a.branch, tree_z.basis_tree(), base_tree, 
 
177
        merge_inner(tree_a.branch, tree_z.basis_tree(), base_tree,
171
178
                    this_tree=tree_a)
172
179
        self.assertEqual([
173
180
            conflicts.DeletingParent('Not deleting', 'b', 'b-id'),
174
181
            conflicts.UnversionedParent('Versioned directory', 'b', 'b-id')],
175
182
            tree_a.conflicts())
 
183
 
 
184
    def test_nested_merge(self):
 
185
        tree = self.make_branch_and_tree('tree',
 
186
            format='dirstate-with-subtree')
 
187
        sub_tree = self.make_branch_and_tree('tree/sub-tree',
 
188
            format='dirstate-with-subtree')
 
189
        sub_tree.set_root_id('sub-tree-root')
 
190
        self.build_tree_contents([('tree/sub-tree/file', 'text1')])
 
191
        sub_tree.add('file')
 
192
        sub_tree.commit('foo')
 
193
        tree.add_reference(sub_tree)
 
194
        tree.commit('set text to 1')
 
195
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
 
196
        # modify the file in the subtree
 
197
        self.build_tree_contents([('tree2/sub-tree/file', 'text2')])
 
198
        # and merge the changes from the diverged subtree into the containing
 
199
        # tree
 
200
        tree2.commit('changed file text')
 
201
        tree.merge_from_branch(tree2.branch)
 
202
        self.assertFileEqual('text2', 'tree/sub-tree/file')
 
203
 
 
204
    def test_merge_with_missing(self):
 
205
        tree_a = self.make_branch_and_tree('tree_a')
 
206
        self.build_tree_contents([('tree_a/file', 'content_1')])
 
207
        tree_a.add('file')
 
208
        tree_a.commit('commit base')
 
209
        # basis_tree() is only guaranteed to be valid as long as it is actually
 
210
        # the basis tree. This mutates the tree after grabbing basis, so go to
 
211
        # the repository.
 
212
        base_tree = tree_a.branch.repository.revision_tree(tree_a.last_revision())
 
213
        tree_b = tree_a.bzrdir.sprout('tree_b').open_workingtree()
 
214
        self.build_tree_contents([('tree_a/file', 'content_2')])
 
215
        tree_a.commit('commit other')
 
216
        other_tree = tree_a.basis_tree()
 
217
        os.unlink('tree_b/file')
 
218
        merge_inner(tree_b.branch, other_tree, base_tree, this_tree=tree_b)
 
219
 
 
220
    def test_merge_kind_change(self):
 
221
        tree_a = self.make_branch_and_tree('tree_a')
 
222
        self.build_tree_contents([('tree_a/file', 'content_1')])
 
223
        tree_a.add('file', 'file-id')
 
224
        tree_a.commit('added file')
 
225
        tree_b = tree_a.bzrdir.sprout('tree_b').open_workingtree()
 
226
        os.unlink('tree_a/file')
 
227
        self.build_tree(['tree_a/file/'])
 
228
        tree_a.commit('changed file to directory')
 
229
        tree_b.merge_from_branch(tree_a.branch)
 
230
        self.assertEqual('directory', file_kind('tree_b/file'))
 
231
        tree_b.revert([])
 
232
        self.assertEqual('file', file_kind('tree_b/file'))
 
233
        self.build_tree_contents([('tree_b/file', 'content_2')])
 
234
        tree_b.commit('content change')
 
235
        tree_b.merge_from_branch(tree_a.branch)
 
236
        self.assertEqual(tree_b.conflicts(),
 
237
                         [conflicts.ContentsConflict('file',
 
238
                          file_id='file-id')])
 
239
    
 
240
    def test_merge_type_registry(self):
 
241
        merge_type_option = option.Option.OPTIONS['merge-type']
 
242
        self.assertFalse('merge4' in [x[0] for x in 
 
243
                        merge_type_option.iter_switches()])
 
244
        registry = _mod_merge.get_merge_type_registry()
 
245
        registry.register_lazy('merge4', 'bzrlib.merge', 'Merge4Merger',
 
246
                               'time-travelling merge')
 
247
        self.assertTrue('merge4' in [x[0] for x in 
 
248
                        merge_type_option.iter_switches()])
 
249
        registry.remove('merge4')
 
250
        self.assertFalse('merge4' in [x[0] for x in 
 
251
                        merge_type_option.iter_switches()])
 
252
 
 
253
    def test_merge_other_moves_we_deleted(self):
 
254
        tree_a = self.make_branch_and_tree('A')
 
255
        tree_a.lock_write()
 
256
        self.addCleanup(tree_a.unlock)
 
257
        self.build_tree(['A/a'])
 
258
        tree_a.add('a')
 
259
        tree_a.commit('1', rev_id='rev-1')
 
260
        tree_a.flush()
 
261
        tree_a.rename_one('a', 'b')
 
262
        tree_a.commit('2')
 
263
        bzrdir_b = tree_a.bzrdir.sprout('B', revision_id='rev-1')
 
264
        tree_b = bzrdir_b.open_workingtree()
 
265
        tree_b.lock_write()
 
266
        self.addCleanup(tree_b.unlock)
 
267
        os.unlink('B/a')
 
268
        tree_b.commit('3')
 
269
        try:
 
270
            tree_b.merge_from_branch(tree_a.branch)
 
271
        except AttributeError:
 
272
            self.fail('tried to join a path when name was None')