114
116
tree_a.add('vla', 'file2')
115
117
tree_a.commit('rev2', rev_id='rev2')
117
delta = tree_a.branch.get_revision_delta(1)
119
delta = self.applyDeprecated(symbol_versioning.deprecated_in(
120
(2, 5, 0)), tree_a.branch.get_revision_delta, 1)
118
121
self.assertIsInstance(delta, _mod_delta.TreeDelta)
119
122
self.assertEqual([('foo', 'file1', 'file')], delta.added)
120
delta = tree_a.branch.get_revision_delta(2)
123
delta = self.applyDeprecated(symbol_versioning.deprecated_in(
124
(2, 5, 0)), tree_a.branch.get_revision_delta, 2)
121
125
self.assertIsInstance(delta, _mod_delta.TreeDelta)
122
126
self.assertEqual([('vla', 'file2', 'file')], delta.added)
245
255
self.get_branch().repository.get_revision,
249
# compare the gpg-to-sign info for a commit with a ghost and
250
# an identical tree without a ghost
251
# fetch missing should rewrite the TOC of weaves to list newly available parents.
253
def test_sign_existing_revision(self):
254
wt = self.make_branch_and_tree('.')
256
wt.commit("base", allow_pointless=True, rev_id='A')
257
from bzrlib.testament import Testament
258
strategy = gpg.LoopbackGPGStrategy(None)
259
branch.repository.lock_write()
260
branch.repository.start_write_group()
261
branch.repository.sign_revision('A', strategy)
262
branch.repository.commit_write_group()
263
branch.repository.unlock()
264
self.assertEqual('-----BEGIN PSEUDO-SIGNED CONTENT-----\n' +
265
Testament.from_revision(branch.repository,
266
'A').as_short_text() +
267
'-----END PSEUDO-SIGNED CONTENT-----\n',
268
branch.repository.get_signature_text('A'))
270
def test_store_signature(self):
271
wt = self.make_branch_and_tree('.')
275
branch.repository.start_write_group()
277
branch.repository.store_revision_signature(
278
gpg.LoopbackGPGStrategy(None), 'FOO', 'A')
280
branch.repository.abort_write_group()
283
branch.repository.commit_write_group()
286
# A signature without a revision should not be accessible.
287
self.assertRaises(errors.NoSuchRevision,
288
branch.repository.has_signature_for_revision_id,
290
wt.commit("base", allow_pointless=True, rev_id='A')
291
self.assertEqual('-----BEGIN PSEUDO-SIGNED CONTENT-----\n'
292
'FOO-----END PSEUDO-SIGNED CONTENT-----\n',
293
branch.repository.get_signature_text('A'))
295
def test_branch_keeps_signatures(self):
296
wt = self.make_branch_and_tree('source')
297
wt.commit('A', allow_pointless=True, rev_id='A')
298
repo = wt.branch.repository
300
repo.start_write_group()
301
repo.sign_revision('A', gpg.LoopbackGPGStrategy(None))
302
repo.commit_write_group()
304
#FIXME: clone should work to urls,
305
# wt.clone should work to disks.
306
self.build_tree(['target/'])
307
d2 = repo.bzrdir.clone(urlutils.local_path_to_url('target'))
308
self.assertEqual(repo.get_signature_text('A'),
309
d2.open_repository().get_signature_text('A'))
311
def test_nicks(self):
312
"""Test explicit and implicit branch nicknames.
258
def test_nicks_bzr(self):
259
"""Test the behaviour of branch nicks specific to bzr branches.
314
261
Nicknames are implicitly the name of the branch's directory, unless an
315
262
explicit nickname is set. That is, an explicit nickname always
316
263
overrides the implicit one.
318
266
t = self.get_transport()
319
267
branch = self.make_branch('bzr.dev')
268
if not isinstance(branch, _mod_branch.BzrBranch):
269
raise tests.TestNotApplicable("not a bzr branch format")
320
270
# The nick will be 'bzr.dev', because there is no explicit nick set.
321
271
self.assertEqual(branch.nick, 'bzr.dev')
322
272
# Move the branch to a different directory, 'bzr.ab'. Now that branch
338
288
branch.nick = u"\u1234"
339
289
self.assertEqual(branch.nick, u"\u1234")
291
def test_nicks(self):
292
"""Test explicit and implicit branch nicknames.
294
A nickname is always available, whether set explicitly or not.
296
t = self.get_transport()
297
branch = self.make_branch('bzr.dev')
298
# An implicit nick name is set; what it is exactly depends on the
300
self.assertIsInstance(branch.nick, basestring)
301
# Set the branch nick explicitly.
302
branch.nick = "Aaron's branch"
303
# Because the nick has been set explicitly, the nick is now always
305
self.assertEqual(branch.nick, "Aaron's branch")
306
branch.nick = u"\u1234"
307
self.assertEqual(branch.nick, u"\u1234")
341
309
def test_commit_nicks(self):
342
310
"""Nicknames are committed to the revision"""
343
311
wt = self.make_branch_and_tree('bzr.dev')
353
321
repo = self.make_repository('.', shared=True)
354
322
except errors.IncompatibleFormat:
356
self.assertEquals(0, len(repo.bzrdir.list_branches()))
324
if repo.bzrdir._format.colocated_branches:
325
raise tests.TestNotApplicable(
326
"control dir does not support colocated branches")
327
self.assertEqual(0, len(repo.bzrdir.list_branches()))
328
if not self.bzrdir_format.colocated_branches:
329
raise tests.TestNotApplicable("control dir format does not support "
330
"colocated branches")
358
332
child_branch1 = self.branch_format.initialize(repo.bzrdir,
360
except (errors.UninitializableFormat, errors.NoColocatedBranchSupport):
334
except errors.UninitializableFormat:
361
335
# branch references are not default init'able and
362
336
# not all bzrdirs support colocated branches.
364
self.assertEquals(1, len(repo.bzrdir.list_branches()))
338
self.assertEqual(1, len(repo.bzrdir.list_branches()))
365
339
self.branch_format.initialize(repo.bzrdir, name='branch2')
366
self.assertEquals(2, len(repo.bzrdir.list_branches()))
340
self.assertEqual(2, len(repo.bzrdir.list_branches()))
342
def test_create_append_revisions_only(self):
344
repo = self.make_repository('.', shared=True)
345
except errors.IncompatibleFormat:
347
for val in (True, False):
349
branch = self.branch_format.initialize(repo.bzrdir,
350
append_revisions_only=True)
351
except (errors.UninitializableFormat, errors.UpgradeRequired):
352
# branch references are not default init'able and
353
# not all branches support append_revisions_only
355
self.assertEqual(True, branch.get_append_revisions_only())
356
repo.bzrdir.destroy_branch()
358
def test_get_set_append_revisions_only(self):
359
branch = self.make_branch('.')
360
if branch._format.supports_set_append_revisions_only():
361
branch.set_append_revisions_only(True)
362
self.assertTrue(branch.get_append_revisions_only())
363
branch.set_append_revisions_only(False)
364
self.assertFalse(branch.get_append_revisions_only())
366
self.assertRaises(errors.UpgradeRequired,
367
branch.set_append_revisions_only, True)
368
self.assertFalse(branch.get_append_revisions_only())
368
370
def test_create_open_branch_uses_repository(self):
370
372
repo = self.make_repository('.', shared=True)
371
373
except errors.IncompatibleFormat:
374
raise tests.TestNotApplicable("requires shared repository support")
373
375
child_transport = repo.bzrdir.root_transport.clone('child')
374
376
child_transport.mkdir('.')
375
child_dir = self.bzrdir_format.initialize_on_transport(child_transport)
378
child_dir = self.bzrdir_format.initialize_on_transport(child_transport)
379
except errors.UninitializableFormat:
380
raise tests.TestNotApplicable("control dir format not initializable")
377
382
child_branch = self.branch_format.initialize(child_dir)
378
383
except errors.UninitializableFormat:
401
406
"""Create a fake revision history easily."""
402
407
tree = self.make_branch_and_tree('.')
403
408
rev1 = tree.commit('foo')
404
orig_history = tree.branch.revision_history()
410
self.addCleanup(tree.unlock)
411
graph = tree.branch.repository.get_graph()
413
graph.iter_lefthand_ancestry(
414
tree.branch.last_revision(), [revision.NULL_REVISION]))
405
415
rev2 = tree.commit('bar', allow_pointless=True)
406
416
tree.branch.generate_revision_history(rev1)
407
self.assertEqual(orig_history, tree.branch.revision_history())
417
self.assertEqual(orig_history, list(
418
graph.iter_lefthand_ancestry(
419
tree.branch.last_revision(), [revision.NULL_REVISION])))
409
421
def test_generate_revision_history_NULL_REVISION(self):
410
422
tree = self.make_branch_and_tree('.')
411
423
rev1 = tree.commit('foo')
425
self.addCleanup(tree.unlock)
412
426
tree.branch.generate_revision_history(revision.NULL_REVISION)
413
self.assertEqual([], tree.branch.revision_history())
427
self.assertEqual(revision.NULL_REVISION, tree.branch.last_revision())
415
429
def test_create_checkout(self):
416
430
tree_a = self.make_branch_and_tree('a')
437
451
tree_a = self.make_branch_and_tree('a')
438
452
rev_id = tree_a.commit('put some content in the branch')
439
453
# open the branch via a readonly transport
440
source_branch = _mod_branch.Branch.open(self.get_readonly_url('a'))
454
url = self.get_readonly_url(urlutils.basename(tree_a.branch.base))
455
t = transport.get_transport_from_url(url)
456
if not tree_a.branch.bzrdir._format.supports_transport(t):
457
raise tests.TestNotApplicable("format does not support transport")
458
source_branch = _mod_branch.Branch.open(url)
441
459
# sanity check that the test will be valid
442
460
self.assertRaises((errors.LockError, errors.TransportNotPossible),
443
461
source_branch.lock_write)
449
467
tree_a = self.make_branch_and_tree('a')
450
468
rev_id = tree_a.commit('put some content in the branch')
451
469
# open the branch via a readonly transport
452
source_branch = _mod_branch.Branch.open(self.get_readonly_url('a'))
470
url = self.get_readonly_url(
471
osutils.basename(tree_a.branch.base.rstrip('/')))
472
t = transport.get_transport_from_url(url)
473
if not tree_a.branch.bzrdir._format.supports_transport(t):
474
raise tests.TestNotApplicable("format does not support transport")
475
source_branch = _mod_branch.Branch.open(url)
453
476
# sanity check that the test will be valid
454
477
self.assertRaises((errors.LockError, errors.TransportNotPossible),
455
478
source_branch.lock_write)
456
479
checkout = source_branch.create_checkout('c')
457
480
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
self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
464
br.set_revision_history, ["rev1"])
465
self.assertEquals(br.revision_history(), ["rev1"])
466
self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
467
br.set_revision_history, [])
468
self.assertEquals(br.revision_history(), [])
470
482
def test_heads_to_fetch(self):
471
483
# heads_to_fetch is a method that returns a collection of revids that
472
484
# need to be fetched to copy this branch into another repo. At a
622
643
class TestChildSubmitFormats(per_branch.TestCaseWithBranch):
624
645
def test_get_child_submit_format_default(self):
625
self.assertEqual(None, self.get_branch().get_child_submit_format())
646
submit_format = self.get_branch().get_child_submit_format()
647
self.assertTrue(submit_format is None or
648
isinstance(submit_format, str))
627
650
def test_get_child_submit_format(self):
628
651
branch = self.get_branch()
629
branch.get_config().set_user_option('child_submit_format', '10')
652
branch.get_config_stack().set('child_submit_format', '10')
630
653
branch = self.get_branch()
631
654
self.assertEqual('10', branch.get_child_submit_format())
750
773
self.assertEqual(None, branch.get_master_branch())
752
def test_unlocked_does_not_cache_master_branch(self):
753
"""Unlocked branches do not cache the result of get_master_branch."""
754
master = self.make_branch('master')
755
branch1 = self.make_branch('branch')
758
except errors.UpgradeRequired:
759
raise tests.TestNotApplicable('Format does not support binding')
761
branch2 = branch1.bzrdir.open_branch()
762
self.assertNotEqual(None, branch1.get_master_branch())
763
# Unbind the branch via branch2. branch1 isn't locked so will
764
# immediately return the new value for get_master_branch.
766
self.assertEqual(None, branch1.get_master_branch())
768
775
def test_bind_clears_cached_master_branch(self):
769
776
"""b.bind clears any cached value of b.get_master_branch."""
770
777
master1 = self.make_branch('master1')
835
842
def test_fallbacks_not_opened(self):
836
843
stacked = self.make_branch_with_fallback()
837
844
self.get_transport('').rename('fallback', 'moved')
838
reopened = stacked.bzrdir.open_branch(ignore_fallbacks=True)
845
reopened_dir = controldir.ControlDir.open(stacked.base)
846
reopened = reopened_dir.open_branch(ignore_fallbacks=True)
839
847
self.assertEqual([], reopened.repository._fallback_repositories)
841
849
def test_fallbacks_are_opened(self):
842
850
stacked = self.make_branch_with_fallback()
843
reopened = stacked.bzrdir.open_branch(ignore_fallbacks=False)
851
reopened_dir = controldir.ControlDir.open(stacked.base)
852
reopened = reopened_dir.open_branch(ignore_fallbacks=False)
844
853
self.assertLength(1, reopened.repository._fallback_repositories)
1049
1061
# above the control dir but we might need to relax that?
1050
1062
self.assertEqual(br.control_url.find(br.user_url), 0)
1051
1063
self.assertEqual(br.control_url, br.control_transport.base)
1066
class FakeShelfCreator(object):
1068
def __init__(self, branch):
1069
self.branch = branch
1071
def write_shelf(self, shelf_file, message=None):
1072
tree = self.branch.repository.revision_tree(revision.NULL_REVISION)
1073
with transform.TransformPreview(tree) as tt:
1074
shelf.ShelfCreator._write_shelf(
1075
shelf_file, tt, revision.NULL_REVISION)
1078
@contextlib.contextmanager
1079
def skip_if_storing_uncommitted_unsupported():
1082
except errors.StoringUncommittedNotSupported:
1083
raise tests.TestNotApplicable('Cannot store uncommitted changes.')
1086
class TestUncommittedChanges(per_branch.TestCaseWithBranch):
1088
def bind(self, branch, master):
1091
except errors.UpgradeRequired:
1092
raise tests.TestNotApplicable('Branch cannot be bound.')
1094
def test_store_uncommitted(self):
1095
tree = self.make_branch_and_tree('b')
1096
branch = tree.branch
1097
creator = FakeShelfCreator(branch)
1098
with skip_if_storing_uncommitted_unsupported():
1099
self.assertIs(None, branch.get_unshelver(tree))
1100
branch.store_uncommitted(creator)
1101
self.assertIsNot(None, branch.get_unshelver(tree))
1103
def test_store_uncommitted_bound(self):
1104
tree = self.make_branch_and_tree('b')
1105
branch = tree.branch
1106
master = self.make_branch('master')
1107
self.bind(branch, master)
1108
creator = FakeShelfCreator(tree.branch)
1109
self.assertIs(None, tree.branch.get_unshelver(tree))
1110
self.assertIs(None, master.get_unshelver(tree))
1111
tree.branch.store_uncommitted(creator)
1112
self.assertIsNot(None, master.get_unshelver(tree))
1114
def test_store_uncommitted_already_stored(self):
1115
branch = self.make_branch('b')
1116
with skip_if_storing_uncommitted_unsupported():
1117
branch.store_uncommitted(FakeShelfCreator(branch))
1118
self.assertRaises(errors.ChangesAlreadyStored,
1119
branch.store_uncommitted, FakeShelfCreator(branch))
1121
def test_store_uncommitted_none(self):
1122
branch = self.make_branch('b')
1123
with skip_if_storing_uncommitted_unsupported():
1124
branch.store_uncommitted(FakeShelfCreator(branch))
1125
branch.store_uncommitted(None)
1126
self.assertIs(None, branch.get_unshelver(None))
1128
def test_get_unshelver(self):
1129
tree = self.make_branch_and_tree('tree')
1131
self.build_tree_contents([('tree/file', 'contents1')])
1133
with skip_if_storing_uncommitted_unsupported():
1134
tree.store_uncommitted()
1135
unshelver = tree.branch.get_unshelver(tree)
1136
self.assertIsNot(None, unshelver)
1138
def test_get_unshelver_bound(self):
1139
tree = self.make_branch_and_tree('tree')
1141
self.build_tree_contents([('tree/file', 'contents1')])
1143
with skip_if_storing_uncommitted_unsupported():
1144
tree.store_uncommitted()
1145
branch = self.make_branch('branch')
1146
self.bind(branch, tree.branch)
1147
unshelver = branch.get_unshelver(tree)
1148
self.assertIsNot(None, unshelver)