116
113
tree_a.add('vla', 'file2')
117
114
tree_a.commit('rev2', rev_id='rev2')
119
delta = tree_a.branch.get_revision_delta(1)
116
delta = self.applyDeprecated(symbol_versioning.deprecated_in(
117
(2, 5, 0)), tree_a.branch.get_revision_delta, 1)
120
118
self.assertIsInstance(delta, _mod_delta.TreeDelta)
121
119
self.assertEqual([('foo', 'file1', 'file')], delta.added)
122
delta = tree_a.branch.get_revision_delta(2)
120
delta = self.applyDeprecated(symbol_versioning.deprecated_in(
121
(2, 5, 0)), tree_a.branch.get_revision_delta, 2)
123
122
self.assertIsInstance(delta, _mod_delta.TreeDelta)
124
123
self.assertEqual([('vla', 'file2', 'file')], delta.added)
247
252
self.get_branch().repository.get_revision,
251
# compare the gpg-to-sign info for a commit with a ghost and
252
# an identical tree without a ghost
253
# fetch missing should rewrite the TOC of weaves to list newly available parents.
255
def test_sign_existing_revision(self):
256
wt = self.make_branch_and_tree('.')
258
wt.commit("base", allow_pointless=True, rev_id='A')
259
from bzrlib.testament import Testament
260
strategy = gpg.LoopbackGPGStrategy(None)
261
branch.repository.lock_write()
262
branch.repository.start_write_group()
263
branch.repository.sign_revision('A', strategy)
264
branch.repository.commit_write_group()
265
branch.repository.unlock()
266
self.assertEqual('-----BEGIN PSEUDO-SIGNED CONTENT-----\n' +
267
Testament.from_revision(branch.repository,
268
'A').as_short_text() +
269
'-----END PSEUDO-SIGNED CONTENT-----\n',
270
branch.repository.get_signature_text('A'))
272
def test_store_signature(self):
273
wt = self.make_branch_and_tree('.')
277
branch.repository.start_write_group()
279
branch.repository.store_revision_signature(
280
gpg.LoopbackGPGStrategy(None), 'FOO', 'A')
282
branch.repository.abort_write_group()
285
branch.repository.commit_write_group()
288
# A signature without a revision should not be accessible.
289
self.assertRaises(errors.NoSuchRevision,
290
branch.repository.has_signature_for_revision_id,
292
wt.commit("base", allow_pointless=True, rev_id='A')
293
self.assertEqual('-----BEGIN PSEUDO-SIGNED CONTENT-----\n'
294
'FOO-----END PSEUDO-SIGNED CONTENT-----\n',
295
branch.repository.get_signature_text('A'))
297
def test_branch_keeps_signatures(self):
298
wt = self.make_branch_and_tree('source')
299
wt.commit('A', allow_pointless=True, rev_id='A')
300
repo = wt.branch.repository
302
repo.start_write_group()
303
repo.sign_revision('A', gpg.LoopbackGPGStrategy(None))
304
repo.commit_write_group()
306
#FIXME: clone should work to urls,
307
# wt.clone should work to disks.
308
self.build_tree(['target/'])
309
d2 = repo.bzrdir.clone(urlutils.local_path_to_url('target'))
310
self.assertEqual(repo.get_signature_text('A'),
311
d2.open_repository().get_signature_text('A'))
313
def test_missing_revisions(self):
314
t1 = self.make_branch_and_tree('b1')
315
rev1 = t1.commit('one')
316
t2 = t1.bzrdir.sprout('b2').open_workingtree()
317
rev2 = t1.commit('two')
318
rev3 = t1.commit('three')
320
self.assertEqual([rev2, rev3],
321
self.applyDeprecated(deprecated_in((1, 6, 0)),
322
t2.branch.missing_revisions, t1.branch))
325
self.applyDeprecated(deprecated_in((1, 6, 0)),
326
t2.branch.missing_revisions, t1.branch, stop_revision=1))
327
self.assertEqual([rev2],
328
self.applyDeprecated(deprecated_in((1, 6, 0)),
329
t2.branch.missing_revisions, t1.branch, stop_revision=2))
330
self.assertEqual([rev2, rev3],
331
self.applyDeprecated(deprecated_in((1, 6, 0)),
332
t2.branch.missing_revisions, t1.branch, stop_revision=3))
334
self.assertRaises(errors.NoSuchRevision,
335
self.applyDeprecated, deprecated_in((1, 6, 0)),
336
t2.branch.missing_revisions, t1.branch, stop_revision=4)
338
rev4 = t2.commit('four')
339
self.assertRaises(errors.DivergedBranches,
340
self.applyDeprecated, deprecated_in((1, 6, 0)),
341
t2.branch.missing_revisions, t1.branch)
343
def test_nicks(self):
344
"""Test explicit and implicit branch nicknames.
255
def test_nicks_bzr(self):
256
"""Test the behaviour of branch nicks specific to bzr branches.
346
258
Nicknames are implicitly the name of the branch's directory, unless an
347
259
explicit nickname is set. That is, an explicit nickname always
348
260
overrides the implicit one.
350
t = transport.get_transport(self.get_url())
263
t = self.get_transport()
351
264
branch = self.make_branch('bzr.dev')
265
if not isinstance(branch, _mod_branch.BzrBranch):
266
raise tests.TestNotApplicable("not a bzr branch format")
352
267
# The nick will be 'bzr.dev', because there is no explicit nick set.
353
268
self.assertEqual(branch.nick, 'bzr.dev')
354
269
# Move the branch to a different directory, 'bzr.ab'. Now that branch
397
330
self.branch_format.initialize(repo.bzrdir, name='branch2')
398
331
self.assertEquals(2, len(repo.bzrdir.list_branches()))
333
def test_create_append_revisions_only(self):
335
repo = self.make_repository('.', shared=True)
336
except errors.IncompatibleFormat:
338
for val in (True, False):
340
branch = self.branch_format.initialize(repo.bzrdir,
341
append_revisions_only=True)
342
except (errors.UninitializableFormat, errors.UpgradeRequired):
343
# branch references are not default init'able and
344
# not all branches support append_revisions_only
346
self.assertEquals(True, branch.get_append_revisions_only())
347
repo.bzrdir.destroy_branch()
349
def test_get_set_append_revisions_only(self):
350
branch = self.make_branch('.')
351
if branch._format.supports_set_append_revisions_only():
352
branch.set_append_revisions_only(True)
353
self.assertTrue(branch.get_append_revisions_only())
354
branch.set_append_revisions_only(False)
355
self.assertFalse(branch.get_append_revisions_only())
357
self.assertRaises(errors.UpgradeRequired,
358
branch.set_append_revisions_only, True)
359
self.assertFalse(branch.get_append_revisions_only())
400
361
def test_create_open_branch_uses_repository(self):
402
363
repo = self.make_repository('.', shared=True)
403
364
except errors.IncompatibleFormat:
365
raise tests.TestNotApplicable("requires shared repository support")
405
366
child_transport = repo.bzrdir.root_transport.clone('child')
406
367
child_transport.mkdir('.')
407
child_dir = self.bzrdir_format.initialize_on_transport(child_transport)
369
child_dir = self.bzrdir_format.initialize_on_transport(child_transport)
370
except errors.UninitializableFormat:
371
raise tests.TestNotApplicable("control dir format not initializable")
409
373
child_branch = self.branch_format.initialize(child_dir)
410
374
except errors.UninitializableFormat:
433
397
"""Create a fake revision history easily."""
434
398
tree = self.make_branch_and_tree('.')
435
399
rev1 = tree.commit('foo')
436
orig_history = tree.branch.revision_history()
401
self.addCleanup(tree.unlock)
402
graph = tree.branch.repository.get_graph()
404
graph.iter_lefthand_ancestry(
405
tree.branch.last_revision(), [revision.NULL_REVISION]))
437
406
rev2 = tree.commit('bar', allow_pointless=True)
438
407
tree.branch.generate_revision_history(rev1)
439
self.assertEqual(orig_history, tree.branch.revision_history())
408
self.assertEqual(orig_history, list(
409
graph.iter_lefthand_ancestry(
410
tree.branch.last_revision(), [revision.NULL_REVISION])))
441
412
def test_generate_revision_history_NULL_REVISION(self):
442
413
tree = self.make_branch_and_tree('.')
443
414
rev1 = tree.commit('foo')
416
self.addCleanup(tree.unlock)
444
417
tree.branch.generate_revision_history(revision.NULL_REVISION)
445
self.assertEqual([], tree.branch.revision_history())
418
self.assertEqual(revision.NULL_REVISION, tree.branch.last_revision())
447
420
def test_create_checkout(self):
448
421
tree_a = self.make_branch_and_tree('a')
492
474
tree = self.make_branch_and_tree('a')
493
475
tree.commit('a commit', rev_id='rev1')
495
br.set_revision_history(["rev1"])
496
self.assertEquals(br.revision_history(), ["rev1"])
497
br.set_revision_history([])
498
self.assertEquals(br.revision_history(), [])
477
self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
478
br.set_revision_history, ["rev1"])
479
self.assertEquals(br.last_revision(), "rev1")
480
self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
481
br.set_revision_history, [])
482
self.assertEquals(br.last_revision(), 'null:')
484
def test_heads_to_fetch(self):
485
# heads_to_fetch is a method that returns a collection of revids that
486
# need to be fetched to copy this branch into another repo. At a
487
# minimum this will include the tip.
488
# (In native formats, this is the tip + tags, but other formats may
489
# have other revs needed)
490
tree = self.make_branch_and_tree('a')
491
tree.commit('first commit', rev_id='rev1')
492
tree.commit('second commit', rev_id='rev2')
493
must_fetch, should_fetch = tree.branch.heads_to_fetch()
494
self.assertTrue('rev2' in must_fetch)
496
def test_heads_to_fetch_not_null_revision(self):
497
# NULL_REVISION does not appear in the result of heads_to_fetch, even
498
# for an empty branch.
499
tree = self.make_branch_and_tree('a')
500
must_fetch, should_fetch = tree.branch.heads_to_fetch()
501
self.assertFalse(revision.NULL_REVISION in must_fetch)
502
self.assertFalse(revision.NULL_REVISION in should_fetch)
501
505
class TestBranchFormat(per_branch.TestCaseWithBranch):
682
697
# they may not be initializable.
684
699
# supported formats must be able to init and open
685
t = transport.get_transport(self.get_url())
686
readonly_t = transport.get_transport(self.get_readonly_url())
700
t = self.get_transport()
701
readonly_t = transport.get_transport_from_url(self.get_readonly_url())
687
702
made_branch = self.make_branch('.')
688
self.failUnless(isinstance(made_branch, _mod_branch.Branch))
703
self.assertIsInstance(made_branch, _mod_branch.Branch)
690
705
# find it via bzrdir opening:
691
706
opened_control = bzrdir.BzrDir.open(readonly_t.base)
692
707
direct_opened_branch = opened_control.open_branch()
693
708
self.assertEqual(direct_opened_branch.__class__, made_branch.__class__)
694
709
self.assertEqual(opened_control, direct_opened_branch.bzrdir)
695
self.failUnless(isinstance(direct_opened_branch._format,
696
self.branch_format.__class__))
710
self.assertIsInstance(direct_opened_branch._format,
711
self.branch_format.__class__)
698
713
# find it via Branch.open
699
714
opened_branch = _mod_branch.Branch.open(readonly_t.base)
700
self.failUnless(isinstance(opened_branch, made_branch.__class__))
715
self.assertIsInstance(opened_branch, made_branch.__class__)
701
716
self.assertEqual(made_branch._format.__class__,
702
717
opened_branch._format.__class__)
703
718
# if it has a unique id string, can we probe for it ?
746
761
except errors.UpgradeRequired:
747
762
raise tests.TestNotApplicable('Format does not support binding')
764
def test_unbind_clears_cached_master_branch(self):
765
"""b.unbind clears any cached value of b.get_master_branch."""
766
master = self.make_branch('master')
767
branch = self.make_branch('branch')
770
except errors.UpgradeRequired:
771
raise tests.TestNotApplicable('Format does not support binding')
772
self.addCleanup(branch.lock_write().unlock)
773
self.assertNotEqual(None, branch.get_master_branch())
775
self.assertEqual(None, branch.get_master_branch())
777
def test_unlocked_does_not_cache_master_branch(self):
778
"""Unlocked branches do not cache the result of get_master_branch."""
779
master = self.make_branch('master')
780
branch1 = self.make_branch('branch')
783
except errors.UpgradeRequired:
784
raise tests.TestNotApplicable('Format does not support binding')
786
branch2 = branch1.bzrdir.open_branch()
787
self.assertNotEqual(None, branch1.get_master_branch())
788
# Unbind the branch via branch2. branch1 isn't locked so will
789
# immediately return the new value for get_master_branch.
791
self.assertEqual(None, branch1.get_master_branch())
793
def test_bind_clears_cached_master_branch(self):
794
"""b.bind clears any cached value of b.get_master_branch."""
795
master1 = self.make_branch('master1')
796
master2 = self.make_branch('master2')
797
branch = self.make_branch('branch')
800
except errors.UpgradeRequired:
801
raise tests.TestNotApplicable('Format does not support binding')
802
self.addCleanup(branch.lock_write().unlock)
803
self.assertNotEqual(None, branch.get_master_branch())
805
self.assertEqual('.', urlutils.relative_url(self.get_url('master2'),
806
branch.get_master_branch().base))
808
def test_set_bound_location_clears_cached_master_branch(self):
809
"""b.set_bound_location clears any cached value of b.get_master_branch.
811
master1 = self.make_branch('master1')
812
master2 = self.make_branch('master2')
813
branch = self.make_branch('branch')
816
except errors.UpgradeRequired:
817
raise tests.TestNotApplicable('Format does not support binding')
818
self.addCleanup(branch.lock_write().unlock)
819
self.assertNotEqual(None, branch.get_master_branch())
820
branch.set_bound_location(self.get_url('master2'))
821
self.assertEqual('.', urlutils.relative_url(self.get_url('master2'),
822
branch.get_master_branch().base))
750
825
class TestStrict(per_branch.TestCaseWithBranch):