1
# Copyright (C) 2005, 2006 Canonical Ltd
1
# (C) 2005 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
11
# GNU General Public License for more details.
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
"""Tests for branch implementations - tests a branch format."""
32
from bzrlib.branch import Branch, needs_read_lock, needs_write_lock
33
from bzrlib.delta import TreeDelta
34
from bzrlib.errors import (FileExists,
37
UninitializableFormat,
40
from bzrlib.osutils import getcwd
41
import bzrlib.revision
42
from bzrlib.tests import TestCase, TestCaseWithTransport, TestSkipped
43
from bzrlib.tests.branch_implementations import TestCaseWithBranch
44
from bzrlib.tests.HttpServer import HttpServer
45
from bzrlib.trace import mutter
46
from bzrlib.transport import get_transport
47
from bzrlib.transport.memory import MemoryServer
48
from bzrlib.upgrade import upgrade
49
from bzrlib.workingtree import WorkingTree
52
class TestBranch(TestCaseWithBranch):
17
from bzrlib.selftest import TestCaseInTempDir
20
class TestAppendRevisions(TestCaseInTempDir):
21
"""Test appending more than one revision"""
54
22
def test_append_revisions(self):
55
"""Test appending more than one revision"""
56
wt = self.make_branch_and_tree('tree')
57
wt.commit('f', rev_id='rev1')
58
wt.commit('f', rev_id='rev2')
59
wt.commit('f', rev_id='rev3')
61
br = self.get_branch()
23
from bzrlib.branch import Branch
24
br = Branch(".", init=True)
63
25
br.append_revision("rev1")
64
26
self.assertEquals(br.revision_history(), ["rev1",])
65
27
br.append_revision("rev2", "rev3")
66
28
self.assertEquals(br.revision_history(), ["rev1", "rev2", "rev3"])
67
self.assertRaises(errors.ReservedId, br.append_revision, 'current:')
69
def test_create_tree_with_merge(self):
70
tree = self.create_tree_with_merge()
71
ancestry_graph = tree.branch.repository.get_revision_graph('rev-3')
72
self.assertEqual({'rev-1':[],
74
'rev-1.1.1':['rev-1'],
75
'rev-3':['rev-2', 'rev-1.1.1'],
78
def test_revision_ids_are_utf8(self):
79
wt = self.make_branch_and_tree('tree')
80
wt.commit('f', rev_id='rev1')
81
wt.commit('f', rev_id='rev2')
82
wt.commit('f', rev_id='rev3')
84
br = self.get_branch()
86
br.set_revision_history(['rev1', 'rev2', 'rev3'])
87
rh = br.revision_history()
88
self.assertEqual(['rev1', 'rev2', 'rev3'], rh)
89
for revision_id in rh:
90
self.assertIsInstance(revision_id, str)
91
last = br.last_revision()
92
self.assertEqual('rev3', last)
93
self.assertIsInstance(last, str)
94
revno, last = br.last_revision_info()
95
self.assertEqual(3, revno)
96
self.assertEqual('rev3', last)
97
self.assertIsInstance(last, str)
99
def test_fetch_revisions(self):
100
"""Test fetch-revision operation."""
101
wt = self.make_branch_and_tree('b1')
103
self.build_tree_contents([('b1/foo', 'hello')])
104
wt.add(['foo'], ['foo-id'])
105
wt.commit('lala!', rev_id='revision-1', allow_pointless=False)
107
b2 = self.make_branch('b2')
108
self.assertEqual((1, []), b2.fetch(b1))
110
rev = b2.repository.get_revision('revision-1')
111
tree = b2.repository.revision_tree('revision-1')
112
self.assertEqual(tree.get_file_text('foo-id'), 'hello')
114
def test_get_revision_delta(self):
115
tree_a = self.make_branch_and_tree('a')
116
self.build_tree(['a/foo'])
117
tree_a.add('foo', 'file1')
118
tree_a.commit('rev1', rev_id='rev1')
119
self.build_tree(['a/vla'])
120
tree_a.add('vla', 'file2')
121
tree_a.commit('rev2', rev_id='rev2')
123
delta = tree_a.branch.get_revision_delta(1)
124
self.assertIsInstance(delta, TreeDelta)
125
self.assertEqual([('foo', 'file1', 'file')], delta.added)
126
delta = tree_a.branch.get_revision_delta(2)
127
self.assertIsInstance(delta, TreeDelta)
128
self.assertEqual([('vla', 'file2', 'file')], delta.added)
130
def get_unbalanced_tree_pair(self):
131
"""Return two branches, a and b, with one file in a."""
132
tree_a = self.make_branch_and_tree('a')
133
self.build_tree_contents([('a/b', 'b')])
135
tree_a.commit("silly commit", rev_id='A')
137
tree_b = self.make_branch_and_tree('b')
138
return tree_a, tree_b
140
def get_balanced_branch_pair(self):
141
"""Returns br_a, br_b as with one commit in a, and b has a's stores."""
142
tree_a, tree_b = self.get_unbalanced_tree_pair()
143
tree_b.branch.repository.fetch(tree_a.branch.repository)
144
return tree_a, tree_b
146
def test_clone_partial(self):
147
"""Copy only part of the history of a branch."""
148
# TODO: RBC 20060208 test with a revision not on revision-history.
149
# what should that behaviour be ? Emailed the list.
150
# First, make a branch with two commits.
151
wt_a = self.make_branch_and_tree('a')
152
self.build_tree(['a/one'])
154
wt_a.commit('commit one', rev_id='1')
155
self.build_tree(['a/two'])
157
wt_a.commit('commit two', rev_id='2')
158
# Now make a copy of the repository.
159
repo_b = self.make_repository('b')
160
wt_a.branch.repository.copy_content_into(repo_b)
161
# wt_a might be a lightweight checkout, so get a hold of the actual
162
# branch (because you can't do a partial clone of a lightweight
164
branch = wt_a.branch.bzrdir.open_branch()
165
# Then make a branch where the new repository is, but specify a revision
166
# ID. The new branch's history will stop at the specified revision.
167
br_b = branch.clone(repo_b.bzrdir, revision_id='1')
168
self.assertEqual('1', br_b.last_revision())
170
def test_sprout_partial(self):
171
# test sprouting with a prefix of the revision-history.
172
# also needs not-on-revision-history behaviour defined.
173
wt_a = self.make_branch_and_tree('a')
174
self.build_tree(['a/one'])
176
wt_a.commit('commit one', rev_id='1')
177
self.build_tree(['a/two'])
179
wt_a.commit('commit two', rev_id='2')
180
repo_b = self.make_repository('b')
181
repo_a = wt_a.branch.repository
182
repo_a.copy_content_into(repo_b)
183
br_b = wt_a.branch.sprout(repo_b.bzrdir, revision_id='1')
184
self.assertEqual('1', br_b.last_revision())
186
def get_parented_branch(self):
187
wt_a = self.make_branch_and_tree('a')
188
self.build_tree(['a/one'])
190
wt_a.commit('commit one', rev_id='1')
192
branch_b = wt_a.bzrdir.sprout('b', revision_id='1').open_branch()
193
self.assertEqual(wt_a.branch.base, branch_b.get_parent())
196
def test_clone_branch_nickname(self):
197
# test the nick name is preserved always
198
raise TestSkipped('XXX branch cloning is not yet tested..')
200
def test_clone_branch_parent(self):
201
# test the parent is preserved always
202
branch_b = self.get_parented_branch()
203
repo_c = self.make_repository('c')
204
branch_b.repository.copy_content_into(repo_c)
205
branch_c = branch_b.clone(repo_c.bzrdir)
206
self.assertNotEqual(None, branch_c.get_parent())
207
self.assertEqual(branch_b.get_parent(), branch_c.get_parent())
209
# We can also set a specific parent, and it should be honored
210
random_parent = 'http://bazaar-vcs.org/path/to/branch'
211
branch_b.set_parent(random_parent)
212
repo_d = self.make_repository('d')
213
branch_b.repository.copy_content_into(repo_d)
214
branch_d = branch_b.clone(repo_d.bzrdir)
215
self.assertEqual(random_parent, branch_d.get_parent())
217
def test_sprout_branch_nickname(self):
218
# test the nick name is reset always
219
raise TestSkipped('XXX branch sprouting is not yet tested..')
221
def test_sprout_branch_parent(self):
222
source = self.make_branch('source')
223
target = source.bzrdir.sprout(self.get_url('target')).open_branch()
224
self.assertEqual(source.bzrdir.root_transport.base, target.get_parent())
226
def test_submit_branch(self):
227
"""Submit location can be queried and set"""
228
branch = self.make_branch('branch')
229
self.assertEqual(branch.get_submit_branch(), None)
230
branch.set_submit_branch('sftp://example.com')
231
self.assertEqual(branch.get_submit_branch(), 'sftp://example.com')
232
branch.set_submit_branch('sftp://example.net')
233
self.assertEqual(branch.get_submit_branch(), 'sftp://example.net')
235
def test_public_branch(self):
236
"""public location can be queried and set"""
237
branch = self.make_branch('branch')
238
self.assertEqual(branch.get_public_branch(), None)
239
branch.set_public_branch('sftp://example.com')
240
self.assertEqual(branch.get_public_branch(), 'sftp://example.com')
241
branch.set_public_branch('sftp://example.net')
242
self.assertEqual(branch.get_public_branch(), 'sftp://example.net')
243
branch.set_public_branch(None)
244
self.assertEqual(branch.get_public_branch(), None)
246
def test_record_initial_ghost(self):
247
"""Branches should support having ghosts."""
248
wt = self.make_branch_and_tree('.')
249
wt.set_parent_ids(['non:existent@rev--ision--0--2'],
250
allow_leftmost_as_ghost=True)
251
rev_id = wt.commit('commit against a ghost first parent.')
252
rev = wt.branch.repository.get_revision(rev_id)
253
self.assertEqual(rev.parent_ids, ['non:existent@rev--ision--0--2'])
254
# parent_sha1s is not populated now, WTF. rbc 20051003
255
self.assertEqual(len(rev.parent_sha1s), 0)
257
def test_record_two_ghosts(self):
258
"""Recording with all ghosts works."""
259
wt = self.make_branch_and_tree('.')
261
'foo@azkhazan-123123-abcabc',
262
'wibble@fofof--20050401--1928390812',
264
allow_leftmost_as_ghost=True)
265
rev_id = wt.commit("commit from ghost base with one merge")
266
# the revision should have been committed with two parents
267
rev = wt.branch.repository.get_revision(rev_id)
268
self.assertEqual(['foo@azkhazan-123123-abcabc',
269
'wibble@fofof--20050401--1928390812'],
272
def test_bad_revision(self):
273
self.assertRaises(errors.InvalidRevisionId,
274
self.get_branch().repository.get_revision,
278
# compare the gpg-to-sign info for a commit with a ghost and
279
# an identical tree without a ghost
280
# fetch missing should rewrite the TOC of weaves to list newly available parents.
282
def test_sign_existing_revision(self):
283
wt = self.make_branch_and_tree('.')
285
wt.commit("base", allow_pointless=True, rev_id='A')
286
from bzrlib.testament import Testament
287
strategy = gpg.LoopbackGPGStrategy(None)
288
branch.repository.sign_revision('A', strategy)
289
self.assertEqual('-----BEGIN PSEUDO-SIGNED CONTENT-----\n' +
290
Testament.from_revision(branch.repository,
291
'A').as_short_text() +
292
'-----END PSEUDO-SIGNED CONTENT-----\n',
293
branch.repository.get_signature_text('A'))
295
def test_store_signature(self):
296
wt = self.make_branch_and_tree('.')
298
branch.repository.store_revision_signature(
299
gpg.LoopbackGPGStrategy(None), 'FOO', 'A')
300
self.assertRaises(errors.NoSuchRevision,
301
branch.repository.has_signature_for_revision_id,
303
wt.commit("base", allow_pointless=True, rev_id='A')
304
self.assertEqual('-----BEGIN PSEUDO-SIGNED CONTENT-----\n'
305
'FOO-----END PSEUDO-SIGNED CONTENT-----\n',
306
branch.repository.get_signature_text('A'))
308
def test_branch_keeps_signatures(self):
309
wt = self.make_branch_and_tree('source')
310
wt.commit('A', allow_pointless=True, rev_id='A')
311
repo = wt.branch.repository
312
repo.sign_revision('A', gpg.LoopbackGPGStrategy(None))
313
#FIXME: clone should work to urls,
314
# wt.clone should work to disks.
315
self.build_tree(['target/'])
316
d2 = repo.bzrdir.clone(urlutils.local_path_to_url('target'))
317
self.assertEqual(repo.get_signature_text('A'),
318
d2.open_repository().get_signature_text('A'))
320
def test_nicks(self):
321
"""Test explicit and implicit branch nicknames.
323
Nicknames are implicitly the name of the branch's directory, unless an
324
explicit nickname is set. That is, an explicit nickname always
325
overrides the implicit one.
327
t = get_transport(self.get_url())
328
branch = self.make_branch('bzr.dev')
329
# The nick will be 'bzr.dev', because there is no explicit nick set.
330
self.assertEqual(branch.nick, 'bzr.dev')
331
# Move the branch to a different directory, 'bzr.ab'. Now that branch
332
# will report its nick as 'bzr.ab'.
333
t.move('bzr.dev', 'bzr.ab')
334
branch = Branch.open(self.get_url('bzr.ab'))
335
self.assertEqual(branch.nick, 'bzr.ab')
336
# Set the branch nick explicitly. This will ensure there's a branch
337
# config file in the branch.
338
branch.nick = "Aaron's branch"
339
branch.nick = "Aaron's branch"
340
if not isinstance(branch, remote.RemoteBranch):
341
controlfilename = branch.control_files.controlfilename
342
self.failUnless(t.has(t.relpath(controlfilename("branch.conf"))))
343
# Because the nick has been set explicitly, the nick is now always
344
# "Aaron's branch", regardless of directory name.
345
self.assertEqual(branch.nick, "Aaron's branch")
346
t.move('bzr.ab', 'integration')
347
branch = Branch.open(self.get_url('integration'))
348
self.assertEqual(branch.nick, "Aaron's branch")
349
branch.nick = u"\u1234"
350
self.assertEqual(branch.nick, u"\u1234")
352
def test_commit_nicks(self):
353
"""Nicknames are committed to the revision"""
354
wt = self.make_branch_and_tree('bzr.dev')
356
branch.nick = "My happy branch"
357
wt.commit('My commit respect da nick.')
358
committed = branch.repository.get_revision(branch.last_revision())
359
self.assertEqual(committed.properties["branch-nick"],
362
def test_create_open_branch_uses_repository(self):
364
repo = self.make_repository('.', shared=True)
365
except errors.IncompatibleFormat:
367
child_transport = repo.bzrdir.root_transport.clone('child')
368
child_transport.mkdir('.')
369
child_dir = self.bzrdir_format.initialize_on_transport(child_transport)
371
child_branch = self.branch_format.initialize(child_dir)
372
except errors.UninitializableFormat:
373
# branch references are not default init'able.
375
self.assertEqual(repo.bzrdir.root_transport.base,
376
child_branch.repository.bzrdir.root_transport.base)
377
child_branch = branch.Branch.open(self.get_url('child'))
378
self.assertEqual(repo.bzrdir.root_transport.base,
379
child_branch.repository.bzrdir.root_transport.base)
381
def test_format_description(self):
382
tree = self.make_branch_and_tree('tree')
383
text = tree.branch._format.get_format_description()
384
self.failUnless(len(text))
386
def test_check_branch_report_results(self):
387
"""Checking a branch produces results which can be printed"""
388
branch = self.make_branch('.')
389
result = branch.check()
390
# reports results through logging
391
result.report_results(verbose=True)
392
result.report_results(verbose=False)
394
def test_get_commit_builder(self):
395
self.assertIsInstance(self.make_branch(".").get_commit_builder([]),
396
repository.CommitBuilder)
398
def test_generate_revision_history(self):
399
"""Create a fake revision history easily."""
400
tree = self.make_branch_and_tree('.')
401
rev1 = tree.commit('foo')
402
orig_history = tree.branch.revision_history()
403
rev2 = tree.commit('bar', allow_pointless=True)
404
tree.branch.generate_revision_history(rev1)
405
self.assertEqual(orig_history, tree.branch.revision_history())
407
def test_generate_revision_history_NULL_REVISION(self):
408
tree = self.make_branch_and_tree('.')
409
rev1 = tree.commit('foo')
410
tree.branch.generate_revision_history(bzrlib.revision.NULL_REVISION)
411
self.assertEqual([], tree.branch.revision_history())
413
def test_create_checkout(self):
414
tree_a = self.make_branch_and_tree('a')
415
branch_a = tree_a.branch
416
checkout_b = branch_a.create_checkout('b')
417
self.assertEqual(None, checkout_b.last_revision())
418
checkout_b.commit('rev1', rev_id='rev1')
419
self.assertEqual('rev1', branch_a.last_revision())
420
self.assertNotEqual(checkout_b.branch.base, branch_a.base)
422
checkout_c = branch_a.create_checkout('c', lightweight=True)
423
self.assertEqual('rev1', checkout_c.last_revision())
424
checkout_c.commit('rev2', rev_id='rev2')
425
self.assertEqual('rev2', branch_a.last_revision())
426
self.assertEqual(checkout_c.branch.base, branch_a.base)
429
checkout_d = branch_a.create_checkout('d', lightweight=True)
430
self.assertEqual('rev2', checkout_d.last_revision())
432
checkout_e = branch_a.create_checkout('e')
433
self.assertEqual('rev2', checkout_e.last_revision())
435
def test_create_anonymous_lightweight_checkout(self):
436
"""A lightweight checkout from a readonly branch should succeed."""
437
tree_a = self.make_branch_and_tree('a')
438
rev_id = tree_a.commit('put some content in the branch')
439
# open the branch via a readonly transport
440
source_branch = bzrlib.branch.Branch.open(self.get_readonly_url('a'))
441
# sanity check that the test will be valid
442
self.assertRaises((errors.LockError, errors.TransportNotPossible),
443
source_branch.lock_write)
444
checkout = source_branch.create_checkout('c', lightweight=True)
445
self.assertEqual(rev_id, checkout.last_revision())
447
def test_create_anonymous_heavyweight_checkout(self):
448
"""A regular checkout from a readonly branch should succeed."""
449
tree_a = self.make_branch_and_tree('a')
450
rev_id = tree_a.commit('put some content in the branch')
451
# open the branch via a readonly transport
452
source_branch = bzrlib.branch.Branch.open(self.get_readonly_url('a'))
453
# sanity check that the test will be valid
454
self.assertRaises((errors.LockError, errors.TransportNotPossible),
455
source_branch.lock_write)
456
checkout = source_branch.create_checkout('c')
457
self.assertEqual(rev_id, checkout.last_revision())
459
def test_set_revision_history(self):
460
tree = self.make_branch_and_tree('a')
461
tree.commit('a commit', rev_id='rev1')
463
br.set_revision_history(["rev1"])
464
self.assertEquals(br.revision_history(), ["rev1"])
465
br.set_revision_history([])
466
self.assertEquals(br.revision_history(), [])
469
class ChrootedTests(TestCaseWithBranch):
470
"""A support class that provides readonly urls outside the local namespace.
472
This is done by checking if self.transport_server is a MemoryServer. if it
473
is then we are chrooted already, if it is not then an HttpServer is used
478
super(ChrootedTests, self).setUp()
479
if not self.vfs_transport_factory == MemoryServer:
480
self.transport_readonly_server = HttpServer
482
def test_open_containing(self):
483
self.assertRaises(NotBranchError, Branch.open_containing,
484
self.get_readonly_url(''))
485
self.assertRaises(NotBranchError, Branch.open_containing,
486
self.get_readonly_url('g/p/q'))
487
branch = self.make_branch('.')
488
branch, relpath = Branch.open_containing(self.get_readonly_url(''))
489
self.assertEqual('', relpath)
490
branch, relpath = Branch.open_containing(self.get_readonly_url('g/p/q'))
491
self.assertEqual('g/p/q', relpath)
494
class InstrumentedTransaction(object):
497
self.calls.append('finish')
503
class TestDecorator(object):
509
self._calls.append('lr')
511
def lock_write(self):
512
self._calls.append('lw')
515
self._calls.append('ul')
518
def do_with_read(self):
522
def except_with_read(self):
526
def do_with_write(self):
530
def except_with_write(self):
534
class TestDecorators(TestCase):
536
def test_needs_read_lock(self):
537
branch = TestDecorator()
538
self.assertEqual(1, branch.do_with_read())
539
self.assertEqual(['lr', 'ul'], branch._calls)
541
def test_excepts_in_read_lock(self):
542
branch = TestDecorator()
543
self.assertRaises(RuntimeError, branch.except_with_read)
544
self.assertEqual(['lr', 'ul'], branch._calls)
546
def test_needs_write_lock(self):
547
branch = TestDecorator()
548
self.assertEqual(2, branch.do_with_write())
549
self.assertEqual(['lw', 'ul'], branch._calls)
551
def test_excepts_in_write_lock(self):
552
branch = TestDecorator()
553
self.assertRaises(RuntimeError, branch.except_with_write)
554
self.assertEqual(['lw', 'ul'], branch._calls)
557
class TestBranchPushLocations(TestCaseWithBranch):
559
def test_get_push_location_unset(self):
560
self.assertEqual(None, self.get_branch().get_push_location())
562
def test_get_push_location_exact(self):
563
from bzrlib.config import (locations_config_filename,
564
ensure_config_dir_exists)
565
ensure_config_dir_exists()
566
fn = locations_config_filename()
567
print >> open(fn, 'wt'), ("[%s]\n"
568
"push_location=foo" %
569
self.get_branch().base[:-1])
570
self.assertEqual("foo", self.get_branch().get_push_location())
572
def test_set_push_location(self):
573
branch = self.get_branch()
574
branch.set_push_location('foo')
575
self.assertEqual('foo', branch.get_push_location())
578
class TestFormat(TestCaseWithBranch):
579
"""Tests for the format itself."""
581
def test_get_reference(self):
582
"""get_reference on all regular branches should return None."""
583
if not self.branch_format.is_supported():
584
# unsupported formats are not loopback testable
585
# because the default open will not open them and
586
# they may not be initializable.
588
made_branch = self.make_branch('.')
589
self.assertEqual(None,
590
made_branch._format.get_reference(made_branch.bzrdir))
592
def test_format_initialize_find_open(self):
593
# loopback test to check the current format initializes to itself.
594
if not self.branch_format.is_supported():
595
# unsupported formats are not loopback testable
596
# because the default open will not open them and
597
# they may not be initializable.
599
# supported formats must be able to init and open
600
t = get_transport(self.get_url())
601
readonly_t = get_transport(self.get_readonly_url())
602
made_branch = self.make_branch('.')
603
self.failUnless(isinstance(made_branch, branch.Branch))
605
# find it via bzrdir opening:
606
opened_control = bzrdir.BzrDir.open(readonly_t.base)
607
direct_opened_branch = opened_control.open_branch()
608
self.assertEqual(direct_opened_branch.__class__, made_branch.__class__)
609
self.assertEqual(opened_control, direct_opened_branch.bzrdir)
610
self.failUnless(isinstance(direct_opened_branch._format,
611
self.branch_format.__class__))
613
# find it via Branch.open
614
opened_branch = branch.Branch.open(readonly_t.base)
615
self.failUnless(isinstance(opened_branch, made_branch.__class__))
616
self.assertEqual(made_branch._format.__class__,
617
opened_branch._format.__class__)
618
# if it has a unique id string, can we probe for it ?
620
self.branch_format.get_format_string()
621
except NotImplementedError:
623
self.assertEqual(self.branch_format,
624
opened_control.find_branch_format())
627
class TestBound(TestCaseWithBranch):
629
def test_bind_unbind(self):
630
branch = self.make_branch('1')
631
branch2 = self.make_branch('2')
634
except errors.UpgradeRequired:
635
raise TestSkipped('Format does not support binding')
636
self.assertTrue(branch.unbind())
637
self.assertFalse(branch.unbind())
638
self.assertIs(None, branch.get_bound_location())
640
def test_old_bound_location(self):
641
branch = self.make_branch('branch1')
643
self.assertIs(None, branch.get_old_bound_location())
644
except errors.UpgradeRequired:
645
raise TestSkipped('Format does not store old bound locations')
646
branch2 = self.make_branch('branch2')
648
self.assertIs(None, branch.get_old_bound_location())
650
self.assertContainsRe(branch.get_old_bound_location(), '\/branch2\/$')
653
class TestStrict(TestCaseWithBranch):
655
def test_strict_history(self):
656
tree1 = self.make_branch_and_tree('tree1')
658
tree1.branch.set_append_revisions_only(True)
659
except errors.UpgradeRequired:
660
raise TestSkipped('Format does not support strict history')
661
tree1.commit('empty commit')
662
tree2 = tree1.bzrdir.sprout('tree2').open_workingtree()
663
tree2.commit('empty commit 2')
664
tree1.pull(tree2.branch)
665
tree1.commit('empty commit 3')
666
tree2.commit('empty commit 4')
667
self.assertRaises(errors.DivergedBranches, tree1.pull, tree2.branch)
668
tree2.merge_from_branch(tree1.branch)
669
tree2.commit('empty commit 5')
670
self.assertRaises(errors.AppendRevisionsOnlyViolation, tree1.pull,
672
tree3 = tree1.bzrdir.sprout('tree3').open_workingtree()
673
tree3.merge_from_branch(tree2.branch)
674
tree3.commit('empty commit 6')
675
tree2.pull(tree3.branch)
31
# TODO: rewrite this as a regular unittest, without relying on the displayed output
32
# >>> from bzrlib.commit import commit
33
# >>> bzrlib.trace.silent = True
34
# >>> br1 = ScratchBranch(files=['foo', 'bar'])
37
# >>> commit(br1, "lala!", rev_id="REVISION-ID-1", verbose=False)
38
# >>> br2 = ScratchBranch()
39
# >>> br2.update_revisions(br1)
41
# Added 1 inventories.
43
# >>> br2.revision_history()
45
# >>> br2.update_revisions(br1)
47
# >>> br1.text_store.total_size() == br2.text_store.total_size()