24
23
from bzrlib.branch import Branch
25
from bzrlib.osutils import abspath
24
from bzrlib.osutils import pathjoin
26
25
from bzrlib.tests.blackbox import ExternalBase
27
26
from bzrlib.uncommit import uncommit
27
from bzrlib.workingtree import WorkingTree
28
from bzrlib import urlutils
30
31
class TestPull(ExternalBase):
32
def example_branch(test):
34
file('hello', 'wt').write('foo')
35
test.runbzr('add hello')
36
test.runbzr('commit -m setup hello')
37
file('goodbye', 'wt').write('baz')
38
test.runbzr('add goodbye')
39
test.runbzr('commit -m setup goodbye')
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')])
39
tree.commit(message='setup')
41
tree.commit(message='setup')
41
44
def test_pull(self):
42
45
"""Pull changes from one branch to another."""
46
a_tree = self.example_branch('a')
47
self.runbzr('pull', retcode=3)
48
self.runbzr('missing', retcode=3)
49
self.runbzr('missing .')
50
self.runbzr('missing')
48
self.run_bzr('pull', retcode=3)
49
self.run_bzr('missing', retcode=3)
50
self.run_bzr('missing .')
51
self.run_bzr('missing')
51
52
# this will work on windows because we check for the same branch
52
53
# in pull - if it fails, it is a regression
54
self.runbzr('pull /', retcode=3)
55
self.run_bzr('pull /', retcode=3)
55
56
if sys.platform not in ('win32', 'cygwin'):
59
self.runbzr('branch a b')
60
b_tree = a_tree.bzrdir.sprout('b').open_workingtree()
63
self.runbzr('add subdir')
64
self.runbzr('commit -m blah --unchanged')
67
b = Branch.open('../b')
68
self.assertEquals(a.revision_history(), b.revision_history()[:-1])
69
self.runbzr('pull ../b')
70
self.assertEquals(a.revision_history(), b.revision_history())
71
self.runbzr('commit -m blah2 --unchanged')
73
self.runbzr('commit -m blah3 --unchanged')
65
b_tree.commit(message='blah', allow_pointless=True)
70
self.assertEqual(a.revision_history(), b.revision_history()[:-1])
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)
75
self.runbzr('pull ../a', retcode=3)
79
self.run_bzr('pull ../a', retcode=3)
77
self.runbzr('branch b overwriteme')
81
b_tree.bzrdir.sprout('overwriteme')
78
82
os.chdir('overwriteme')
79
self.runbzr('pull --overwrite ../a')
83
self.run_bzr('pull --overwrite ../a')
80
84
overwritten = Branch.open('.')
81
85
self.assertEqual(overwritten.revision_history(),
82
86
a.revision_history())
84
self.runbzr('merge ../b')
85
self.runbzr('commit -m blah4 --unchanged')
87
a_tree.merge_from_branch(b_tree.branch)
88
a_tree.commit(message="blah4", allow_pointless=True)
86
89
os.chdir('../b/subdir')
87
self.runbzr('pull ../../a')
88
self.assertEquals(a.revision_history()[-1], b.revision_history()[-1])
89
self.runbzr('commit -m blah5 --unchanged')
90
self.runbzr('commit -m blah6 --unchanged')
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)
92
self.runbzr('pull ../a')
96
self.run_bzr('pull ../a')
94
self.runbzr('commit -m blah7 --unchanged')
95
self.runbzr('merge ../b')
96
self.runbzr('commit -m blah8 --unchanged')
97
self.runbzr('pull ../b')
98
self.runbzr('pull ../b')
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')
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'])
100
115
def test_pull_revision(self):
101
116
"""Pull some changes from one branch to another."""
105
self.example_branch()
106
file('hello2', 'wt').write('foo')
107
self.runbzr('add hello2')
108
self.runbzr('commit -m setup hello2')
109
file('goodbye2', 'wt').write('baz')
110
self.runbzr('add goodbye2')
111
self.runbzr('commit -m setup goodbye2')
114
self.runbzr('branch -r 1 a b')
117
a_tree = self.example_branch('a')
118
self.build_tree_contents([
120
('a/goodbye2', 'baz')])
122
a_tree.commit(message="setup")
123
a_tree.add('goodbye2')
124
a_tree.commit(message="setup")
126
b_tree = a_tree.bzrdir.sprout('b',
127
revision_id=a_tree.branch.get_rev_id(1)).open_workingtree()
116
self.runbzr('pull -r 2')
129
self.run_bzr('pull -r 2')
117
130
a = Branch.open('../a')
118
131
b = Branch.open('.')
119
self.assertEquals(a.revno(),4)
120
self.assertEquals(b.revno(),2)
121
self.runbzr('pull -r 3')
122
self.assertEquals(b.revno(),3)
123
self.runbzr('pull -r 4')
124
self.assertEquals(a.revision_history(), b.revision_history())
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())
127
140
def test_overwrite_uptodate(self):
128
141
# Make sure pull --overwrite overwrites
129
142
# even if the target branch has merged
130
143
# everything already.
133
def get_rh(expected_len):
134
rh = self.capture('revision-history')
135
# Make sure we don't have trailing empty revisions
136
rh = rh.strip().split('\n')
137
self.assertEqual(len(rh), expected_len)
143
open('foo', 'wb').write('original\n')
145
bzr('commit', '-m', 'initial commit')
148
bzr('branch', 'a', 'b')
151
open('foo', 'wb').write('changed\n')
152
bzr('commit', '-m', 'later change')
154
open('foo', 'wb').write('another\n')
155
bzr('commit', '-m', 'a third change')
157
rev_history_a = get_rh(3)
161
bzr('commit', '-m', 'merge')
163
rev_history_b = get_rh(2)
165
bzr('pull', '--overwrite', '../a')
166
rev_history_b = get_rh(3)
144
a_tree = self.make_branch_and_tree('a')
145
self.build_tree_contents([('a/foo', 'original\n')])
147
a_tree.commit(message='initial commit')
149
b_tree = a_tree.bzrdir.sprout('b').open_workingtree()
151
self.build_tree_contents([('a/foo', 'changed\n')])
152
a_tree.commit(message='later change')
154
self.build_tree_contents([('a/foo', 'a third change')])
155
a_tree.commit(message='a third change')
157
rev_history_a = a_tree.branch.revision_history()
158
self.assertEqual(len(rev_history_a), 3)
160
b_tree.merge_from_branch(a_tree.branch)
161
b_tree.commit(message='merge')
163
self.assertEqual(len(b_tree.branch.revision_history()), 2)
166
self.run_bzr('pull --overwrite ../a')
167
rev_history_b = b_tree.branch.revision_history()
168
self.assertEqual(len(rev_history_b), 3)
168
170
self.assertEqual(rev_history_b, rev_history_a)
170
172
def test_overwrite_children(self):
171
173
# Make sure pull --overwrite sets the revision-history
172
174
# to be identical to the pull source, even if we have convergence
175
def get_rh(expected_len):
176
rh = self.capture('revision-history')
177
# Make sure we don't have trailing empty revisions
178
rh = rh.strip().split('\n')
179
self.assertEqual(len(rh), expected_len)
185
open('foo', 'wb').write('original\n')
187
bzr('commit', '-m', 'initial commit')
190
bzr('branch', 'a', 'b')
193
open('foo', 'wb').write('changed\n')
194
bzr('commit', '-m', 'later change')
196
open('foo', 'wb').write('another\n')
197
bzr('commit', '-m', 'a third change')
199
rev_history_a = get_rh(3)
203
bzr('commit', '-m', 'merge')
205
rev_history_b = get_rh(2)
208
open('foo', 'wb').write('a fourth change\n')
209
bzr('commit', '-m', 'a fourth change')
211
rev_history_a = get_rh(4)
175
a_tree = self.make_branch_and_tree('a')
176
self.build_tree_contents([('a/foo', 'original\n')])
178
a_tree.commit(message='initial commit')
180
b_tree = a_tree.bzrdir.sprout('b').open_workingtree()
182
self.build_tree_contents([('a/foo', 'changed\n')])
183
a_tree.commit(message='later change')
185
self.build_tree_contents([('a/foo', 'a third change')])
186
a_tree.commit(message='a third change')
188
self.assertEqual(len(a_tree.branch.revision_history()), 3)
190
b_tree.merge_from_branch(a_tree.branch)
191
b_tree.commit(message='merge')
193
self.assertEqual(len(b_tree.branch.revision_history()), 2)
195
self.build_tree_contents([('a/foo', 'a fourth change\n')])
196
a_tree.commit(message='a fourth change')
198
rev_history_a = a_tree.branch.revision_history()
199
self.assertEqual(len(rev_history_a), 4)
213
201
# With convergence, we could just pull over the
214
202
# new change, but with --overwrite, we want to switch our history
216
bzr('pull', '--overwrite', '../a')
217
rev_history_b = get_rh(4)
204
self.run_bzr('pull --overwrite ../a')
205
rev_history_b = b_tree.branch.revision_history()
206
self.assertEqual(len(rev_history_b), 4)
219
208
self.assertEqual(rev_history_b, rev_history_a)
239
228
self.assertEqual(None, branch_b.get_parent())
240
229
# test pull for failure without parent set
241
230
os.chdir('branch_b')
242
out = self.runbzr('pull', retcode=3)
243
self.assertEquals(out,
231
out = self.run_bzr('pull', retcode=3)
232
self.assertEqual(out,
244
233
('','bzr: ERROR: No pull location known or specified.\n'))
245
234
# test implicit --remember when no parent set, this pull conflicts
246
235
self.build_tree(['d'])
248
237
tree_b.commit('commit d')
249
out = self.runbzr('pull ../branch_a', retcode=3)
250
self.assertEquals(out,
251
('','bzr: ERROR: These branches have diverged. Try merge.\n'))
252
self.assertEquals(abspath(branch_b.get_parent()), abspath(parent))
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)
253
243
# test implicit --remember after resolving previous failure
254
244
uncommit(branch=branch_b, tree=tree_b)
255
245
transport.delete('branch_b/d')
257
self.assertEquals(abspath(branch_b.get_parent()), abspath(parent))
247
self.assertEqual(branch_b.get_parent(), parent)
258
248
# test explicit --remember
259
self.runbzr('pull ../branch_c --remember')
260
self.assertEquals(abspath(branch_b.get_parent()),
261
abspath(branch_c.bzrdir.root_transport.base))
249
self.run_bzr('pull ../branch_c --remember')
250
self.assertEqual(branch_b.get_parent(),
251
branch_c.bzrdir.root_transport.base)
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')
261
tree_a.commit('message')
263
tree_b = tree_a.bzrdir.sprout('branch_b').open_workingtree()
265
# Make a change to 'a' that 'b' can pull
266
f = open('branch_a/a', 'wb')
269
tree_a.commit('message')
271
# Create the bundle for 'b' to pull
273
self.run_bzr('bundle ../branch_b -o ../bundle')
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')
282
self.assertEqualDiff(tree_a.branch.revision_history(),
283
tree_b.branch.revision_history())
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())
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')
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'])
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')