~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_merge.py

  • Committer: John Arbash Meinel
  • Date: 2007-02-08 16:28:05 UTC
  • mto: This revision was merged to the branch mainline in revision 2278.
  • Revision ID: john@arbash-meinel.com-20070208162805-dcqiqrwjh9a5lo7n
``GPGStrategy.sign()`` will now raise ``BzrBadParameterUnicode`` if
you pass a Unicode string rather than an 8-bit string. It doesn't 
make sense to sign a Unicode string, and it turns out that some 
versions of python will write out the raw Unicode bytes rather than
encoding automatically. So fail and make callers do the right thing.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005, 2006 Canonical Ltd
 
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
 
 
17
import os
 
18
from StringIO import StringIO
 
19
 
 
20
from bzrlib import (
 
21
    conflicts,
 
22
    merge as _mod_merge,
 
23
    option,
 
24
    )
 
25
from bzrlib.branch import Branch
 
26
from bzrlib.builtins import merge
 
27
from bzrlib.conflicts import ConflictList, TextConflict
 
28
from bzrlib.errors import UnrelatedBranches, NoCommits, BzrCommandError
 
29
from bzrlib.merge import transform_tree, merge_inner
 
30
from bzrlib.osutils import pathjoin, file_kind
 
31
from bzrlib.revision import common_ancestor
 
32
from bzrlib.tests import TestCaseWithTransport
 
33
from bzrlib.trace import (enable_test_log, disable_test_log)
 
34
from bzrlib.workingtree import WorkingTree
 
35
 
 
36
 
 
37
class TestMerge(TestCaseWithTransport):
 
38
    """Test appending more than one revision"""
 
39
 
 
40
    def test_pending(self):
 
41
        wt = self.make_branch_and_tree('.')
 
42
        rev_a = wt.commit("lala!")
 
43
        self.assertEqual([rev_a], wt.get_parent_ids())
 
44
        merge([u'.', -1], [None, None])
 
45
        self.assertEqual([rev_a], wt.get_parent_ids())
 
46
 
 
47
    def test_undo(self):
 
48
        wt = self.make_branch_and_tree('.')
 
49
        wt.commit("lala!")
 
50
        wt.commit("haha!")
 
51
        wt.commit("blabla!")
 
52
        merge([u'.', 2], [u'.', 1])
 
53
 
 
54
    def test_nocommits(self):
 
55
        self.test_pending()
 
56
        wt2 = self.make_branch_and_tree('branch2')
 
57
        self.assertRaises(NoCommits, merge, ['branch2', -1], 
 
58
                          [None, None])
 
59
        return wt2
 
60
 
 
61
    def test_unrelated(self):
 
62
        wt2 = self.test_nocommits()
 
63
        wt2.commit("blah")
 
64
        self.assertRaises(UnrelatedBranches, merge, ['branch2', -1], 
 
65
                          [None, None])
 
66
        return wt2
 
67
 
 
68
    def test_merge_one_file(self):
 
69
        """Do a partial merge of a tree which should not affect tree parents."""
 
70
        wt1 = self.make_branch_and_tree('branch1')
 
71
        tip = wt1.commit('empty commit')
 
72
        wt2 = self.make_branch_and_tree('branch2')
 
73
        wt2.pull(wt1.branch)
 
74
        file('branch1/foo', 'wb').write('foo')
 
75
        file('branch1/bar', 'wb').write('bar')
 
76
        wt1.add('foo')
 
77
        wt1.add('bar')
 
78
        wt1.commit('add foobar')
 
79
        os.chdir('branch2')
 
80
        self.run_bzr('merge', '../branch1/baz', retcode=3)
 
81
        self.run_bzr('merge', '../branch1/foo')
 
82
        self.failUnlessExists('foo')
 
83
        self.failIfExists('bar')
 
84
        wt2 = WorkingTree.open('.') # opens branch2
 
85
        self.assertEqual([tip], wt2.get_parent_ids())
 
