482
627
tree = self.make_branch_and_tree('.', format)
483
628
tree.commit("Dull commit", rev_id="dull")
484
629
revision_tree = tree.branch.repository.revision_tree('dull')
485
self.assertRaises(errors.NoSuchFile, revision_tree.get_file_lines,
486
revision_tree.inventory.root.file_id)
630
revision_tree.lock_read()
632
self.assertRaises(errors.NoSuchFile, revision_tree.get_file_lines,
633
revision_tree.inventory.root.file_id)
635
revision_tree.unlock()
487
636
format = bzrdir.BzrDirMetaFormat1()
488
637
format.repository_format = knitrepo.RepositoryFormatKnit3()
489
638
upgrade.Convert('.', format)
490
639
tree = workingtree.WorkingTree.open('.')
491
640
revision_tree = tree.branch.repository.revision_tree('dull')
492
revision_tree.get_file_lines(revision_tree.inventory.root.file_id)
641
revision_tree.lock_read()
643
revision_tree.get_file_lines(revision_tree.inventory.root.file_id)
645
revision_tree.unlock()
493
646
tree.commit("Another dull commit", rev_id='dull2')
494
647
revision_tree = tree.branch.repository.revision_tree('dull2')
648
revision_tree.lock_read()
649
self.addCleanup(revision_tree.unlock)
495
650
self.assertEqual('dull', revision_tree.inventory.root.revision)
652
def test_supports_external_lookups(self):
653
format = bzrdir.BzrDirMetaFormat1()
654
format.repository_format = knitrepo.RepositoryFormatKnit3()
655
repo = self.make_repository('.', format=format)
656
self.assertFalse(repo._format.supports_external_lookups)
659
class TestWithBrokenRepo(TestCaseWithTransport):
660
"""These tests seem to be more appropriate as interface tests?"""
662
def make_broken_repository(self):
663
# XXX: This function is borrowed from Aaron's "Reconcile can fix bad
664
# parent references" branch which is due to land in bzr.dev soon. Once
665
# it does, this duplication should be removed.
666
repo = self.make_repository('broken-repo')
670
cleanups.append(repo.unlock)
671
repo.start_write_group()
672
cleanups.append(repo.commit_write_group)
673
# make rev1a: A well-formed revision, containing 'file1'
674
inv = inventory.Inventory(revision_id='rev1a')
675
inv.root.revision = 'rev1a'
676
self.add_file(repo, inv, 'file1', 'rev1a', [])
677
repo.add_inventory('rev1a', inv, [])
678
revision = _mod_revision.Revision('rev1a',
679
committer='jrandom@example.com', timestamp=0,
680
inventory_sha1='', timezone=0, message='foo', parent_ids=[])
681
repo.add_revision('rev1a',revision, inv)
683
# make rev1b, which has no Revision, but has an Inventory, and
685
inv = inventory.Inventory(revision_id='rev1b')
686
inv.root.revision = 'rev1b'
687
self.add_file(repo, inv, 'file1', 'rev1b', [])
688
repo.add_inventory('rev1b', inv, [])
690
# make rev2, with file1 and file2
692
# file1 has 'rev1b' as an ancestor, even though this is not
693
# mentioned by 'rev1a', making it an unreferenced ancestor
694
inv = inventory.Inventory()
695
self.add_file(repo, inv, 'file1', 'rev2', ['rev1a', 'rev1b'])
696
self.add_file(repo, inv, 'file2', 'rev2', [])
697
self.add_revision(repo, 'rev2', inv, ['rev1a'])
699
# make ghost revision rev1c
700
inv = inventory.Inventory()
701
self.add_file(repo, inv, 'file2', 'rev1c', [])
703
# make rev3 with file2
704
# file2 refers to 'rev1c', which is a ghost in this repository, so
705
# file2 cannot have rev1c as its ancestor.
706
inv = inventory.Inventory()
707
self.add_file(repo, inv, 'file2', 'rev3', ['rev1c'])
708
self.add_revision(repo, 'rev3', inv, ['rev1c'])
711
for cleanup in reversed(cleanups):
714
def add_revision(self, repo, revision_id, inv, parent_ids):
715
inv.revision_id = revision_id
716
inv.root.revision = revision_id
717
repo.add_inventory(revision_id, inv, parent_ids)
718
revision = _mod_revision.Revision(revision_id,
719
committer='jrandom@example.com', timestamp=0, inventory_sha1='',
720
timezone=0, message='foo', parent_ids=parent_ids)
721
repo.add_revision(revision_id,revision, inv)
723
def add_file(self, repo, inv, filename, revision, parents):
724
file_id = filename + '-id'
725
entry = inventory.InventoryFile(file_id, filename, 'TREE_ROOT')
726
entry.revision = revision
729
text_key = (file_id, revision)
730
parent_keys = [(file_id, parent) for parent in parents]
731
repo.texts.add_lines(text_key, parent_keys, ['line\n'])
733
def test_insert_from_broken_repo(self):
734
"""Inserting a data stream from a broken repository won't silently
735
corrupt the target repository.
737
broken_repo = self.make_broken_repository()
738
empty_repo = self.make_repository('empty-repo')
739
self.assertRaises(errors.RevisionNotPresent, empty_repo.fetch, broken_repo)
742
class TestRepositoryPackCollection(TestCaseWithTransport):
744
def get_format(self):
745
return bzrdir.format_registry.make_bzrdir('pack-0.92')
747
def test__max_pack_count(self):
748
"""The maximum pack count is a function of the number of revisions."""
749
format = self.get_format()
750
repo = self.make_repository('.', format=format)
751
packs = repo._pack_collection
752
# no revisions - one pack, so that we can have a revision free repo
753
# without it blowing up
754
self.assertEqual(1, packs._max_pack_count(0))
755
# after that the sum of the digits, - check the first 1-9
756
self.assertEqual(1, packs._max_pack_count(1))
757
self.assertEqual(2, packs._max_pack_count(2))
758
self.assertEqual(3, packs._max_pack_count(3))
759
self.assertEqual(4, packs._max_pack_count(4))
760
self.assertEqual(5, packs._max_pack_count(5))
761
self.assertEqual(6, packs._max_pack_count(6))
762
self.assertEqual(7, packs._max_pack_count(7))
763
self.assertEqual(8, packs._max_pack_count(8))
764
self.assertEqual(9, packs._max_pack_count(9))
765
# check the boundary cases with two digits for the next decade
766
self.assertEqual(1, packs._max_pack_count(10))
767
self.assertEqual(2, packs._max_pack_count(11))
768
self.assertEqual(10, packs._max_pack_count(19))
769
self.assertEqual(2, packs._max_pack_count(20))
770
self.assertEqual(3, packs._max_pack_count(21))
771
# check some arbitrary big numbers
772
self.assertEqual(25, packs._max_pack_count(112894))
774
def test_pack_distribution_zero(self):
775
format = self.get_format()
776
repo = self.make_repository('.', format=format)
777
packs = repo._pack_collection
778
self.assertEqual([0], packs.pack_distribution(0))
780
def test_ensure_loaded_unlocked(self):
781
format = self.get_format()
782
repo = self.make_repository('.', format=format)
783
self.assertRaises(errors.ObjectNotLocked,
784
repo._pack_collection.ensure_loaded)
786
def test_pack_distribution_one_to_nine(self):
787
format = self.get_format()
788
repo = self.make_repository('.', format=format)
789
packs = repo._pack_collection
790
self.assertEqual([1],
791
packs.pack_distribution(1))
792
self.assertEqual([1, 1],
793
packs.pack_distribution(2))
794
self.assertEqual([1, 1, 1],
795
packs.pack_distribution(3))
796
self.assertEqual([1, 1, 1, 1],
797
packs.pack_distribution(4))
798
self.assertEqual([1, 1, 1, 1, 1],
799
packs.pack_distribution(5))
800
self.assertEqual([1, 1, 1, 1, 1, 1],
801
packs.pack_distribution(6))
802
self.assertEqual([1, 1, 1, 1, 1, 1, 1],
803
packs.pack_distribution(7))
804
self.assertEqual([1, 1, 1, 1, 1, 1, 1, 1],
805
packs.pack_distribution(8))
806
self.assertEqual([1, 1, 1, 1, 1, 1, 1, 1, 1],
807
packs.pack_distribution(9))
809
def test_pack_distribution_stable_at_boundaries(self):
810
"""When there are multi-rev packs the counts are stable."""
811
format = self.get_format()
812
repo = self.make_repository('.', format=format)
813
packs = repo._pack_collection
815
self.assertEqual([10], packs.pack_distribution(10))
816
self.assertEqual([10, 1], packs.pack_distribution(11))
817
self.assertEqual([10, 10], packs.pack_distribution(20))
818
self.assertEqual([10, 10, 1], packs.pack_distribution(21))
820
self.assertEqual([100], packs.pack_distribution(100))
821
self.assertEqual([100, 1], packs.pack_distribution(101))
822
self.assertEqual([100, 10, 1], packs.pack_distribution(111))
823
self.assertEqual([100, 100], packs.pack_distribution(200))
824
self.assertEqual([100, 100, 1], packs.pack_distribution(201))
825
self.assertEqual([100, 100, 10, 1], packs.pack_distribution(211))
827
def test_plan_pack_operations_2009_revisions_skip_all_packs(self):
828
format = self.get_format()
829
repo = self.make_repository('.', format=format)
830
packs = repo._pack_collection
831
existing_packs = [(2000, "big"), (9, "medium")]
832
# rev count - 2009 -> 2x1000 + 9x1
833
pack_operations = packs.plan_autopack_combinations(
834
existing_packs, [1000, 1000, 1, 1, 1, 1, 1, 1, 1, 1, 1])
835
self.assertEqual([], pack_operations)
837
def test_plan_pack_operations_2010_revisions_skip_all_packs(self):
838
format = self.get_format()
839
repo = self.make_repository('.', format=format)
840
packs = repo._pack_collection
841
existing_packs = [(2000, "big"), (9, "medium"), (1, "single")]
842
# rev count - 2010 -> 2x1000 + 1x10
843
pack_operations = packs.plan_autopack_combinations(
844
existing_packs, [1000, 1000, 10])
845
self.assertEqual([], pack_operations)
847
def test_plan_pack_operations_2010_combines_smallest_two(self):
848
format = self.get_format()
849
repo = self.make_repository('.', format=format)
850
packs = repo._pack_collection
851
existing_packs = [(1999, "big"), (9, "medium"), (1, "single2"),
853
# rev count - 2010 -> 2x1000 + 1x10 (3)
854
pack_operations = packs.plan_autopack_combinations(
855
existing_packs, [1000, 1000, 10])
856
self.assertEqual([[2, ["single2", "single1"]], [0, []]], pack_operations)
858
def test_all_packs_none(self):
859
format = self.get_format()
860
tree = self.make_branch_and_tree('.', format=format)
862
self.addCleanup(tree.unlock)
863
packs = tree.branch.repository._pack_collection
864
packs.ensure_loaded()
865
self.assertEqual([], packs.all_packs())
867
def test_all_packs_one(self):
868
format = self.get_format()
869
tree = self.make_branch_and_tree('.', format=format)
872
self.addCleanup(tree.unlock)
873
packs = tree.branch.repository._pack_collection
874
packs.ensure_loaded()
876
packs.get_pack_by_name(packs.names()[0])],
879
def test_all_packs_two(self):
880
format = self.get_format()
881
tree = self.make_branch_and_tree('.', format=format)
883
tree.commit('continue')
885
self.addCleanup(tree.unlock)
886
packs = tree.branch.repository._pack_collection
887
packs.ensure_loaded()
889
packs.get_pack_by_name(packs.names()[0]),
890
packs.get_pack_by_name(packs.names()[1]),
891
], packs.all_packs())
893
def test_get_pack_by_name(self):
894
format = self.get_format()
895
tree = self.make_branch_and_tree('.', format=format)
898
self.addCleanup(tree.unlock)
899
packs = tree.branch.repository._pack_collection
900
packs.ensure_loaded()
901
name = packs.names()[0]
902
pack_1 = packs.get_pack_by_name(name)
903
# the pack should be correctly initialised
904
sizes = packs._names[name]
905
rev_index = GraphIndex(packs._index_transport, name + '.rix', sizes[0])
906
inv_index = GraphIndex(packs._index_transport, name + '.iix', sizes[1])
907
txt_index = GraphIndex(packs._index_transport, name + '.tix', sizes[2])
908
sig_index = GraphIndex(packs._index_transport, name + '.six', sizes[3])
909
self.assertEqual(pack_repo.ExistingPack(packs._pack_transport,
910
name, rev_index, inv_index, txt_index, sig_index), pack_1)
911
# and the same instance should be returned on successive calls.
912
self.assertTrue(pack_1 is packs.get_pack_by_name(name))
915
class TestPack(TestCaseWithTransport):
916
"""Tests for the Pack object."""
918
def assertCurrentlyEqual(self, left, right):
919
self.assertTrue(left == right)
920
self.assertTrue(right == left)
921
self.assertFalse(left != right)
922
self.assertFalse(right != left)
924
def assertCurrentlyNotEqual(self, left, right):
925
self.assertFalse(left == right)
926
self.assertFalse(right == left)
927
self.assertTrue(left != right)
928
self.assertTrue(right != left)
930
def test___eq____ne__(self):
931
left = pack_repo.ExistingPack('', '', '', '', '', '')
932
right = pack_repo.ExistingPack('', '', '', '', '', '')
933
self.assertCurrentlyEqual(left, right)
934
# change all attributes and ensure equality changes as we do.
935
left.revision_index = 'a'
936
self.assertCurrentlyNotEqual(left, right)
937
right.revision_index = 'a'
938
self.assertCurrentlyEqual(left, right)
939
left.inventory_index = 'a'
940
self.assertCurrentlyNotEqual(left, right)
941
right.inventory_index = 'a'
942
self.assertCurrentlyEqual(left, right)
943
left.text_index = 'a'
944
self.assertCurrentlyNotEqual(left, right)
945
right.text_index = 'a'
946
self.assertCurrentlyEqual(left, right)
947
left.signature_index = 'a'
948
self.assertCurrentlyNotEqual(left, right)
949
right.signature_index = 'a'
950
self.assertCurrentlyEqual(left, right)
952
self.assertCurrentlyNotEqual(left, right)
954
self.assertCurrentlyEqual(left, right)
956
self.assertCurrentlyNotEqual(left, right)
957
right.transport = 'a'
958
self.assertCurrentlyEqual(left, right)
960
def test_file_name(self):
961
pack = pack_repo.ExistingPack('', 'a_name', '', '', '', '')
962
self.assertEqual('a_name.pack', pack.file_name())
965
class TestNewPack(TestCaseWithTransport):
966
"""Tests for pack_repo.NewPack."""
968
def test_new_instance_attributes(self):
969
upload_transport = self.get_transport('upload')
970
pack_transport = self.get_transport('pack')
971
index_transport = self.get_transport('index')
972
upload_transport.mkdir('.')
973
pack = pack_repo.NewPack(upload_transport, index_transport,
975
self.assertIsInstance(pack.revision_index, InMemoryGraphIndex)
976
self.assertIsInstance(pack.inventory_index, InMemoryGraphIndex)
977
self.assertIsInstance(pack._hash, type(md5.new()))
978
self.assertTrue(pack.upload_transport is upload_transport)
979
self.assertTrue(pack.index_transport is index_transport)
980
self.assertTrue(pack.pack_transport is pack_transport)
981
self.assertEqual(None, pack.index_sizes)
982
self.assertEqual(20, len(pack.random_name))
983
self.assertIsInstance(pack.random_name, str)
984
self.assertIsInstance(pack.start_time, float)
987
class TestPacker(TestCaseWithTransport):
988
"""Tests for the packs repository Packer class."""
990
# To date, this class has been factored out and nothing new added to it;
991
# thus there are not yet any tests.
994
class TestInterDifferingSerializer(TestCaseWithTransport):
996
def test_progress_bar(self):
997
tree = self.make_branch_and_tree('tree')
998
tree.commit('rev1', rev_id='rev-1')
999
tree.commit('rev2', rev_id='rev-2')
1000
tree.commit('rev3', rev_id='rev-3')
1001
repo = self.make_repository('repo')
1002
inter_repo = repository.InterDifferingSerializer(
1003
tree.branch.repository, repo)
1004
pb = progress.InstrumentedProgress(to_file=StringIO())
1005
pb.never_throttle = True
1006
inter_repo.fetch('rev-1', pb)
1007
self.assertEqual('Transferring revisions', pb.last_msg)
1008
self.assertEqual(1, pb.last_cnt)
1009
self.assertEqual(1, pb.last_total)
1010
inter_repo.fetch('rev-3', pb)
1011
self.assertEqual(2, pb.last_cnt)
1012
self.assertEqual(2, pb.last_total)