~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

[merge] jam-integration

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 Canonical Ltd
2
 
#
 
1
# Copyright (C) 2005 by Canonical Ltd
 
2
# -*- coding: utf-8 -*-
 
3
 
3
4
# This program is free software; you can redistribute it and/or modify
4
5
# it under the terms of the GNU General Public License as published by
5
6
# the Free Software Foundation; either version 2 of the License, or
6
7
# (at your option) any later version.
7
 
#
 
8
 
8
9
# This program is distributed in the hope that it will be useful,
9
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
12
# GNU General Public License for more details.
12
 
#
 
13
 
13
14
# You should have received a copy of the GNU General Public License
14
15
# along with this program; if not, write to the Free Software
15
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
 
17
18
 
18
 
"""Black-box tests for bzr pull."""
 
19
"""Black-box tests for bzr pull.
 
20
"""
19
21
 
20
22
import os
21
23
import sys
22
24
 
23
25
from bzrlib.branch import Branch
24
 
from bzrlib.osutils import pathjoin
25
26
from bzrlib.tests.blackbox import ExternalBase
26
 
from bzrlib.uncommit import uncommit
27
 
from bzrlib.workingtree import WorkingTree
28
 
from bzrlib import urlutils
29
 
 
30
27
 
31
28
class TestPull(ExternalBase):
32
29
 
33
 
    def example_branch(self, path='.'):
34
 
        tree = self.make_branch_and_tree(path)
35
 
        self.build_tree_contents([
36
 
            (pathjoin(path, 'hello'),   'foo'),
37
 
            (pathjoin(path, 'goodbye'), 'baz')])
38
 
        tree.add('hello')
39
 
        tree.commit(message='setup')
40
 
        tree.add('goodbye')
41
 
        tree.commit(message='setup')
42
 
        return tree
 
30
    def example_branch(test):
 
31
        test.runbzr('init')
 
32
        file('hello', 'wt').write('foo')
 
33
        test.runbzr('add hello')
 
34
        test.runbzr('commit -m setup hello')
 
35
        file('goodbye', 'wt').write('baz')
 
36
        test.runbzr('add goodbye')
 
37
        test.runbzr('commit -m setup goodbye')
43
38
 
44
39
    def test_pull(self):
45
40
        """Pull changes from one branch to another."""
46
 
        a_tree = self.example_branch('a')
 
41
        os.mkdir('a')
47
42
        os.chdir('a')
48
 
        self.run_bzr('pull', retcode=3)
49
 
        self.run_bzr('missing', retcode=3)
50
 
        self.run_bzr('missing .')
51
 
        self.run_bzr('missing')
52
 
        # this will work on windows because we check for the same branch
53
 
        # in pull - if it fails, it is a regression
54
 
        self.run_bzr('pull')
55
 
        self.run_bzr('pull /', retcode=3)
56
 
        if sys.platform not in ('win32', 'cygwin'):
57
 
            self.run_bzr('pull')
 
43
 
 
44
        self.example_branch()
 
45
        self.runbzr('pull', retcode=3)
 
46
        self.runbzr('missing', retcode=3)
 
47
        self.runbzr('missing .')
 
48
        self.runbzr('missing')
 
49
        if sys.platform not in ('win32', 'cygwin'):
 
50
            # This is equivalent to doing "bzr pull ."
 
51
            # Which means that bzr creates 2 branches grabbing
 
52
            # the same location, and tries to pull.
 
53
            # However, 2 branches mean 2 locks on the same file
 
54
            # which ultimately implies a deadlock.
 
55
            # (non windows platforms allow multiple locks on the
 
56
            # same file by the same calling process)
 
57
            self.runbzr('pull')
 
58
        self.runbzr('pull /', retcode=3)
 
59
        if sys.platform not in ('win32', 'cygwin'):
 
60
            self.runbzr('pull')
58
61
 
59
62
        os.chdir('..')
60
 
        b_tree = a_tree.bzrdir.sprout('b').open_workingtree()
 
63
        self.runbzr('branch a b')
61
64
        os.chdir('b')
62
 
        self.run_bzr('pull')
 
65
        self.runbzr('pull')
63
66
        os.mkdir('subdir')
64
 
        b_tree.add('subdir')