86
        
 
87
    def test_pending_with_null(self):
 
88
        """When base is forced to revno 0, parent_ids are set"""
 
89
        wt2 = self.test_unrelated()
 
90
        wt1 = WorkingTree.open('.')
 
91
        br1 = wt1.branch
 
92
        br1.fetch(wt2.branch)
 
93
        # merge all of branch 2 into branch 1 even though they 
 
94
        # are not related.
 
95
        self.assertRaises(BzrCommandError, merge, ['branch2', -1],
 
96
                          ['branch2', 0], reprocess=True, show_base=True)
 
97
        merge(['branch2', -1], ['branch2', 0], reprocess=True)
 
98
        self.assertEqual([br1.last_revision(), wt2.branch.last_revision()],
 
99
            wt1.get_parent_ids())
 
100
        return (wt1, wt2.branch)
 
101
 
 
102
    def test_two_roots(self):
 
103
        """Merge base is sane when two unrelated branches are merged"""
 
104
        wt1, br2 = self.test_pending_with_null()
 
105
        wt1.commit("blah")
 
106
        last = wt1.branch.last_revision()
 
107
        self.assertEqual(common_ancestor(last, last, wt1.branch.repository), last)
 
108
 
 
109
    def test_create_rename(self):
 
110
        """Rename an inventory entry while creating the file"""
 
111
        tree =self.make_branch_and_tree('.')
 
112
        file('name1', 'wb').write('Hello')
 
113
        tree.add('name1')
 
114
        tree.commit(message="hello")
 
115
        tree.rename_one('name1', 'name2')
 
116
        os.unlink('name2')
 
117
        transform_tree(tree, tree.branch.basis_tree())
 
118
 
 
119
    def test_layered_rename(self):
 
120
        """Rename both child and parent at same time"""
 
121
        tree =self.make_branch_and_tree('.')
 
122
        os.mkdir('dirname1')
 
123
        tree.add('dirname1')
 
124
        filename = pathjoin('dirname1', 'name1')
 
125
        file(filename, 'wb').write('Hello')
 
126
        tree.add(filename)
 
127
        tree.commit(message="hello")
 
128
        filename2 = pathjoin('dirname1', 'name2')
 
129
        tree.rename_one(filename, filename2)
 
130
        tree.rename_one('dirname1', 'dirname2')
 
131
        transform_tree(tree, tree.branch.basis_tree())
 
132
 
 
133
    def test_ignore_zero_merge_inner(self):
 
134
        # Test that merge_inner's ignore zero parameter is effective
 
135
        tree_a =self.make_branch_and_tree('a')
 
136
        tree_a.commit(message="hello")
 
137
        dir_b = tree_a.bzrdir.sprout('b')
 
138
        tree_b = dir_b.open_workingtree()
 
139
        tree_a.commit(message="hello again")
 
140
        log = StringIO()
 
141
        merge_inner(tree_b.branch, tree_a, tree_b.basis_tree(), 
 
142
                    this_tree=tree_b, ignore_zero=True)
 
143
        log = self._get_log(keep_log_file=True)
 
144
        self.failUnless('All changes applied successfully.\n' not in log)
 
145
        tree_b.revert([])
 
146
        merge_inner(tree_b.branch, tree_a, tree_b.basis_tree(), 
 
147
                    this_tree=tree_b, ignore_zero=False)
 
148
        log = self._get_log(keep_log_file=True)
 
149
        self.failUnless('All changes applied successfully.\n' in log)
 
150
 
 
151
    def test_merge_inner_conflicts(self):
 
152
        tree_a = self.make_branch_and_tree('a')
 
153
        tree_a.set_conflicts(ConflictList([TextConflict('patha')]))
 
154
        merge_inner(tree_a.branch, tree_a, tree_a, this_tree=tree_a)
 
155
        self.assertEqual(1, len(tree_a.conflicts()))
 
156
 
 
157
    def test_rmdir_conflict(self):
 
158
        tree_a = self.make_branch_and_tree('a')
 
