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.osutils import getcwd
32
from bzrlib.workingtree import WorkingTree
35
class TestLegacyFormats(TestCaseWithTransport):
38
super(TestLegacyFormats, self).setUp()
39
self.build_tree(['master/', 'child/'])
40
self.run_bzr('init', 'master')
41
old_format = BzrDirFormat.get_default_format()
42
BzrDirFormat.set_default_format(BzrDirFormat6())
44
self.run_bzr('init', 'child')
46
BzrDirFormat.set_default_format(old_format)
49
def test_bind_format_6_bzrdir(self):
50
# bind on a format 6 bzrdir should error
51
out,err = self.run_bzr('bind', '../master', retcode=3)
52
self.assertEqual('', out)
53
self.assertEqual('bzr: ERROR: To use this feature you must '
54
'upgrade your branch at %s/.\n' % getcwd(), 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
self.assertEqual('bzr: ERROR: To use this feature you must '
61
'upgrade your branch at %s/.\n' % getcwd(), err)
64
class TestBoundBranches(TestCaseWithTransport):
66
def create_branches(self):
68
self.build_tree(['base/', 'base/a', 'base/b'])
70
self.init_meta_branch('base')
73
bzr('commit', '-m', 'init')
77
bzr('checkout', 'base', 'child')
79
self.failUnlessExists('child')
81
self.check_revno(1, 'child')
82
d = BzrDir.open('child')
83
self.assertNotEqual(None, d.open_branch().get_master_branch())
85
def check_revno(self, val, loc=None):
89
self.assertEquals(str(val), self.run_bzr('revno')[0].strip())
93
def test_simple_binding(self):
94
self.build_tree(['base/', 'base/a', 'base/b'])
96
self.init_meta_branch('base')
97
self.run_bzr('add', 'base')
98
self.run_bzr('commit', '-m', 'init', 'base')
100
self.run_bzr('branch', 'base', 'child')
103
self.run_bzr('bind', '../base')
106
self.assertNotEqual(None, d.open_branch().get_master_branch())
108
self.run_bzr('unbind')
109
self.assertEqual(None, d.open_branch().get_master_branch())
111
self.run_bzr('unbind', retcode=3)
113
def init_meta_branch(self, path):
114
old_format = BzrDirFormat.get_default_format()
115
BzrDirFormat.set_default_format(BzrDirMetaFormat1())
117
self.run_bzr('init', path)
119
BzrDirFormat.set_default_format(old_format)
121
def test_bound_commit(self):
123
self.create_branches()
126
open('a', 'wb').write('new contents\n')
127
bzr('commit', '-m', 'child')
131
# Make sure it committed on the parent
132
self.check_revno(2, '../base')
134
def test_bound_fail(self):
135
# Make sure commit fails if out of date.
137
self.create_branches()
140
open('a', 'wb').write('new base contents\n')
141
bzr('commit', '-m', 'base')
146
open('b', 'wb').write('new b child contents\n')
147
bzr('commit', '-m', 'child', retcode=3)
153
bzr('commit', '-m', 'child')
155
self.check_revno(3, '../base')
157
def test_double_binding(self):
159
self.create_branches()
161
bzr('branch', 'child', 'child2')
164
# Double binding succeeds, but committing to child2 should fail
165
bzr('bind', '../child')
167
bzr('commit', '-m', 'child2', '--unchanged', retcode=3)
169
def test_unbinding(self):
171
self.create_branches()
174
open('a', 'wb').write('new base contents\n')
175
bzr('commit', '-m', 'base')
179
open('b', 'wb').write('new b child contents\n')
181
bzr('commit', '-m', 'child', retcode=3)
184
bzr('commit', '-m', 'child')
187
bzr('bind', retcode=3)
189
def test_commit_remote_bound(self):
190
# It is not possible to commit to a branch
191
# which is bound to a branch which is bound
193
self.create_branches()
194
bzr('branch', 'base', 'newbase')
197
# There is no way to know that B has already
198
# been bound by someone else, otherwise it
199
# might be nice if this would fail
200
bzr('bind', '../newbase')
203
bzr('commit', '-m', 'failure', '--unchanged', retcode=3)
205
def test_pull_updates_both(self):
207
self.create_branches()
208
bzr('branch', 'base', 'newchild')
210
open('b', 'wb').write('newchild b contents\n')
211
bzr('commit', '-m', 'newchild')
215
# The pull should succeed, and update
216
# the bound parent branch
217
bzr('pull', '../newchild')
220
self.check_revno(2, '../base')
222
def test_bind_diverged(self):
224
self.create_branches()
229
bzr('commit', '-m', 'child', '--unchanged')
234
bzr('commit', '-m', 'base', '--unchanged')
238
# These branches have diverged
239
bzr('bind', '../base', retcode=3)
241
# TODO: In the future, this might require actual changes
242
# to have occurred, rather than just a new revision entry
243
bzr('merge', '../base')
244
bzr('commit', '-m', 'merged')
247
# After a merge, trying to bind again should succeed
248
# by pushing the new change to base
249
bzr('bind', '../base')
251
self.check_revno(3, '../base')
253
# After binding, the revision history should be identical
254
child_rh = bzr('revision-history')[0]
256
base_rh = bzr('revision-history')[0]
257
self.assertEquals(child_rh, base_rh)
259
def test_bind_parent_ahead(self):
261
self.create_branches()
267
bzr('commit', '-m', 'base', '--unchanged')
271
bzr('bind', '../base')
276
# Check and make sure it also works if parent is ahead multiple
278
bzr('commit', '-m', 'base 3', '--unchanged')
279
bzr('commit', '-m', 'base 4', '--unchanged')
280
bzr('commit', '-m', 'base 5', '--unchanged')
285
bzr('bind', '../base')
288
def test_bind_child_ahead(self):
290
self.create_branches()
294
bzr('commit', '-m', 'child', '--unchanged')
296
self.check_revno(1, '../base')
298
bzr('bind', '../base')
299
self.check_revno(2, '../base')
301
# Check and make sure it also works if child is ahead multiple
303
bzr('commit', '-m', 'child 3', '--unchanged')
304
bzr('commit', '-m', 'child 4', '--unchanged')
305
bzr('commit', '-m', 'child 5', '--unchanged')
308
self.check_revno(2, '../base')
309
bzr('bind', '../base')
310
self.check_revno(5, '../base')
312
def test_commit_after_merge(self):
314
self.create_branches()
316
# We want merge to be able to be a local only
317
# operation, because it can be without violating
318
# the binding invariants.
319
# But we can't fail afterwards
321
bzr('branch', 'child', 'other')
324
open('c', 'wb').write('file c\n')
326
bzr('commit', '-m', 'adding c')
327
new_rev_id = bzr('revision-history')[0].strip().split('\n')[-1]
330
bzr('merge', '../other')
332
self.failUnlessExists('c')
333
tree = WorkingTree.open('.')
334
self.assertEqual([new_rev_id], tree.pending_merges())
336
# Make sure the local branch has the installed revision
337
bzr('cat-revision', new_rev_id)
339
# And make sure that the base tree does not
341
bzr('cat-revision', new_rev_id, retcode=3)
343
# Commit should succeed, and cause merged revisions to
344
# be pulled into base
346
bzr('commit', '-m', 'merge other')
353
bzr('cat-revision', new_rev_id)
355
def test_pull_overwrite_fails(self):
357
self.create_branches()
359
bzr('branch', 'child', 'other')
362
open('a', 'wb').write('new contents\n')
363
bzr('commit', '-m', 'changed a')
365
open('a', 'ab').write('and then some\n')
366
bzr('commit', '-m', 'another a')
368
open('a', 'ab').write('and some more\n')
369
bzr('commit', '-m', 'yet another a')
373
open('a', 'wb').write('also changed a\n')
374
bzr('commit', '-m', 'child modified a')
377
self.check_revno(2, '../base')
379
# It might be possible that we want pull --overwrite to
381
# If we want it, just change this test to make sure that
382
# both base and child are updated properly
383
bzr('pull', '--overwrite', '../other', retcode=3)
385
# It should fail without changing the local revision
387
self.check_revno(2, '../base')
389
# TODO: jam 20051230 Test that commit & pull fail when the branch we
390
# are bound to is not available