65
 
        b_tree.commit(message='blah', allow_pointless=True)
66
 
 
67
 
        os.chdir('..')
68
 
        a = Branch.open('a')
69
 
        b = Branch.open('b')
70
 
        self.assertEqual(a.revision_history(), b.revision_history()[:-1])
71
 
 
72
 
        os.chdir('a')
73
 
        self.run_bzr('pull ../b')
74
 
        self.assertEqual(a.revision_history(), b.revision_history())
75
 
        a_tree.commit(message='blah2', allow_pointless=True)
76
 
        b_tree.commit(message='blah3', allow_pointless=True)
 
67
        self.runbzr('add subdir')
 
68
        self.runbzr('commit -m blah --unchanged')
 
69
        os.chdir('../a')
 
70
        a = Branch.open('.')
 
71
        b = Branch.open('../b')
 
72
        self.assertEquals(a.revision_history(), b.revision_history()[:-1])
 
73
        self.runbzr('pull ../b')
 
74
        self.assertEquals(a.revision_history(), b.revision_history())
 
75
        self.runbzr('commit -m blah2 --unchanged')
 
76
        os.chdir('../b')
 
77
        self.runbzr('commit -m blah3 --unchanged')
77
78
        # no overwrite
78
 
        os.chdir('../b')
79
 
        self.run_bzr('pull ../a', retcode=3)
 
79
        self.runbzr('pull ../a', retcode=3)
80
80
        os.chdir('..')
81
 
        b_tree.bzrdir.sprout('overwriteme')
 
81
        self.runbzr('branch b overwriteme')
82
82
        os.chdir('overwriteme')
83
 
        self.run_bzr('pull --overwrite ../a')
 
83
        self.runbzr('pull --overwrite ../a')
84
84
        overwritten = Branch.open('.')
85
85
        self.assertEqual(overwritten.revision_history(),
86
86
                         a.revision_history())
87
 
        a_tree.merge_from_branch(b_tree.branch)
88
 
        a_tree.commit(message="blah4", allow_pointless=True)
 
87
        os.chdir('../a')
 
88
        self.runbzr('merge ../b')
 
89
        self.runbzr('commit -m blah4 --unchanged')
89
90
        os.chdir('../b/subdir')
90
 
        self.run_bzr('pull ../../a')
91
 
        self.assertEqual(a.revision_history()[-1], b.revision_history()[-1])
92
 
        sub_tree = WorkingTree.open_containing('.')[0]
93
 
        sub_tree.commit(message="blah5", allow_pointless=True)
94
 
        sub_tree.commit(message="blah6", allow_pointless=True)
 
91
        self.runbzr('pull ../../a')
 
92
        self.assertEquals(a.revision_history()[-1], b.revision_history()[-1])
 
93
        self.runbzr('commit -m blah5 --unchanged')
 
94
        self.runbzr('commit -m blah6 --unchanged')
95
95
        os.chdir('..')
96
 
        self.run_bzr('pull ../a')
 
96
        self.runbzr('pull ../a')
97
97
        os.chdir('../a')
98
 
        a_tree.commit(message="blah7", allow_pointless=True)
99
 
        a_tree.merge_from_branch(b_tree.branch)
100
 
        a_tree.commit(message="blah8", allow_pointless=True)
101
 
        self.run_bzr('pull ../b')
102
 
        self.run_bzr('pull ../b')
103
 
 
104
 
    def test_pull_dash_d(self):
105
 
        self.example_branch('a')
106
 
        self.make_branch_and_tree('b')
107
 
        self.make_branch_and_tree('c')
108
 
        # pull into that branch
109
 
        self.run_bzr('pull -d b a')
110
 
        # pull into a branch specified by a url
111
 
        c_url = urlutils.local_path_to_url('c')
112
 
        self.assertStartsWith(c_url, 'file://')
113
 
        self.run_bzr(['pull', '-d', c_url, 'a'])
114
 
 
115
 
    def test_pull_revision(self):
116
 
        """Pull some changes from one branch to another."""
117
 
        a_tree = self.example_branch('a')
118
 
        self.build_tree_contents([
119
 
            ('a/hello2',   'foo'),
120
 
            ('a/goodbye2', 'baz')])
121
 
        a_tree.add('hello2')
