1
# Copyright (C) 2005 by 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
"""Tests of bound branches (binding, unbinding, commit, etc) command.
22
from cStringIO import StringIO
24
from bzrlib.tests import TestCaseWithTransport
25
from bzrlib.branch import Branch
26
from bzrlib.bzrdir import (BzrDir,
31
from bzrlib.workingtree import WorkingTree
34
class TestLegacyFormats(TestCaseWithTransport):
37
super(TestLegacyFormats, self).setUp()
38
self.build_tree(['master/', 'child/'])
39
self.run_bzr('init', 'master')
40
old_format = BzrDirFormat.get_default_format()
41
BzrDirFormat.set_default_format(BzrDirFormat6())
43
self.run_bzr('init', 'child')
45
BzrDirFormat.set_default_format(old_format)
48
def test_bind_format_6_bzrdir(self):
49
# bind on a format 6 bzrdir should error
50
out,err = self.run_bzr('bind', '../master', retcode=3)
51
self.assertEqual('', out)
52
self.assertEqual('bzr: ERROR: To use this feature you must '
53
'upgrade your branch at %s/.\n' % os.getcwdu(), err)
55
def test_unbind_format_6_bzrdir(self):
56
# bind on a format 6 bzrdir should error
57
out,err = self.run_bzr('unbind', retcode=3)
58
self.assertEqual('', out)
59
self.assertEqual('bzr: ERROR: To use this feature you must '
60
'upgrade your branch at %s/.\n' % os.getcwdu(), err)
63
class TestBoundBranches(TestCaseWithTransport):
65
def create_branches(self):
67
self.build_tree(['base/', 'base/a', 'base/b'])
69
self.init_meta_branch('base')
72
bzr('commit', '-m', 'init')
76
bzr('checkout', 'base', 'child')
78
self.failUnlessExists('child')
80
self.check_revno(1, 'child')
81
d = BzrDir.open('child')
82
self.assertNotEqual(None, d.open_branch().get_master_branch())
84
def check_revno(self, val, loc=None):
88
self.assertEquals(str(val), self.run_bzr('revno')[0].strip())
92
def test_simple_binding(self):
93
self.build_tree(['base/', 'base/a', 'base/b'])
95
self.init_meta_branch('base')
96
self.run_bzr('add', 'base')
97
self.run_bzr('commit', '-m', 'init', 'base')
99
self.run_bzr('branch', 'base', 'child')
102
self.run_bzr('bind', '../base')
105
self.assertNotEqual(None, d.open_branch().get_master_branch())
107
self.run_bzr('unbind')
108
self.assertEqual(None, d.open_branch().get_master_branch())
110
self.run_bzr('unbind', retcode=3)
112
def init_meta_branch(self, path):
113
old_format = BzrDirFormat.get_default_format()
114
BzrDirFormat.set_default_format(BzrDirMetaFormat1())
116
self.run_bzr('init', path)
118
BzrDirFormat.set_default_format(old_format)
120
def test_bound_commit(self):
122
self.create_branches()
125
open('a', 'wb').write('new contents\n')
126
bzr('commit', '-m', 'child')
130
# Make sure it committed on the parent
131
self.check_revno(2, '../base')
133
def test_bound_fail(self):
134
# Make sure commit fails if out of date.
136
self.create_branches()
139
open('a', 'wb').write('new base contents\n')
140
bzr('commit', '-m', 'base')
145
open('b', 'wb').write('new b child contents\n')
146
bzr('commit', '-m', 'child', retcode=3)
152
bzr('commit', '-m', 'child')
154
self.check_revno(3, '../base')
156
def test_double_binding(self):
158
self.create_branches()
160
bzr('branch', 'child', 'child2')
163
# Double binding succeeds, but committing to child2 should fail
164
bzr('bind', '../child')
166
bzr('commit', '-m', 'child2', '--unchanged', retcode=3)
168
def test_unbinding(self):
170
self.create_branches()
173
open('a', 'wb').write('new base contents\n')
174
bzr('commit', '-m', 'base')
178
open('b', 'wb').write('new b child contents\n')
180
bzr('commit', '-m', 'child', retcode=3)
183
bzr('commit', '-m', 'child')
186
bzr('bind', retcode=3)
188
def test_commit_remote_bound(self):
189
# It is not possible to commit to a branch
190
# which is bound to a branch which is bound
192
self.create_branches()
193
bzr('branch', 'base', 'newbase')
196
# There is no way to know that B has already
197
# been bound by someone else, otherwise it
198
# might be nice if this would fail
199
bzr('bind', '../newbase')
202
bzr('commit', '-m', 'failure', '--unchanged', retcode=3)
204
def test_pull_updates_both(self):
206
self.create_branches()
207
bzr('branch', 'base', 'newchild')
209
open('b', 'wb').write('newchild b contents\n')
210
bzr('commit', '-m', 'newchild')
214
# The pull should succeed, and update
215
# the bound parent branch
216
bzr('pull', '../newchild')
219
self.check_revno(2, '../base')
221
def test_bind_diverged(self):
223
self.create_branches()
228
bzr('commit', '-m', 'child', '--unchanged')
233
bzr('commit', '-m', 'base', '--unchanged')
237
# These branches have diverged
238
bzr('bind', '../base', retcode=3)
240
# TODO: In the future, this might require actual changes
241
# to have occurred, rather than just a new revision entry
242
bzr('merge', '../base')
243
bzr('commit', '-m', 'merged')
246
# After a merge, trying to bind again should succeed
247
# by pushing the new change to base
248
bzr('bind', '../base')
250
self.check_revno(3, '../base')
252
# After binding, the revision history should be identical
253
child_rh = bzr('revision-history')[0]
255
base_rh = bzr('revision-history')[0]
256
self.assertEquals(child_rh, base_rh)
258
def test_bind_parent_ahead(self):
260
self.create_branches()
266
bzr('commit', '-m', 'base', '--unchanged')
270
bzr('bind', '../base')
275
# Check and make sure it also works if parent is ahead multiple
277
bzr('commit', '-m', 'base 3', '--unchanged')
278
bzr('commit', '-m', 'base 4', '--unchanged')
279
bzr('commit', '-m', 'base 5', '--unchanged')
284
bzr('bind', '../base')
287
def test_bind_child_ahead(self):
289
self.create_branches()
293
bzr('commit', '-m', 'child', '--unchanged')
295
self.check_revno(1, '../base')
297
bzr('bind', '../base')
298
self.check_revno(2, '../base')
300
# Check and make sure it also works if child is ahead multiple
302
bzr('commit', '-m', 'child 3', '--unchanged')
303
bzr('commit', '-m', 'child 4', '--unchanged')
304
bzr('commit', '-m', 'child 5', '--unchanged')
307
self.check_revno(2, '../base')
308
bzr('bind', '../base')
309
self.check_revno(5, '../base')
311
def test_commit_after_merge(self):
313
self.create_branches()
315
# We want merge to be able to be a local only
316
# operation, because it can be without violating
317
# the binding invariants.
318
# But we can't fail afterwards
320
bzr('branch', 'child', 'other')
323
open('c', 'wb').write('file c\n')
325
bzr('commit', '-m', 'adding c')
326
new_rev_id = bzr('revision-history')[0].strip().split('\n')[-1]
329
bzr('merge', '../other')
331
self.failUnlessExists('c')
332
tree = WorkingTree.open('.')
333
self.assertEqual([new_rev_id], tree.pending_merges())
335
# Make sure the local branch has the installed revision
336
bzr('cat-revision', new_rev_id)
338
# And make sure that the base tree does not
340
bzr('cat-revision', new_rev_id, retcode=3)
342
# Commit should succeed, and cause merged revisions to
343
# be pulled into base
345
bzr('commit', '-m', 'merge other')
352
bzr('cat-revision', new_rev_id)
354
def test_pull_overwrite_fails(self):
356
self.create_branches()
358
bzr('branch', 'child', 'other')
361
open('a', 'wb').write('new contents\n')
362
bzr('commit', '-m', 'changed a')
364
open('a', 'ab').write('and then some\n')
365
bzr('commit', '-m', 'another a')
367
open('a', 'ab').write('and some more\n')
368
bzr('commit', '-m', 'yet another a')
372
open('a', 'wb').write('also changed a\n')
373
bzr('commit', '-m', 'child modified a')
376
self.check_revno(2, '../base')
378
# It might be possible that we want pull --overwrite to
380
# If we want it, just change this test to make sure that
381
# both base and child are updated properly
382
bzr('pull', '--overwrite', '../other', retcode=3)
384
# It should fail without changing the local revision
386
self.check_revno(2, '../base')
388
# TODO: jam 20051230 Test that commit & pull fail when the branch we
389
# are bound to is not available