1
# Copyright (C) 2005, 2006 Canonical Ltd
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.
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.
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
18
"""Black-box tests for bzr pull."""
23
from bzrlib.branch import Branch
24
from bzrlib.directory_service import directories
25
from bzrlib.osutils import pathjoin
26
from bzrlib.tests.blackbox import ExternalBase
27
from bzrlib.uncommit import uncommit
28
from bzrlib.workingtree import WorkingTree
29
from bzrlib import urlutils
32
class TestPull(ExternalBase):
34
def example_branch(self, path='.'):
35
tree = self.make_branch_and_tree(path)
36
self.build_tree_contents([
37
(pathjoin(path, 'hello'), 'foo'),
38
(pathjoin(path, 'goodbye'), 'baz')])
40
tree.commit(message='setup')
42
tree.commit(message='setup')
46
"""Pull changes from one branch to another."""
47
a_tree = self.example_branch('a')
49
self.run_bzr('pull', retcode=3)
50
self.run_bzr('missing', retcode=3)
51
self.run_bzr('missing .')
52
self.run_bzr('missing')
53
# this will work on windows because we check for the same branch
54
# in pull - if it fails, it is a regression
56
self.run_bzr('pull /', retcode=3)
57
if sys.platform not in ('win32', 'cygwin'):
61
b_tree = a_tree.bzrdir.sprout('b').open_workingtree()
66
b_tree.commit(message='blah', allow_pointless=True)
71
self.assertEqual(a.revision_history(), b.revision_history()[:-1])
74
self.run_bzr('pull ../b')
75
self.assertEqual(a.revision_history(), b.revision_history())
76
a_tree.commit(message='blah2', allow_pointless=True)
77
b_tree.commit(message='blah3', allow_pointless=True)
80
self.run_bzr('pull ../a', retcode=3)
82
b_tree.bzrdir.sprout('overwriteme')
83
os.chdir('overwriteme')
84
self.run_bzr('pull --overwrite ../a')
85
overwritten = Branch.open('.')
86
self.assertEqual(overwritten.revision_history(),
88
a_tree.merge_from_branch(b_tree.branch)
89
a_tree.commit(message="blah4", allow_pointless=True)
90
os.chdir('../b/subdir')
91
self.run_bzr('pull ../../a')
92
self.assertEqual(a.revision_history()[-1], b.revision_history()[-1])
93
sub_tree = WorkingTree.open_containing('.')[0]
94
sub_tree.commit(message="blah5", allow_pointless=True)
95
sub_tree.commit(message="blah6", allow_pointless=True)
97
self.run_bzr('pull ../a')
99
a_tree.commit(message="blah7", allow_pointless=True)
100
a_tree.merge_from_branch(b_tree.branch)
101
a_tree.commit(message="blah8", allow_pointless=True)
102
self.run_bzr('pull ../b')
103
self.run_bzr('pull ../b')
105
def test_pull_dash_d(self):
106
self.example_branch('a')
107
self.make_branch_and_tree('b')
108
self.make_branch_and_tree('c')
109
# pull into that branch
110
self.run_bzr('pull -d b a')
111
# pull into a branch specified by a url
112
c_url = urlutils.local_path_to_url('c')
113
self.assertStartsWith(c_url, 'file://')
114
self.run_bzr(['pull', '-d', c_url, 'a'])
116
def test_pull_revision(self):
117
"""Pull some changes from one branch to another."""
118
a_tree = self.example_branch('a')
119
self.build_tree_contents([
121
('a/goodbye2', 'baz')])
123
a_tree.commit(message="setup")
124
a_tree.add('goodbye2')
125
a_tree.commit(message="setup")
127
b_tree = a_tree.bzrdir.sprout('b',
128
revision_id=a_tree.branch.get_rev_id(1)).open_workingtree()
130
self.run_bzr('pull -r 2')
131
a = Branch.open('../a')
133
self.assertEqual(a.revno(),4)
134
self.assertEqual(b.revno(),2)
135
self.run_bzr('pull -r 3')
136
self.assertEqual(b.revno(),3)
137
self.run_bzr('pull -r 4')
138
self.assertEqual(a.revision_history(), b.revision_history())
141
def test_overwrite_uptodate(self):
142
# Make sure pull --overwrite overwrites
143
# even if the target branch has merged
144
# everything already.
145
a_tree = self.make_branch_and_tree('a')
146
self.build_tree_contents([('a/foo', 'original\n')])
148
a_tree.commit(message='initial commit')
150
b_tree = a_tree.bzrdir.sprout('b').open_workingtree()
152
self.build_tree_contents([('a/foo', 'changed\n')])
153
a_tree.commit(message='later change')
155
self.build_tree_contents([('a/foo', 'a third change')])
156
a_tree.commit(message='a third change')
158
rev_history_a = a_tree.branch.revision_history()
159
self.assertEqual(len(rev_history_a), 3)
161
b_tree.merge_from_branch(a_tree.branch)
162
b_tree.commit(message='merge')
164
self.assertEqual(len(b_tree.branch.revision_history()), 2)
167
self.run_bzr('pull --overwrite ../a')
168
rev_history_b = b_tree.branch.revision_history()
169
self.assertEqual(len(rev_history_b), 3)
171
self.assertEqual(rev_history_b, rev_history_a)
173
def test_overwrite_children(self):
174
# Make sure pull --overwrite sets the revision-history
175
# to be identical to the pull source, even if we have convergence
176
a_tree = self.make_branch_and_tree('a')
177
self.build_tree_contents([('a/foo', 'original\n')])
179
a_tree.commit(message='initial commit')
181
b_tree = a_tree.bzrdir.sprout('b').open_workingtree()
183
self.build_tree_contents([('a/foo', 'changed\n')])
184
a_tree.commit(message='later change')
186
self.build_tree_contents([('a/foo', 'a third change')])
187
a_tree.commit(message='a third change')
189
self.assertEqual(len(a_tree.branch.revision_history()), 3)
191
b_tree.merge_from_branch(a_tree.branch)
192
b_tree.commit(message='merge')
194
self.assertEqual(len(b_tree.branch.revision_history()), 2)
196
self.build_tree_contents([('a/foo', 'a fourth change\n')])
197
a_tree.commit(message='a fourth change')
199
rev_history_a = a_tree.branch.revision_history()
200
self.assertEqual(len(rev_history_a), 4)
202
# With convergence, we could just pull over the
203
# new change, but with --overwrite, we want to switch our history
205
self.run_bzr('pull --overwrite ../a')
206
rev_history_b = b_tree.branch.revision_history()
207
self.assertEqual(len(rev_history_b), 4)
209
self.assertEqual(rev_history_b, rev_history_a)
211
def test_pull_remember(self):
212
"""Pull changes from one branch to another and test parent location."""
213
transport = self.get_transport()
214
tree_a = self.make_branch_and_tree('branch_a')
215
branch_a = tree_a.branch
216
self.build_tree(['branch_a/a'])
218
tree_a.commit('commit a')
219
tree_b = branch_a.bzrdir.sprout('branch_b').open_workingtree()
220
branch_b = tree_b.branch
221
tree_c = branch_a.bzrdir.sprout('branch_c').open_workingtree()
222
branch_c = tree_c.branch
223
self.build_tree(['branch_a/b'])
225
tree_a.commit('commit b')
227
parent = branch_b.get_parent()
228
branch_b.set_parent(None)
229
self.assertEqual(None, branch_b.get_parent())
230
# test pull for failure without parent set
232
out = self.run_bzr('pull', retcode=3)
233
self.assertEqual(out,
234
('','bzr: ERROR: No pull location known or specified.\n'))
235
# test implicit --remember when no parent set, this pull conflicts
236
self.build_tree(['d'])
238
tree_b.commit('commit d')
239
out = self.run_bzr('pull ../branch_a', retcode=3)
240
self.assertEqual(out,
241
('','bzr: ERROR: These branches have diverged.'
242
' Use the merge command to reconcile them.\n'))
243
self.assertEqual(branch_b.get_parent(), parent)
244
# test implicit --remember after resolving previous failure
245
uncommit(branch=branch_b, tree=tree_b)
246
transport.delete('branch_b/d')
248
self.assertEqual(branch_b.get_parent(), parent)
249
# test explicit --remember
250
self.run_bzr('pull ../branch_c --remember')
251
self.assertEqual(branch_b.get_parent(),
252
branch_c.bzrdir.root_transport.base)
254
def test_pull_bundle(self):
255
from bzrlib.testament import Testament
256
# Build up 2 trees and prepare for a pull
257
tree_a = self.make_branch_and_tree('branch_a')
258
f = open('branch_a/a', 'wb')
262
tree_a.commit('message')
264
tree_b = tree_a.bzrdir.sprout('branch_b').open_workingtree()
266
# Make a change to 'a' that 'b' can pull
267
f = open('branch_a/a', 'wb')
270
tree_a.commit('message')
272
# Create the bundle for 'b' to pull
274
self.run_bzr('bundle ../branch_b -o ../bundle')
276
os.chdir('../branch_b')
277
out, err = self.run_bzr('pull ../bundle')
278
self.assertEqual(out,
279
'Now on revision 2.\n')
280
self.assertEqual(err,
281
' M a\nAll changes applied successfully.\n')
283
self.assertEqualDiff(tree_a.branch.revision_history(),
284
tree_b.branch.revision_history())
286
testament_a = Testament.from_revision(tree_a.branch.repository,
287
tree_a.get_parent_ids()[0])
288
testament_b = Testament.from_revision(tree_b.branch.repository,
289
tree_b.get_parent_ids()[0])
290
self.assertEqualDiff(testament_a.as_text(),
291
testament_b.as_text())
293
# it is legal to attempt to pull an already-merged bundle
294
out, err = self.run_bzr('pull ../bundle')
295
self.assertEqual(err, '')
296
self.assertEqual(out, 'No revisions to pull.\n')
298
def test_pull_verbose_no_files(self):
299
"""Pull --verbose should not list modified files"""
300
tree_a = self.make_branch_and_tree('tree_a')
301
self.build_tree(['tree_a/foo'])
304
tree_b = self.make_branch_and_tree('tree_b')
305
out = self.run_bzr('pull --verbose -d tree_b tree_a')[0]
306
self.assertContainsRe(out, 'bar')
307
self.assertNotContainsRe(out, 'added:')
308
self.assertNotContainsRe(out, 'foo')
310
def test_pull_quiet(self):
311
"""Check that bzr pull --quiet does not print anything"""
312
tree_a = self.make_branch_and_tree('tree_a')
313
self.build_tree(['tree_a/foo'])
315
revision_id = tree_a.commit('bar')
316
tree_b = tree_a.bzrdir.sprout('tree_b').open_workingtree()
317
out, err = self.run_bzr('pull --quiet -d tree_b')
318
self.assertEqual(out, '')
319
self.assertEqual(err, '')
320
self.assertEqual(tree_b.last_revision(), revision_id)
321
self.build_tree(['tree_a/moo'])
323
revision_id = tree_a.commit('quack')
324
out, err = self.run_bzr('pull --quiet -d tree_b')
325
self.assertEqual(out, '')
326
self.assertEqual(err, '')
327
self.assertEqual(tree_b.last_revision(), revision_id)
329
def test_pull_from_directory_service(self):
330
source = self.make_branch_and_tree('source')
331
source.commit('commit 1')
332
target = source.bzrdir.sprout('target').open_workingtree()
333
source_last = source.commit('commit 2')
334
class FooService(object):
335
"""A directory service that always returns source"""
337
def look_up(self, name, url):
339
directories.register('foo:', FooService, 'Testing directory service')
340
self.addCleanup(lambda: directories.remove('foo:'))
341
self.run_bzr('pull foo:bar -d target')
342
self.assertEqual(source_last, target.last_revision())