122
 
        a_tree.commit(message="setup")
123
 
        a_tree.add('goodbye2')
124
 
        a_tree.commit(message="setup")
125
 
 
126
 
        b_tree = a_tree.bzrdir.sprout('b',
127
 
                   revision_id=a_tree.branch.get_rev_id(1)).open_workingtree()
128
 
        os.chdir('b')
129
 
        self.run_bzr('pull -r 2')
130
 
        a = Branch.open('../a')
131
 
        b = Branch.open('.')
132
 
        self.assertEqual(a.revno(),4)
133
 
        self.assertEqual(b.revno(),2)
134
 
        self.run_bzr('pull -r 3')
135
 
        self.assertEqual(b.revno(),3)
136
 
        self.run_bzr('pull -r 4')
137
 
        self.assertEqual(a.revision_history(), b.revision_history())
138
 
 
 
98
        self.runbzr('commit -m blah7 --unchanged')
 
99
        self.runbzr('merge ../b')
 
100
        self.runbzr('commit -m blah8 --unchanged')
 
101
        self.runbzr('pull ../b')
 
102
        self.runbzr('pull ../b')
139
103
 
140
104
    def test_overwrite_uptodate(self):
141
105
        # Make sure pull --overwrite overwrites
142
106
        # even if the target branch has merged
143
107
        # everything already.
144
 
        a_tree = self.make_branch_and_tree('a')
145
 
        self.build_tree_contents([('a/foo', 'original\n')])
146
 
        a_tree.add('foo')
147
 
        a_tree.commit(message='initial commit')
148
 
 
149
 
        b_tree = a_tree.bzrdir.sprout('b').open_workingtree()
150
 
 
151
 
        self.build_tree_contents([('a/foo', 'changed\n')])
152
 
        a_tree.commit(message='later change')
153
 
 
154
 
        self.build_tree_contents([('a/foo', 'a third change')])
155
 
        a_tree.commit(message='a third change')
156
 
 
157
 
        rev_history_a = a_tree.branch.revision_history()
158
 
        self.assertEqual(len(rev_history_a), 3)
159
 
 
160
 
        b_tree.merge_from_branch(a_tree.branch)
161
 
        b_tree.commit(message='merge')
162
 
 
163
 
        self.assertEqual(len(b_tree.branch.revision_history()), 2)
164
 
 
165
 
        os.chdir('b')
166
 
        self.run_bzr('pull --overwrite ../a')
167
 
        rev_history_b = b_tree.branch.revision_history()
168
 
        self.assertEqual(len(rev_history_b), 3)
 
108
        bzr = self.run_bzr
 
109
 
 
110
        def get_rh(expected_len):
 
111
            rh = self.capture('revision-history')
 
112
            # Make sure we don't have trailing empty revisions
 
113
            rh = rh.strip().split('\n')
 
114
            self.assertEqual(len(rh), expected_len)
 
115
            return rh
 
116
 
 
117
        os.mkdir('a')
 
118
        os.chdir('a')
 
119
        bzr('init')
 
120
        open('foo', 'wb').write('original\n')
 
121
        bzr('add', 'foo')
 
122
        bzr('commit', '-m', 'initial commit')
 
123
 
 
124
        os.chdir('..')
 
125
        bzr('branch', 'a', 'b')
 
126
 
 
127
        os.chdir('a')
 
128
        open('foo', 'wb').write('changed\n')
 
129
        bzr('commit', '-m', 'later change')
 
130
 
 
131
        open('foo', 'wb').write('another\n')
 
132
        bzr('commit', '-m', 'a third change')
 
133
 
 
134
        rev_history_a = get_rh(3)
 
135
 
 
136
        os.chdir('../b')
 
137
        bzr('merge', '../a')
 
138
        bzr('commit', '-m', 'merge')
 
139
 
 
140
        rev_history_b = get_rh(2)
 
141
 
 
142
        bzr('pull', '--overwrite', '../a')
 
143
        rev_history_b = get_rh(3)
169
144
 
170
145
        self.assertEqual(rev_history_b, rev_history_a)
171
146
 
172
147
    def test_overwrite_children(self):
173
148
        # Make sure pull --overwrite sets the revision-history
174
149
        # to be identical to the pull source, even if we have convergence
