18
18
"""Tests of bound branches (binding, unbinding, commit, etc) command."""
21
from cStringIO import StringIO
20
23
from bzrlib import (
28
from bzrlib.branch import Branch
29
from bzrlib.bzrdir import (BzrDir, BzrDirFormat, BzrDirMetaFormat1)
30
from bzrlib.osutils import getcwd
26
31
from bzrlib.tests import script
32
import bzrlib.urlutils as urlutils
33
from bzrlib.workingtree import WorkingTree
36
class TestLegacyFormats(tests.TestCaseWithTransport):
39
super(TestLegacyFormats, self).setUp()
40
self.build_tree(['master/', 'child/'])
41
self.make_branch_and_tree('master')
42
self.make_branch_and_tree('child',
43
format=bzrdir.format_registry.make_bzrdir('weave'))
46
def test_bind_format_6_bzrdir(self):
47
# bind on a format 6 bzrdir should error
48
out,err = self.run_bzr('bind ../master', retcode=3)
49
self.assertEqual('', out)
50
# TODO: jam 20060427 Probably something like this really should
51
# print out the actual path, rather than the URL
52
cwd = urlutils.local_path_to_url(getcwd())
53
self.assertEqual('bzr: ERROR: To use this feature you must '
54
'upgrade your branch at %s/.\n' % cwd, err)
56
def test_unbind_format_6_bzrdir(self):
57
# bind on a format 6 bzrdir should error
58
out,err = self.run_bzr('unbind', retcode=3)
59
self.assertEqual('', out)
60
cwd = urlutils.local_path_to_url(getcwd())
61
self.assertEqual('bzr: ERROR: To use this feature you must '
62
'upgrade your branch at %s/.\n' % cwd, err)
29
65
class TestBoundBranches(tests.TestCaseWithTransport):
35
71
base_tree.add(['a', 'b'])
36
72
base_tree.commit('init')
74
branch = base_tree.branch
39
child_tree = base_tree.branch.create_checkout('child')
76
child_tree = branch.create_checkout('child')
41
78
self.check_revno(1, 'child')
42
d = controldir.ControlDir.open('child')
79
d = BzrDir.open('child')
43
80
self.assertNotEqual(None, d.open_branch().get_master_branch())
45
82
return base_tree, child_tree
47
84
def check_revno(self, val, loc='.'):
49
val, controldir.ControlDir.open(loc).open_branch().last_revision_info()[0])
86
val, len(BzrDir.open(loc).open_branch().revision_history()))
51
88
def test_simple_binding(self):
52
89
tree = self.make_branch_and_tree('base')
53
90
self.build_tree(['base/a', 'base/b'])
55
92
tree.commit(message='init')
57
95
tree.bzrdir.sprout('child')
59
self.run_bzr('bind ../base', working_dir='child')
98
self.run_bzr('bind ../base')
61
d = controldir.ControlDir.open('child')
62
101
self.assertNotEqual(None, d.open_branch().get_master_branch())
64
self.run_bzr('unbind', working_dir='child')
103
self.run_bzr('unbind')
65
104
self.assertEqual(None, d.open_branch().get_master_branch())
67
self.run_bzr('unbind', retcode=3, working_dir='child')
106
self.run_bzr('unbind', retcode=3)
69
108
def test_bind_branch6(self):
70
109
branch1 = self.make_branch('branch1', format='dirstate-tags')
71
error = self.run_bzr('bind', retcode=3, working_dir='branch1')[1]
73
error, 'No location supplied and no previous location known\n')
111
error = self.run_bzr('bind', retcode=3)[1]
112
self.assertContainsRe(error, 'no previous location known')
75
114
def setup_rebind(self, format):
76
115
branch1 = self.make_branch('branch1')
81
120
def test_rebind_branch6(self):
82
121
self.setup_rebind('dirstate-tags')
83
self.run_bzr('bind', working_dir='branch2')
84
b = branch.Branch.open('branch2')
85
self.assertEndsWith(b.get_bound_location(), '/branch1/')
125
self.assertContainsRe(b.get_bound_location(), '\/branch1\/$')
87
127
def test_rebind_branch5(self):
88
128
self.setup_rebind('knit')
89
error = self.run_bzr('bind', retcode=3, working_dir='branch2')[1]
91
error, 'No location supplied. This format does not remember'
130
error = self.run_bzr('bind', retcode=3)[1]
131
self.assertContainsRe(error, 'old locations')
94
133
def test_bound_commit(self):
95
134
child_tree = self.create_branches()[1]
127
166
def test_double_binding(self):
128
167
child_tree = self.create_branches()[1]
129
child_tree.bzrdir.sprout('child2')
169
child2_tree = child_tree.bzrdir.sprout('child2').open_workingtree()
131
172
# Double binding succeeds, but committing to child2 should fail
132
self.run_bzr('bind ../child', working_dir='child2')
173
self.run_bzr('bind ../child')
134
# Refresh the child tree object as 'unbind' modified it
135
child2_tree = controldir.ControlDir.open('child2').open_workingtree()
136
175
self.assertRaises(errors.CommitToDoubleBoundBranch,
137
176
child2_tree.commit, message='child2', allow_pointless=True)
147
186
self.check_revno(2, 'base')
149
188
self.check_revno(1, 'child')
150
self.run_bzr("commit -m child", retcode=3, working_dir='child')
151
self.check_revno(1, 'child')
152
self.run_bzr('unbind', working_dir='child')
153
# Refresh the child tree/branch objects as 'unbind' modified them
154
child_tree = child_tree.bzrdir.open_workingtree()
190
self.run_bzr("commit -m child", retcode=3)
192
self.run_bzr('unbind')
155
193
child_tree.commit(message='child')
156
self.check_revno(2, 'child')
158
196
def test_commit_remote_bound(self):
159
197
# It is not possible to commit to a branch
161
199
base_tree, child_tree = self.create_branches()
162
200
base_tree.bzrdir.sprout('newbase')
164
203
# There is no way to know that B has already
165
204
# been bound by someone else, otherwise it
166
205
# might be nice if this would fail
167
self.run_bzr('bind ../newbase', working_dir='base')
206
self.run_bzr('bind ../newbase')
169
self.run_bzr('commit -m failure --unchanged', retcode=3,
209
self.run_bzr('commit -m failure --unchanged', retcode=3)
172
211
def test_pull_updates_both(self):
173
212
base_tree = self.create_branches()[0]
176
215
newchild_tree.commit(message='newchild')
177
216
self.check_revno(2, 'newchild')
179
219
# The pull should succeed, and update
180
220
# the bound parent branch
181
self.run_bzr('pull ../newchild', working_dir='child')
182
self.check_revno(2, 'child')
183
self.check_revno(2, 'base')
221
self.run_bzr('pull ../newchild')
224
self.check_revno(2, '../base')
185
226
def test_pull_local_updates_local(self):
186
227
base_tree = self.create_branches()[0]
189
230
newchild_tree.commit(message='newchild')
190
231
self.check_revno(2, 'newchild')
192
234
# The pull should succeed, and update
193
235
# the bound parent branch
194
self.run_bzr('pull ../newchild --local', working_dir='child')
195
self.check_revno(2, 'child')
196
self.check_revno(1, 'base')
236
self.run_bzr('pull ../newchild --local')
239
self.check_revno(1, '../base')
198
241
def test_bind_diverged(self):
199
242
base_tree, child_tree = self.create_branches()
200
243
base_branch = base_tree.branch
201
244
child_branch = child_tree.branch
203
self.run_bzr('unbind', working_dir='child')
247
self.run_bzr('unbind')
205
# Refresh the child tree/branch objects as 'unbind' modified them
206
child_tree = child_tree.bzrdir.open_workingtree()
207
249
child_tree.commit(message='child', allow_pointless=True)
208
self.check_revno(2, 'child')
210
253
self.check_revno(1, 'base')
211
254
base_tree.commit(message='base', allow_pointless=True)
212
255
self.check_revno(2, 'base')
214
258
# These branches have diverged, but bind should succeed anyway
215
self.run_bzr('bind ../base', working_dir='child')
259
self.run_bzr('bind ../base')
217
# Refresh the child tree/branch objects as 'bind' modified them
218
child_tree = child_tree.bzrdir.open_workingtree()
219
261
# This should turn the local commit into a merge
220
262
child_tree.update()
221
263
child_tree.commit(message='merged')
222
self.check_revno(3, 'child')
223
self.assertEqual(child_tree.branch.last_revision(),
224
base_tree.branch.last_revision())
266
# After binding, the revision history should be unaltered
268
base_history = base_branch.revision_history()
269
child_history = child_branch.revision_history()
226
271
def test_bind_parent_ahead(self):
227
272
base_tree = self.create_branches()[0]
229
self.run_bzr('unbind', working_dir='child')
275
self.run_bzr('unbind')
231
277
base_tree.commit(message='base', allow_pointless=True)
233
self.check_revno(1, 'child')
234
self.run_bzr('bind ../base', working_dir='child')
280
self.run_bzr('bind ../base')
236
282
# binding does not pull data:
237
self.check_revno(1, 'child')
238
self.run_bzr('unbind', working_dir='child')
284
self.run_bzr('unbind')
240
286
# Check and make sure it also works if parent is ahead multiple
241
287
base_tree.commit(message='base 3', allow_pointless=True)
242
288
base_tree.commit(message='base 4', allow_pointless=True)
243
289
base_tree.commit(message='base 5', allow_pointless=True)
244
self.check_revno(5, 'base')
290
self.check_revno(5, '../base')
246
self.check_revno(1, 'child')
247
self.run_bzr('bind ../base', working_dir='child')
248
self.check_revno(1, 'child')
293
self.run_bzr('bind ../base')
250
296
def test_bind_child_ahead(self):
251
297
# test binding when the master branches history is a prefix of the
254
300
child_tree = self.create_branches()[1]
256
self.run_bzr('unbind', working_dir='child')
257
# Refresh the child tree/branch objects as 'bind' modified them
258
child_tree = child_tree.bzrdir.open_workingtree()
303
self.run_bzr('unbind')
259
304
child_tree.commit(message='child', allow_pointless=True)
260
self.check_revno(2, 'child')
261
self.check_revno(1, 'base')
306
self.check_revno(1, '../base')
263
self.run_bzr('bind ../base', working_dir='child')
264
self.check_revno(1, 'base')
308
self.run_bzr('bind ../base')
309
self.check_revno(1, '../base')
266
311
# Check and make sure it also works if child is ahead multiple
267
self.run_bzr('unbind', working_dir='child')
312
self.run_bzr('unbind')
268
313
child_tree.commit(message='child 3', allow_pointless=True)
269
314
child_tree.commit(message='child 4', allow_pointless=True)
270
315
child_tree.commit(message='child 5', allow_pointless=True)
271
self.check_revno(5, 'child')
273
self.check_revno(1, 'base')
274
self.run_bzr('bind ../base', working_dir='child')
275
self.check_revno(1, 'base')
318
self.check_revno(1, '../base')
319
self.run_bzr('bind ../base')
320
self.check_revno(1, '../base')
277
322
def test_bind_fail_if_missing(self):
278
323
"""We should not be able to bind to a missing branch."""
279
324
tree = self.make_branch_and_tree('tree_1')
280
325
tree.commit('dummy commit')
281
self.run_bzr_error(['Not a branch.*no-such-branch/'],
282
['bind', '../no-such-branch'],
283
working_dir='tree_1')
326
self.run_bzr_error(['Not a branch.*no-such-branch/'], ['bind', '../no-such-branch'],
327
working_dir='tree_1')
284
328
self.assertIs(None, tree.branch.get_bound_location())
330
def test_bind_nick(self):
331
"""Bind should not update implicit nick."""
332
base = self.make_branch_and_tree('base')
333
child = self.make_branch_and_tree('child')
335
self.assertEqual(child.branch.nick, 'child')
336
self.assertEqual(child.branch.get_config().has_explicit_nickname(),
338
self.run_bzr('bind ../base')
339
self.assertEqual(child.branch.nick, base.branch.nick)
340
self.assertEqual(child.branch.get_config().has_explicit_nickname(),
343
def test_bind_explicit_nick(self):
344
"""Bind should update explicit nick."""
345
base = self.make_branch_and_tree('base')
346
child = self.make_branch_and_tree('child')
348
child.branch.nick = "explicit_nick"
349
self.assertEqual(child.branch.nick, "explicit_nick")
350
self.assertEqual(child.branch.get_config()._get_explicit_nickname(),
352
self.run_bzr('bind ../base')
353
self.assertEqual(child.branch.nick, base.branch.nick)
354
self.assertEqual(child.branch.get_config()._get_explicit_nickname(),
286
357
def test_commit_after_merge(self):
287
358
base_tree, child_tree = self.create_branches()
312
383
# Commit should succeed, and cause merged revisions to
313
384
# be pulled into base
314
self.run_bzr(['commit', '-m', 'merge other'], working_dir='child')
315
self.check_revno(2, 'child')
316
self.check_revno(2, 'base')
386
self.run_bzr(['commit', '-m', 'merge other'])
390
self.check_revno(2, '../base')
317
392
self.assertTrue(base_tree.branch.repository.has_revision(new_rev_id))
319
394
def test_pull_overwrite(self):
340
415
self.check_revno(2, 'child')
341
416
self.check_revno(2, 'base')
343
self.run_bzr('pull --overwrite ../other', working_dir='child')
419
self.run_bzr('pull --overwrite ../other')
345
421
# both the local and master should have been updated.
346
self.check_revno(4, 'child')
347
self.check_revno(4, 'base')
423
self.check_revno(4, '../base')
349
425
def test_bind_directory(self):
350
426
"""Test --directory option"""