159
        self.build_tree(['a/b/'])
 
160
        tree_a.add('b', 'b-id')
 
161
        tree_a.commit('added b')
 
162
        base_tree = tree_a.basis_tree()
 
163
        tree_z = tree_a.bzrdir.sprout('z').open_workingtree()
 
164
        self.build_tree(['a/b/c'])
 
165
        tree_a.add('b/c')
 
166
        tree_a.commit('added c')
 
167
        os.rmdir('z/b')
 
168
        tree_z.commit('removed b')
 
169
        merge_inner(tree_z.branch, tree_a, base_tree, this_tree=tree_z)
 
170
        self.assertEqual([
 
171
            conflicts.MissingParent('Created directory', 'b', 'b-id'),
 
172
            conflicts.UnversionedParent('Versioned directory', 'b', 'b-id')],
 
173
            tree_z.conflicts())
 
174
        merge_inner(tree_a.branch, tree_z.basis_tree(), base_tree, 
 
175
                    this_tree=tree_a)
 
176
        self.assertEqual([
 
177
            conflicts.DeletingParent('Not deleting', 'b', 'b-id'),
 
178
            conflicts.UnversionedParent('Versioned directory', 'b', 'b-id')],
 
179
            tree_a.conflicts())
 
180
 
 
181
    def test_merge_with_missing(self):
 
182
        tree_a = self.make_branch_and_tree('tree_a')
 
183
        self.build_tree_contents([('tree_a/file', 'content_1')])
 
184
        tree_a.add('file')
 
185
        tree_a.commit('commit base')
 
186
        base_tree = tree_a.basis_tree()
 
187
        tree_b = tree_a.bzrdir.sprout('tree_b').open_workingtree()
 
188
        self.build_tree_contents([('tree_a/file', 'content_2')])
 
189
        tree_a.commit('commit other')
 
190
        other_tree = tree_a.basis_tree()
 
191
        os.unlink('tree_b/file')
 
192
        merge_inner(tree_b.branch, other_tree, base_tree, this_tree=tree_b)
 
193
 
 
194
    def test_merge_kind_change(self):
 
195
        tree_a = self.make_branch_and_tree('tree_a')
 
196
        self.build_tree_contents([('tree_a/file', 'content_1')])
 
197
        tree_a.add('file', 'file-id')
 
198
        tree_a.commit('added file')
 
199
        tree_b = tree_a.bzrdir.sprout('tree_b').open_workingtree()
 
200
        os.unlink('tree_a/file')
 
201
        self.build_tree(['tree_a/file/'])
 
202
        tree_a.commit('changed file to directory')
 
203
        tree_b.merge_from_branch(tree_a.branch)
 
204
        self.assertEqual('directory', file_kind('tree_b/file'))
 
205
        tree_b.revert([])
 
206
        self.assertEqual('file', file_kind('tree_b/file'))
 
207
        self.build_tree_contents([('tree_b/file', 'content_2')])
 
208
        tree_b.commit('content change')
 
209
        tree_b.merge_from_branch(tree_a.branch)
 
210
        self.assertEqual(tree_b.conflicts(),
 
211
                         [conflicts.ContentsConflict('file',
 
212
                          file_id='file-id')])
 
213
    
 
214
    def test_merge_type_registry(self):
 
215
        merge_type_option = option.Option.OPTIONS['merge-type']
 
216
        self.assertFalse('merge4' in [x[0] for x in 
 
217
                        merge_type_option.iter_switches()])
 
218
        registry = _mod_merge.get_merge_type_registry()
 
219
        registry.register_lazy('merge4', 'bzrlib.merge', 'Merge4Merger',
 
220
                               'time-travelling merge')
 
221
        self.assertTrue('merge4' in [x[0] for x in 
 
222
                        merge_type_option.iter_switches()])
 
223
        registry.remove('merge4')
 
224
        self.assertFalse('merge4' in [x[0] for x in 
 
225
                        merge_type_option.iter_switches()])