~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/blackbox/test_merge.py

Factor out another win32 special case and add platform independent tests for it.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 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
# Author: Aaron Bentley <aaron.bentley@utoronto.ca>
 
18
 
 
19
"""Black-box tests for bzr merge.
 
20
"""
 
21
 
 
22
import os
 
23
 
 
24
from bzrlib.branch import Branch
 
25
from bzrlib.bzrdir import BzrDir
 
26
from bzrlib.conflicts import ConflictList
 
27
from bzrlib.delta import compare_trees
 
28
from bzrlib.osutils import abspath
 
29
from bzrlib.tests.blackbox import ExternalBase
 
30
import bzrlib.urlutils as urlutils
 
31
from bzrlib.workingtree import WorkingTree
 
32
 
 
33
 
 
34
class TestMerge(ExternalBase):
 
35
 
 
36
    def example_branch(test):
 
37
        test.runbzr('init')
 
38
        file('hello', 'wt').write('foo')
 
39
        test.runbzr('add hello')
 
40
        test.runbzr('commit -m setup hello')
 
41
        file('goodbye', 'wt').write('baz')
 
42
        test.runbzr('add goodbye')
 
43
        test.runbzr('commit -m setup goodbye')
 
44
 
 
45
    def test_merge_reprocess(self):
 
46
        d = BzrDir.create_standalone_workingtree('.')
 
47
        d.commit('h')
 
48
        self.run_bzr('merge', '.', '--reprocess', '--merge-type', 'weave')
 
49
 
 
50
    def test_merge(self):
 
51
        from bzrlib.branch import Branch
 
52
        
 
53
        os.mkdir('a')
 
54
        os.chdir('a')
 
55
        self.example_branch()
 
56
        os.chdir('..')
 
57
        self.runbzr('branch a b')
 
58
        os.chdir('b')
 
59
        file('goodbye', 'wt').write('quux')
 
60
        self.runbzr(['commit',  '-m',  "more u's are always good"])
 
61
 
 
62
        os.chdir('../a')
 
63
        file('hello', 'wt').write('quuux')
 
64
        # We can't merge when there are in-tree changes
 
65
        self.runbzr('merge ../b', retcode=3)
 
66
        self.runbzr(['commit', '-m', "Like an epidemic of u's"])
 
67
        self.runbzr('merge ../b -r last:1..last:1 --merge-type blooof',
 
68
                    retcode=3)
 
69
        self.runbzr('merge ../b -r last:1..last:1 --merge-type merge3')
 
70
        self.runbzr('revert --no-backup')
 
71
        self.runbzr('merge ../b -r last:1..last:1 --merge-type weave')
 
72
        self.runbzr('revert --no-backup')
 
73
        self.runbzr('merge ../b -r last:1..last:1 --reprocess')
 
74
        self.runbzr('revert --no-backup')
 
75
        self.runbzr('merge ../b -r last:1')
 
76
        self.check_file_contents('goodbye', 'quux')
 
77
        # Merging a branch pulls its revision into the tree
 
78
        a = WorkingTree.open('.')
 
79
        b = Branch.open('../b')
 
80
        a.branch.repository.get_revision_xml(b.last_revision())
 
81
        self.log('pending merges: %s', a.pending_merges())
 
82
        self.assertEquals(a.pending_merges(),
 
83
                          [b.last_revision()])
 
84
        self.runbzr('commit -m merged')
 
85
        self.runbzr('merge ../b -r last:1')
 
86
        self.assertEqual(a.pending_merges(), [])
 
87
 
 
88
    def test_merge_with_missing_file(self):
 
89
        """Merge handles missing file conflicts"""
 
90
        os.mkdir('a')
 
91
        os.chdir('a')
 
92
        os.mkdir('sub')
 
93
        print >> file('sub/a.txt', 'wb'), "hello"
 
94
        print >> file('b.txt', 'wb'), "hello"
 
95
        print >> file('sub/c.txt', 'wb'), "hello"
 
96
        self.runbzr('init')
 
97
        self.runbzr('add')
 
98
        self.runbzr(('commit', '-m', 'added a'))
 
99
        self.runbzr('branch . ../b')
 
100
        print >> file('sub/a.txt', 'ab'), "there"
 
101
        print >> file('b.txt', 'ab'), "there"
 
102
        print >> file('sub/c.txt', 'ab'), "there"
 
103
        self.runbzr(('commit', '-m', 'Added there'))
 
104
        os.unlink('sub/a.txt')
 
105
        os.unlink('sub/c.txt')
 
106
        os.rmdir('sub')
 
107
        os.unlink('b.txt')
 
108
        self.runbzr(('commit', '-m', 'Removed a.txt'))
 
109
        os.chdir('../b')
 
110
        print >> file('sub/a.txt', 'ab'), "something"
 
111
        print >> file('b.txt', 'ab'), "something"
 
112
        print >> file('sub/c.txt', 'ab'), "something"
 
113
        self.runbzr(('commit', '-m', 'Modified a.txt'))
 
114
        self.runbzr('merge ../a/', retcode=1)
 
115
        self.assert_(os.path.exists('sub/a.txt.THIS'))
 
116
        self.assert_(os.path.exists('sub/a.txt.BASE'))
 
