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('get', '--bound', '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')
143
open('b', 'wb').write('new b child contents\n')
144
bzr('commit', '-m', 'child', retcode=3)
149
bzr('commit', '-m', 'child')
151
self.check_revno(3, '../base')
153
def test_double_binding(self):
155
self.create_branches()
157
bzr('branch', 'child', 'child2')
160
# Double binding succeeds, but committing to child2 should fail
161
bzr('bind', '../child')
163
bzr('commit', '-m', 'child2', '--unchanged', retcode=3)
165
def test_unbinding(self):
167
self.create_branches()
170
open('a', 'wb').write('new base contents\n')
171
bzr('commit', '-m', 'base')
175
open('b', 'wb').write('new b child contents\n')
177
bzr('commit', '-m', 'child', retcode=3)
180
bzr('commit', '-m', 'child')
183
bzr('bind', retcode=3)
185
def test_commit_remote_bound(self):
186
# It is not possible to commit to a branch
187
# which is bound to a branch which is bound
189
self.create_branches()
190
bzr('branch', 'base', 'newbase')
193
# There is no way to know that B has already
194
# been bound by someone else, otherwise it
195
# might be nice if this would fail
196
bzr('bind', '../newbase')
199
bzr('commit', '-m', 'failure', '--unchanged', retcode=3)
201
def test_pull_updates_both(self):
203
self.create_branches()
204
bzr('branch', 'base', 'newchild')
206
open('b', 'wb').write('newchild b contents\n')
207
bzr('commit', '-m', 'newchild')
211
# The pull should succeed, and update
212
# the bound parent branch
213
bzr('pull', '../newchild')
216
self.check_revno(2, '../base')
218
def test_bind_diverged(self):
220
self.create_branches()
225
bzr('commit', '-m', 'child', '--unchanged')
230
bzr('commit', '-m', 'base', '--unchanged')
234
# These branches have diverged
235
bzr('bind', '../base', retcode=3)
237
# TODO: In the future, this might require actual changes
238
# to have occurred, rather than just a new revision entry
239
bzr('merge', '../base')
240
bzr('commit', '-m', 'merged')
243
# After a merge, trying to bind again should succeed
244
# by pushing the new change to base
245
bzr('bind', '../base')
247
self.check_revno(3, '../base')
249
# After binding, the revision history should be identical
250
child_rh = bzr('revision-history')[0]
252
base_rh = bzr('revision-history')[0]
253
self.assertEquals(child_rh, base_rh)
255
def test_bind_parent_ahead(self):
257
self.create_branches()
263
bzr('commit', '-m', 'base', '--unchanged')
267
bzr('bind', '../base')
272
# Check and make sure it also works if parent is ahead multiple
274
bzr('commit', '-m', 'base 3', '--unchanged')
275
bzr('commit', '-m', 'base 4', '--unchanged')
276
bzr('commit', '-m', 'base 5', '--unchanged')
284
def test_bind_child_ahead(self):
286
self.create_branches()
290
bzr('commit', '-m', 'child', '--unchanged')
292
self.check_revno(1, '../base')
294
bzr('bind', '../base')
295
self.check_revno(2, '../base')
297
# Check and make sure it also works if child is ahead multiple
299
bzr('commit', '-m', 'child 3', '--unchanged')
300
bzr('commit', '-m', 'child 4', '--unchanged')
301
bzr('commit', '-m', 'child 5', '--unchanged')
304
self.check_revno(2, '../base')
306
self.check_revno(5, '../base')
308
def test_commit_after_merge(self):
310
self.create_branches()
312
# We want merge to be able to be a local only
313
# operation, because it can be without violating
314
# the binding invariants.
315
# But we can't fail afterwards
317
bzr('branch', 'child', 'other')
320
open('c', 'wb').write('file c\n')
322
bzr('commit', '-m', 'adding c')
323
new_rev_id = bzr('revision-history')[0].strip().split('\n')[-1]
326
bzr('merge', '../other')
328
self.failUnlessExists('c')
329
tree = WorkingTree.open('.')
330
self.assertEqual([new_rev_id], tree.pending_merges())
332
# Make sure the local branch has the installed revision
333
bzr('cat-revision', new_rev_id)
335
# And make sure that the base tree does not
337
bzr('cat-revision', new_rev_id, retcode=3)
339
# Commit should succeed, and cause merged revisions to
340
# be pulled into base
342
bzr('commit', '-m', 'merge other')
349
bzr('cat-revision', new_rev_id)
351
def test_pull_overwrite_fails(self):
353
self.create_branches()
355
bzr('branch', 'child', 'other')
358
open('a', 'wb').write('new contents\n')
359
bzr('commit', '-m', 'changed a')
361
open('a', 'ab').write('and then some\n')
362
bzr('commit', '-m', 'another a')
364
open('a', 'ab').write('and some more\n')
365
bzr('commit', '-m', 'yet another a')
369
open('a', 'wb').write('also changed a\n')
370
bzr('commit', '-m', 'child modified a')
373
self.check_revno(2, '../base')
375
# It might be possible that we want pull --overwrite to
377
# If we want it, just change this test to make sure that
378
# both base and child are updated properly
379
bzr('pull', '--overwrite', '../other', retcode=3)
381
# It should fail without changing the local revision
383
self.check_revno(2, '../base')
385
# TODO: jam 20051230 Test that commit & pull fail when the branch we
386
# are bound to is not available