1
# Copyright (C) 2005, 2006, 2007, 2008 Canonical Ltd
1
# Copyright (C) 2005-2010 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
17
17
"""Tests for branch implementations - tests a branch format."""
22
19
from bzrlib import (
20
branch as _mod_branch,
34
from bzrlib.branch import Branch, needs_read_lock, needs_write_lock
35
from bzrlib.delta import TreeDelta
36
from bzrlib.errors import (FileExists,
39
UninitializableFormat,
42
from bzrlib.osutils import getcwd
43
import bzrlib.revision
44
34
from bzrlib.symbol_versioning import deprecated_in
45
from bzrlib.tests import TestCase, TestCaseWithTransport, TestSkipped
35
from bzrlib.tests import (
46
39
from bzrlib.tests.http_server import HttpServer
47
from bzrlib.tests.per_branch import TestCaseWithBranch
48
from bzrlib.trace import mutter
49
from bzrlib.transport import get_transport
50
from bzrlib.transport.memory import MemoryServer
51
from bzrlib.upgrade import upgrade
52
from bzrlib.workingtree import WorkingTree
55
class TestTestCaseWithBranch(TestCaseWithBranch):
40
from bzrlib.transport import memory
43
class TestTestCaseWithBranch(per_branch.TestCaseWithBranch):
57
45
def test_branch_format_matches_bzrdir_branch_format(self):
58
46
bzrdir_branch_format = self.bzrdir_format.get_branch_format()
65
53
branch._format.__class__)
68
class TestBranch(TestCaseWithBranch):
56
class TestBranch(per_branch.TestCaseWithBranch):
70
58
def test_create_tree_with_merge(self):
71
59
tree = self.create_tree_with_merge()
128
116
tree_a.commit('rev2', rev_id='rev2')
130
118
delta = tree_a.branch.get_revision_delta(1)
131
self.assertIsInstance(delta, TreeDelta)
119
self.assertIsInstance(delta, _mod_delta.TreeDelta)
132
120
self.assertEqual([('foo', 'file1', 'file')], delta.added)
133
121
delta = tree_a.branch.get_revision_delta(2)
134
self.assertIsInstance(delta, TreeDelta)
122
self.assertIsInstance(delta, _mod_delta.TreeDelta)
135
123
self.assertEqual([('vla', 'file2', 'file')], delta.added)
137
125
def get_unbalanced_tree_pair(self):
187
175
def test_clone_branch_nickname(self):
188
176
# test the nick name is preserved always
189
raise TestSkipped('XXX branch cloning is not yet tested.')
177
raise tests.TestSkipped('XXX branch cloning is not yet tested.')
191
179
def test_clone_branch_parent(self):
192
180
# test the parent is preserved always
358
346
explicit nickname is set. That is, an explicit nickname always
359
347
overrides the implicit one.
361
t = get_transport(self.get_url())
349
t = transport.get_transport(self.get_url())
362
350
branch = self.make_branch('bzr.dev')
363
351
# The nick will be 'bzr.dev', because there is no explicit nick set.
364
352
self.assertEqual(branch.nick, 'bzr.dev')
365
353
# Move the branch to a different directory, 'bzr.ab'. Now that branch
366
354
# will report its nick as 'bzr.ab'.
367
355
t.move('bzr.dev', 'bzr.ab')
368
branch = Branch.open(self.get_url('bzr.ab'))
356
branch = _mod_branch.Branch.open(self.get_url('bzr.ab'))
369
357
self.assertEqual(branch.nick, 'bzr.ab')
370
358
# Set the branch nick explicitly. This will ensure there's a branch
371
359
# config file in the branch.
376
364
# "Aaron's branch", regardless of directory name.
377
365
self.assertEqual(branch.nick, "Aaron's branch")
378
366
t.move('bzr.ab', 'integration')
379
branch = Branch.open(self.get_url('integration'))
367
branch = _mod_branch.Branch.open(self.get_url('integration'))
380
368
self.assertEqual(branch.nick, "Aaron's branch")
381
369
branch.nick = u"\u1234"
382
370
self.assertEqual(branch.nick, u"\u1234")
391
379
self.assertEqual(committed.properties["branch-nick"],
392
380
"My happy branch")
382
def test_create_colocated(self):
384
repo = self.make_repository('.', shared=True)
385
except errors.IncompatibleFormat:
387
self.assertEquals(0, len(repo.bzrdir.list_branches()))
389
child_branch1 = self.branch_format.initialize(repo.bzrdir,
391
except (errors.UninitializableFormat, errors.NoColocatedBranchSupport):
392
# branch references are not default init'able and
393
# not all bzrdirs support colocated branches.
395
self.assertEquals(1, len(repo.bzrdir.list_branches()))
396
self.branch_format.initialize(repo.bzrdir, name='branch2')
397
self.assertEquals(2, len(repo.bzrdir.list_branches()))
394
399
def test_create_open_branch_uses_repository(self):
396
401
repo = self.make_repository('.', shared=True)
407
412
self.assertEqual(repo.bzrdir.root_transport.base,
408
413
child_branch.repository.bzrdir.root_transport.base)
409
child_branch = branch.Branch.open(self.get_url('child'))
414
child_branch = _mod_branch.Branch.open(self.get_url('child'))
410
415
self.assertEqual(repo.bzrdir.root_transport.base,
411
416
child_branch.repository.bzrdir.root_transport.base)
435
440
def test_generate_revision_history_NULL_REVISION(self):
436
441
tree = self.make_branch_and_tree('.')
437
442
rev1 = tree.commit('foo')
438
tree.branch.generate_revision_history(bzrlib.revision.NULL_REVISION)
443
tree.branch.generate_revision_history(revision.NULL_REVISION)
439
444
self.assertEqual([], tree.branch.revision_history())
441
446
def test_create_checkout(self):
453
458
self.assertEqual('rev2', branch_a.last_revision())
454
459
self.assertEqual(checkout_c.branch.base, branch_a.base)
457
461
checkout_d = branch_a.create_checkout('d', lightweight=True)
458
462
self.assertEqual('rev2', checkout_d.last_revision())
460
463
checkout_e = branch_a.create_checkout('e')
461
464
self.assertEqual('rev2', checkout_e.last_revision())
465
468
tree_a = self.make_branch_and_tree('a')
466
469
rev_id = tree_a.commit('put some content in the branch')
467
470
# open the branch via a readonly transport
468
source_branch = bzrlib.branch.Branch.open(self.get_readonly_url('a'))
471
source_branch = _mod_branch.Branch.open(self.get_readonly_url('a'))
469
472
# sanity check that the test will be valid
470
473
self.assertRaises((errors.LockError, errors.TransportNotPossible),
471
474
source_branch.lock_write)
477
480
tree_a = self.make_branch_and_tree('a')
478
481
rev_id = tree_a.commit('put some content in the branch')
479
482
# open the branch via a readonly transport
480
source_branch = bzrlib.branch.Branch.open(self.get_readonly_url('a'))
483
source_branch = _mod_branch.Branch.open(self.get_readonly_url('a'))
481
484
# sanity check that the test will be valid
482
485
self.assertRaises((errors.LockError, errors.TransportNotPossible),
483
486
source_branch.lock_write)
494
497
self.assertEquals(br.revision_history(), [])
497
class TestBranchFormat(TestCaseWithBranch):
500
class TestBranchFormat(per_branch.TestCaseWithBranch):
499
502
def test_branch_format_network_name(self):
500
503
br = self.make_branch('.')
511
514
real_branch = br._real_branch
512
515
self.assertEqual(real_branch._format.network_name(), network_name)
514
registry = branch.network_format_registry
517
registry = _mod_branch.network_format_registry
515
518
looked_up_format = registry.get(network_name)
516
519
self.assertEqual(format.__class__, looked_up_format.__class__)
519
class ChrootedTests(TestCaseWithBranch):
522
class ChrootedTests(per_branch.TestCaseWithBranch):
520
523
"""A support class that provides readonly urls outside the local namespace.
522
525
This is done by checking if self.transport_server is a MemoryServer. if it
528
531
super(ChrootedTests, self).setUp()
529
if not self.vfs_transport_factory == MemoryServer:
532
if not self.vfs_transport_factory == memory.MemoryServer:
530
533
self.transport_readonly_server = HttpServer
532
535
def test_open_containing(self):
533
self.assertRaises(NotBranchError, Branch.open_containing,
536
self.assertRaises(errors.NotBranchError,
537
_mod_branch.Branch.open_containing,
534
538
self.get_readonly_url(''))
535
self.assertRaises(NotBranchError, Branch.open_containing,
539
self.assertRaises(errors.NotBranchError,
540
_mod_branch.Branch.open_containing,
536
541
self.get_readonly_url('g/p/q'))
537
542
branch = self.make_branch('.')
538
branch, relpath = Branch.open_containing(self.get_readonly_url(''))
543
branch, relpath = _mod_branch.Branch.open_containing(
544
self.get_readonly_url(''))
539
545
self.assertEqual('', relpath)
540
branch, relpath = Branch.open_containing(self.get_readonly_url('g/p/q'))
546
branch, relpath = _mod_branch.Branch.open_containing(
547
self.get_readonly_url('g/p/q'))
541
548
self.assertEqual('g/p/q', relpath)
564
571
def unlock(self):
565
572
self._calls.append('ul')
574
@_mod_branch.needs_read_lock
568
575
def do_with_read(self):
578
@_mod_branch.needs_read_lock
572
579
def except_with_read(self):
573
580
raise RuntimeError
582
@_mod_branch.needs_write_lock
576
583
def do_with_write(self):
586
@_mod_branch.needs_write_lock
580
587
def except_with_write(self):
581
588
raise RuntimeError
584
class TestDecorators(TestCase):
591
class TestDecorators(tests.TestCase):
586
593
def test_needs_read_lock(self):
587
594
branch = TestDecorator()
604
611
self.assertEqual(['lw', 'ul'], branch._calls)
607
class TestBranchPushLocations(TestCaseWithBranch):
614
class TestBranchPushLocations(per_branch.TestCaseWithBranch):
609
616
def test_get_push_location_unset(self):
610
617
self.assertEqual(None, self.get_branch().get_push_location())
625
632
self.assertEqual('foo', branch.get_push_location())
628
class TestChildSubmitFormats(TestCaseWithBranch):
635
class TestChildSubmitFormats(per_branch.TestCaseWithBranch):
630
637
def test_get_child_submit_format_default(self):
631
638
self.assertEqual(None, self.get_branch().get_child_submit_format())
637
644
self.assertEqual('10', branch.get_child_submit_format())
640
class TestFormat(TestCaseWithBranch):
647
class TestFormat(per_branch.TestCaseWithBranch):
641
648
"""Tests for the format itself."""
643
650
def test_get_reference(self):
677
684
# they may not be initializable.
679
686
# supported formats must be able to init and open
680
t = get_transport(self.get_url())
681
readonly_t = get_transport(self.get_readonly_url())
687
t = transport.get_transport(self.get_url())
688
readonly_t = transport.get_transport(self.get_readonly_url())
682
689
made_branch = self.make_branch('.')
683
self.failUnless(isinstance(made_branch, branch.Branch))
690
self.failUnless(isinstance(made_branch, _mod_branch.Branch))
685
692
# find it via bzrdir opening:
686
693
opened_control = bzrdir.BzrDir.open(readonly_t.base)
691
698
self.branch_format.__class__))
693
700
# find it via Branch.open
694
opened_branch = branch.Branch.open(readonly_t.base)
701
opened_branch = _mod_branch.Branch.open(readonly_t.base)
695
702
self.failUnless(isinstance(opened_branch, made_branch.__class__))
696
703
self.assertEqual(made_branch._format.__class__,
697
704
opened_branch._format.__class__)
704
711
opened_control.find_branch_format())
707
class TestBound(TestCaseWithBranch):
714
class TestBound(per_branch.TestCaseWithBranch):
709
716
def test_bind_unbind(self):
710
717
branch = self.make_branch('1')
742
749
raise tests.TestNotApplicable('Format does not support binding')
745
class TestStrict(TestCaseWithBranch):
752
class TestStrict(per_branch.TestCaseWithBranch):
747
754
def test_strict_history(self):
748
755
tree1 = self.make_branch_and_tree('tree1')
750
757
tree1.branch.set_append_revisions_only(True)
751
758
except errors.UpgradeRequired:
752
raise TestSkipped('Format does not support strict history')
759
raise tests.TestSkipped('Format does not support strict history')
753
760
tree1.commit('empty commit')
754
761
tree2 = tree1.bzrdir.sprout('tree2').open_workingtree()
755
762
tree2.commit('empty commit 2')
789
796
self.assertLength(1, reopened.repository._fallback_repositories)
792
class TestReferenceLocation(TestCaseWithBranch):
799
class TestReferenceLocation(per_branch.TestCaseWithBranch):
794
801
def test_reference_parent(self):
795
802
tree = self.make_branch_and_tree('tree')
797
804
subtree.set_root_id('subtree-id')
799
806
tree.add_reference(subtree)
800
except bzrlib.errors.UnsupportedOperation:
807
except errors.UnsupportedOperation:
801
808
raise tests.TestNotApplicable('Tree cannot hold references.')
802
809
reference_parent = tree.branch.reference_parent('subtree-id',
809
816
subtree.set_root_id('subtree-id')
811
818
tree.add_reference(subtree)
812
except bzrlib.errors.UnsupportedOperation:
819
except errors.UnsupportedOperation:
813
820
raise tests.TestNotApplicable('Tree cannot hold references.')
814
821
reference_parent = tree.branch.reference_parent('subtree-id',
815
822
'subtree', possible_transports=[subtree.bzrdir.root_transport])
818
825
branch = self.make_branch('branch')
820
827
path, loc = branch.get_reference_info('file-id')
821
except bzrlib.errors.UnsupportedOperation:
828
except errors.UnsupportedOperation:
822
829
raise tests.TestNotApplicable('Branch cannot hold references.')
823
830
self.assertIs(None, path)
824
831
self.assertIs(None, loc)
829
836
branch.set_reference_info('file-id', 'path/to/location',
831
except bzrlib.errors.UnsupportedOperation:
838
except errors.UnsupportedOperation:
832
839
raise tests.TestNotApplicable('Branch cannot hold references.')
834
841
def test_set_get_reference_info(self):
837
844
branch.set_reference_info('file-id', 'path/to/file',
838
845
'path/to/location')
839
except bzrlib.errors.UnsupportedOperation:
846
except errors.UnsupportedOperation:
840
847
raise tests.TestNotApplicable('Branch cannot hold references.')
841
848
# Create a new instance to ensure storage is permanent
842
branch = Branch.open('branch')
849
branch = _mod_branch.Branch.open('branch')
843
850
tree_path, branch_location = branch.get_reference_info('file-id')
844
851
self.assertEqual('path/to/location', branch_location)
849
856
branch.set_reference_info('file-id', 'path/to/file',
850
857
'path/to/location')
851
except bzrlib.errors.UnsupportedOperation:
858
except errors.UnsupportedOperation:
852
859
raise tests.TestNotApplicable('Branch cannot hold references.')
853
860
branch.set_reference_info('file-id', None, None)
854
861
tree_path, branch_location = branch.get_reference_info('file-id')
859
866
branch = self.make_branch('branch')
861
868
tree_path, branch_location = branch.get_reference_info('file-id')
862
except bzrlib.errors.UnsupportedOperation:
869
except errors.UnsupportedOperation:
863
870
raise tests.TestNotApplicable('Branch cannot hold references.')
864
871
self.assertIs(None, tree_path)
865
872
self.assertIs(None, branch_location)
871
878
e = self.assertRaises(ValueError, branch.set_reference_info,
872
879
'file-id', 'path', None)
873
except bzrlib.errors.UnsupportedOperation:
880
except errors.UnsupportedOperation:
874
881
raise tests.TestNotApplicable('Branch cannot hold references.')
875
882
self.assertEqual('tree_path must be None when branch_location is'
876
883
' None.', str(e))
886
893
branch.set_reference_info(file_id, 'path/to/file',
887
894
reference_location)
888
except bzrlib.errors.UnsupportedOperation:
895
except errors.UnsupportedOperation:
889
896
raise tests.TestNotApplicable('Branch cannot hold references.')
902
909
branch.set_reference_info('file-id', 'path/to/file',
903
910
'../reference_branch')
904
except bzrlib.errors.UnsupportedOperation:
911
except errors.UnsupportedOperation:
905
912
raise tests.TestNotApplicable('Branch cannot hold references.')
906
913
referenced_branch = self.make_branch('reference_branch')
907
914
parent = branch.reference_parent('file-id', 'path/to/file')