175
 
        a_tree = self.make_branch_and_tree('a')
176
 
        self.build_tree_contents([('a/foo', 'original\n')])
177
 
        a_tree.add('foo')
178
 
        a_tree.commit(message='initial commit')
179
 
 
180
 
        b_tree = a_tree.bzrdir.sprout('b').open_workingtree()
181
 
 
182
 
        self.build_tree_contents([('a/foo', 'changed\n')])
183
 
        a_tree.commit(message='later change')
184
 
 
185
 
        self.build_tree_contents([('a/foo', 'a third change')])
186
 
        a_tree.commit(message='a third change')
187
 
 
188
 
        self.assertEqual(len(a_tree.branch.revision_history()), 3)
189
 
 
190
 
        b_tree.merge_from_branch(a_tree.branch)
191
 
        b_tree.commit(message='merge')
192
 
 
193
 
        self.assertEqual(len(b_tree.branch.revision_history()), 2)
194
 
 
195
 
        self.build_tree_contents([('a/foo', 'a fourth change\n')])
196
 
        a_tree.commit(message='a fourth change')
197
 
 
198
 
        rev_history_a = a_tree.branch.revision_history()
199
 
        self.assertEqual(len(rev_history_a), 4)
 
150
        bzr = self.run_bzr
 
151
 
 
152
        def get_rh(expected_len):
 
153
            rh = self.capture('revision-history')
 
154
            # Make sure we don't have trailing empty revisions
 
155
            rh = rh.strip().split('\n')
 
156
            self.assertEqual(len(rh), expected_len)
 
157
            return rh
 
158
 
 
159
        os.mkdir('a')
 
160
        os.chdir('a')
 
161
        bzr('init')
 
162
        open('foo', 'wb').write('original\n')
 
163
        bzr('add', 'foo')
 
164
        bzr('commit', '-m', 'initial commit')
 
165
 
 
166
        os.chdir('..')
 
167
        bzr('branch', 'a', 'b')
 
168
 
 
169
        os.chdir('a')
 
170
        open('foo', 'wb').write('changed\n')
 
171
        bzr('commit', '-m', 'later change')
 
172
 
 
173
        open('foo', 'wb').write('another\n')
 
174
        bzr('commit', '-m', 'a third change')
 
175
 
 
176
        rev_history_a = get_rh(3)
 
177
 
 
178
        os.chdir('../b')
 
179
        bzr('merge', '../a')
 
180
        bzr('commit', '-m', 'merge')
 
181
 
 
182
        rev_history_b = get_rh(2)
 
183
 
 
184
        os.chdir('../a')
 
185
        open('foo', 'wb').write('a fourth change\n')
 
186
        bzr('commit', '-m', 'a fourth change')
 
187
 
 
188
        rev_history_a = get_rh(4)
200
189
 
201
190
        # With convergence, we could just pull over the
202
191
        # new change, but with --overwrite, we want to switch our history
203
 
        os.chdir('b')
204
 
        self.run_bzr('pull --overwrite ../a')
205
 
        rev_history_b = b_tree.branch.revision_history()
206
 
        self.assertEqual(len(rev_history_b), 4)
 
192
        os.chdir('../b')
 
193
        bzr('pull', '--overwrite', '../a')
 
194
        rev_history_b = get_rh(4)
207
195
 
208
196
        self.assertEqual(rev_history_b, rev_history_a)
209
197
 
210
 
    def test_pull_remember(self):
211
 
        """Pull changes from one branch to another and test parent location."""
212
 
        transport = self.get_transport()
213
 
        tree_a = self.make_branch_and_tree('branch_a')
214
 
        branch_a = tree_a.branch
215
 
        self.build_tree(['branch_a/a'])
216
 
        tree_a.add('a')
217
 
        tree_a.commit('commit a')
218
 
        tree_b = branch_a.bzrdir.sprout('branch_b').open_workingtree()
219
 
        branch_b = tree_b.branch
220
 
        tree_c = branch_a.bzrdir.sprout('branch_c').open_workingtree()
221
 
        branch_c = tree_c.branch
222
 
        self.build_tree(['branch_a/b'])
223
 
        tree_a.add('b')
224
 
        tree_a.commit('commit b')
225
 
        # reset parent