117
        os.chdir('../a')
 
118
        self.runbzr('merge ../b/', retcode=1)
 
119
        self.assert_(os.path.exists('sub/a.txt.OTHER'))
 
120
        self.assert_(os.path.exists('sub/a.txt.BASE'))
 
121
 
 
122
    def test_merge_remember(self):
 
123
        """Merge changes from one branch to another and test parent location."""
 
124
        tree_a = self.make_branch_and_tree('branch_a')
 
125
        branch_a = tree_a.branch
 
126
        self.build_tree(['branch_a/a'])
 
127
        tree_a.add('a')
 
128
        tree_a.commit('commit a')
 
129
        branch_b = branch_a.bzrdir.sprout('branch_b').open_branch()
 
130
        tree_b = branch_b.bzrdir.open_workingtree()
 
131
        branch_c = branch_a.bzrdir.sprout('branch_c').open_branch()
 
132
        tree_c = branch_c.bzrdir.open_workingtree()
 
133
        self.build_tree(['branch_a/b'])
 
134
        tree_a.add('b')
 
135
        tree_a.commit('commit b')
 
136
        self.build_tree(['branch_c/c'])
 
137
        tree_c.add('c')
 
138
        tree_c.commit('commit c')
 
139
        # reset parent
 
140
        parent = branch_b.get_parent()
 
141
        branch_b.set_parent(None)
 
142
        self.assertEqual(None, branch_b.get_parent())
 
143
        # test merge for failure without parent set
 
144
        os.chdir('branch_b')
 
145
        out = self.runbzr('merge', retcode=3)
 
146
        self.assertEquals(out,
 
147
                ('','bzr: ERROR: No location specified or remembered\n'))
 
148
        # test implicit --remember when no parent set, this merge conflicts
 
149
        self.build_tree(['d'])
 
150
        tree_b.add('d')
 
151
        out = self.runbzr('merge ../branch_a', retcode=3)
 
152
        self.assertEquals(out,
 
153
                ('','bzr: ERROR: Working tree has uncommitted changes.\n'))
 
154
        self.assertEquals(abspath(branch_b.get_parent()), abspath(parent))
 
155
        # test implicit --remember after resolving conflict
 
156
        tree_b.commit('commit d')
 
157
        out, err = self.runbzr('merge')
 
158
        
 
159
        base = urlutils.local_path_from_url(branch_a.base)
 
160
        self.assertEquals(out, 'Merging from remembered location %s\n' % (base,))
 
161
        self.assertEquals(err, 'All changes applied successfully.\n')
 
162
        self.assertEquals(abspath(branch_b.get_parent()), abspath(parent))
 
163
        # re-open tree as external runbzr modified it
 
164
        tree_b = branch_b.bzrdir.open_workingtree()
 
165
        tree_b.commit('merge branch_a')
 
166
        # test explicit --remember
 
167
        out, err = self.runbzr('merge ../branch_c --remember')
 
168
        self.assertEquals(out, '')
 
169
        self.assertEquals(err, 'All changes applied successfully.\n')
 
170
        self.assertEquals(abspath(branch_b.get_parent()),
 
171
                          abspath(branch_c.bzrdir.root_transport.base))
 
172
        # re-open tree as external runbzr modified it
 
173
        tree_b = branch_b.bzrdir.open_workingtree()
 
174
        tree_b.commit('merge branch_c')
 
175
 
 
176
    def test_merge_bundle(self):
 
177
        from bzrlib.testament import Testament
 
178
        tree_a = self.make_branch_and_tree('branch_a')
 
179
        f = file('branch_a/a', 'wb')
 
180
        f.write('hello')
 
181
        f.close()
 
182
        tree_a.add('a')
 
183
        tree_a.commit('message')
 
184
 
 
185
        tree_b = tree_a.bzrdir.sprout('branch_b').open_workingtree()
 
186
        f = file('branch_a/a', 'wb')
 
187
        f.write('hey there')
 
188
        f.close()
 
189
        tree_a.commit('message')
 
190
 
 
191
        f = file('branch_b/a', 'wb')
 
192
        f.write('goodbye')
 
193
        f.close()
 
194
        tree_b.commit('message')
 
195
        os.chdir('branch_b')
 
196
        file('../bundle', 'wb').write(self.runbzr('bundle ../branch_a')[0])
 
197
        os.chdir('../branch_a')
 
198
        self.runbzr('merge ../bundle', retcode=1)
 
199
        testament_a = Testament.from_revision(tree_a.branch.repository, 
 
200
                                              tree_b.last_revision())
 
201
        testament_b = Testament.from_revision(tree_b.branch.repository,
 
202
                                              tree_b.last_revision())
 
203
        self.assertEqualDiff(testament_a.as_text(),
 
204
                         testament_b.as_text())
 
205
        tree_a.set_conflicts(ConflictList())
 
206
        tree_a.commit('message')
 
207
        # it is legal to attempt to merge an already-merged bundle
 
208
        output = self.runbzr('merge ../bundle')[1]
 
209
        # but it does nothing
 
210
        self.assertFalse(compare_trees(tree_a.basis_tree(), 
 
211
                                       tree_a).has_changed())
 
212
        self.assertEqual('Nothing to do.\n', output)