226
 
        parent = branch_b.get_parent()
227
 
        branch_b.set_parent(None)
228
 
        self.assertEqual(None, branch_b.get_parent())
229
 
        # test pull for failure without parent set
230
 
        os.chdir('branch_b')
231
 
        out = self.run_bzr('pull', retcode=3)
232
 
        self.assertEqual(out,
233
 
                ('','bzr: ERROR: No pull location known or specified.\n'))
234
 
        # test implicit --remember when no parent set, this pull conflicts
235
 
        self.build_tree(['d'])
236
 
        tree_b.add('d')
237
 
        tree_b.commit('commit d')
238
 
        out = self.run_bzr('pull ../branch_a', retcode=3)
239
 
        self.assertEqual(out,
240
 
                ('','bzr: ERROR: These branches have diverged.'
241
 
                    ' Use the merge command to reconcile them.\n'))
242
 
        self.assertEqual(branch_b.get_parent(), parent)
243
 
        # test implicit --remember after resolving previous failure
244
 
        uncommit(branch=branch_b, tree=tree_b)
245
 
        transport.delete('branch_b/d')
246
 
        self.run_bzr('pull')
247
 
        self.assertEqual(branch_b.get_parent(), parent)
248
 
        # test explicit --remember
249
 
        self.run_bzr('pull ../branch_c --remember')
250
 
        self.assertEqual(branch_b.get_parent(),
251
 
                          branch_c.bzrdir.root_transport.base)
252
 
 
253
 
    def test_pull_bundle(self):
254
 
        from bzrlib.testament import Testament
255
 
        # Build up 2 trees and prepare for a pull
256
 
        tree_a = self.make_branch_and_tree('branch_a')
257
 
        f = open('branch_a/a', 'wb')
258
 
        f.write('hello')
259
 
        f.close()
260
 
        tree_a.add('a')
261
 
        tree_a.commit('message')
262
 
 
263
 
        tree_b = tree_a.bzrdir.sprout('branch_b').open_workingtree()
264
 
 
265
 
        # Make a change to 'a' that 'b' can pull
266
 
        f = open('branch_a/a', 'wb')
267
 
        f.write('hey there')
268
 
        f.close()
269
 
        tree_a.commit('message')
270
 
 
271
 
        # Create the bundle for 'b' to pull
272
 
        os.chdir('branch_a')
273
 
        self.run_bzr('bundle ../branch_b -o ../bundle')
274
 
 
275
 
        os.chdir('../branch_b')
276
 
        out, err = self.run_bzr('pull ../bundle')
277
 
        self.assertEqual(out,
278
 
                         'Now on revision 2.\n')
279
 
        self.assertEqual(err,
280
 
                ' M  a\nAll changes applied successfully.\n')
281
 
 
282
 
        self.assertEqualDiff(tree_a.branch.revision_history(),
283
 
                             tree_b.branch.revision_history())
284
 
 
285
 
        testament_a = Testament.from_revision(tree_a.branch.repository,
286
 
                                              tree_a.get_parent_ids()[0])
287
 
        testament_b = Testament.from_revision(tree_b.branch.repository,
288
 
                                              tree_b.get_parent_ids()[0])
289
 
        self.assertEqualDiff(testament_a.as_text(),
290
 
                             testament_b.as_text())
291
 
 
292
 
        # it is legal to attempt to pull an already-merged bundle
293
 
        out, err = self.run_bzr('pull ../bundle')
294
 
        self.assertEqual(err, '')
295
 
        self.assertEqual(out, 'No revisions to pull.\n')
296
 
 
297
 
    def test_pull_verbose_no_files(self):
298
 
        """Pull --verbose should not list modified files"""
299
 
        tree_a = self.make_branch_and_tree('tree_a')
300
 
        self.build_tree(['tree_a/foo'])
301
 
        tree_a.add('foo')
302
 
        tree_a.commit('bar')
303
 
        tree_b = self.make_branch_and_tree('tree_b')
304
 
        out = self.run_bzr('pull --verbose -d tree_b tree_a')[0]
305
 
        self.assertContainsRe(out, 'bar')
306
 
        self.assertNotContainsRe(out, 'added:')
307
 
        self.assertNotContainsRe(out, 'foo')
 
198