666
494
revision_tree = tree.branch.repository.revision_tree('dull2')
667
495
self.assertEqual('dull', revision_tree.inventory.root.revision)
669
def test_exposed_versioned_files_are_marked_dirty(self):
670
format = bzrdir.BzrDirMetaFormat1()
671
format.repository_format = knitrepo.RepositoryFormatKnit3()
672
repo = self.make_repository('.', format=format)
674
inv = repo.get_inventory_weave()
676
self.assertRaises(errors.OutSideTransaction,
677
inv.add_lines, 'foo', [], [])
680
class TestWithBrokenRepo(TestCaseWithTransport):
681
"""These tests seem to be more appropriate as interface tests?"""
683
def make_broken_repository(self):
684
# XXX: This function is borrowed from Aaron's "Reconcile can fix bad
685
# parent references" branch which is due to land in bzr.dev soon. Once
686
# it does, this duplication should be removed.
687
repo = self.make_repository('broken-repo')
691
cleanups.append(repo.unlock)
692
repo.start_write_group()
693
cleanups.append(repo.commit_write_group)
694
# make rev1a: A well-formed revision, containing 'file1'
695
inv = inventory.Inventory(revision_id='rev1a')
696
inv.root.revision = 'rev1a'
697
self.add_file(repo, inv, 'file1', 'rev1a', [])
698
repo.add_inventory('rev1a', inv, [])
699
revision = _mod_revision.Revision('rev1a',
700
committer='jrandom@example.com', timestamp=0,
701
inventory_sha1='', timezone=0, message='foo', parent_ids=[])
702
repo.add_revision('rev1a',revision, inv)
704
# make rev1b, which has no Revision, but has an Inventory, and
706
inv = inventory.Inventory(revision_id='rev1b')
707
inv.root.revision = 'rev1b'
708
self.add_file(repo, inv, 'file1', 'rev1b', [])
709
repo.add_inventory('rev1b', inv, [])
711
# make rev2, with file1 and file2
713
# file1 has 'rev1b' as an ancestor, even though this is not
714
# mentioned by 'rev1a', making it an unreferenced ancestor
715
inv = inventory.Inventory()
716
self.add_file(repo, inv, 'file1', 'rev2', ['rev1a', 'rev1b'])
717
self.add_file(repo, inv, 'file2', 'rev2', [])
718
self.add_revision(repo, 'rev2', inv, ['rev1a'])
720
# make ghost revision rev1c
721
inv = inventory.Inventory()
722
self.add_file(repo, inv, 'file2', 'rev1c', [])
724
# make rev3 with file2
725
# file2 refers to 'rev1c', which is a ghost in this repository, so
726
# file2 cannot have rev1c as its ancestor.
727
inv = inventory.Inventory()
728
self.add_file(repo, inv, 'file2', 'rev3', ['rev1c'])
729
self.add_revision(repo, 'rev3', inv, ['rev1c'])
732
for cleanup in reversed(cleanups):
735
def add_revision(self, repo, revision_id, inv, parent_ids):
736
inv.revision_id = revision_id
737
inv.root.revision = revision_id
738
repo.add_inventory(revision_id, inv, parent_ids)
739
revision = _mod_revision.Revision(revision_id,
740
committer='jrandom@example.com', timestamp=0, inventory_sha1='',
741
timezone=0, message='foo', parent_ids=parent_ids)
742
repo.add_revision(revision_id,revision, inv)
744
def add_file(self, repo, inv, filename, revision, parents):
745
file_id = filename + '-id'
746
entry = inventory.InventoryFile(file_id, filename, 'TREE_ROOT')
747
entry.revision = revision
750
vf = repo.weave_store.get_weave_or_empty(file_id,
751
repo.get_transaction())
752
vf.add_lines(revision, parents, ['line\n'])
754
def test_insert_from_broken_repo(self):
755
"""Inserting a data stream from a broken repository won't silently
756
corrupt the target repository.
758
broken_repo = self.make_broken_repository()
759
empty_repo = self.make_repository('empty-repo')
760
stream = broken_repo.get_data_stream(['rev1a', 'rev2', 'rev3'])
761
empty_repo.lock_write()
762
self.addCleanup(empty_repo.unlock)
763
empty_repo.start_write_group()
766
errors.KnitCorrupt, empty_repo.insert_data_stream, stream)
768
empty_repo.abort_write_group()
771
class TestKnitPackNoSubtrees(TestCaseWithTransport):
773
def get_format(self):
774
return bzrdir.format_registry.make_bzrdir('pack-0.92')
776
def test_disk_layout(self):
777
format = self.get_format()
778
repo = self.make_repository('.', format=format)
779
# in case of side effects of locking.
782
t = repo.bzrdir.get_repository_transport(None)
784
# XXX: no locks left when unlocked at the moment
785
# self.assertEqualDiff('', t.get('lock').read())
786
self.check_databases(t)
788
def check_format(self, t):
789
self.assertEqualDiff(
790
"Bazaar pack repository format 1 (needs bzr 0.92)\n",
791
t.get('format').read())
793
def assertHasKndx(self, t, knit_name):
794
"""Assert that knit_name exists on t."""
795
self.assertEqualDiff('# bzr knit index 8\n',
796
t.get(knit_name + '.kndx').read())
798
def assertHasNoKndx(self, t, knit_name):
799
"""Assert that knit_name has no index on t."""
800
self.assertFalse(t.has(knit_name + '.kndx'))
802
def assertHasNoKnit(self, t, knit_name):
803
"""Assert that knit_name exists on t."""
805
self.assertFalse(t.has(knit_name + '.knit'))
807
def check_databases(self, t):
808
"""check knit content for a repository."""
809
# check conversion worked
810
self.assertHasNoKndx(t, 'inventory')
811
self.assertHasNoKnit(t, 'inventory')
812
self.assertHasNoKndx(t, 'revisions')
813
self.assertHasNoKnit(t, 'revisions')
814
self.assertHasNoKndx(t, 'signatures')
815
self.assertHasNoKnit(t, 'signatures')
816
self.assertFalse(t.has('knits'))
817
# revision-indexes file-container directory
819
list(GraphIndex(t, 'pack-names', None).iter_all_entries()))
820
self.assertTrue(S_ISDIR(t.stat('packs').st_mode))
821
self.assertTrue(S_ISDIR(t.stat('upload').st_mode))
822
self.assertTrue(S_ISDIR(t.stat('indices').st_mode))
823
self.assertTrue(S_ISDIR(t.stat('obsolete_packs').st_mode))
825
def test_shared_disk_layout(self):
826
format = self.get_format()
827
repo = self.make_repository('.', shared=True, format=format)
829
t = repo.bzrdir.get_repository_transport(None)
831
# XXX: no locks left when unlocked at the moment
832
# self.assertEqualDiff('', t.get('lock').read())
833
# We should have a 'shared-storage' marker file.
834
self.assertEqualDiff('', t.get('shared-storage').read())
835
self.check_databases(t)
837
def test_shared_no_tree_disk_layout(self):
838
format = self.get_format()
839
repo = self.make_repository('.', shared=True, format=format)
840
repo.set_make_working_trees(False)
842
t = repo.bzrdir.get_repository_transport(None)
844
# XXX: no locks left when unlocked at the moment
845
# self.assertEqualDiff('', t.get('lock').read())
846
# We should have a 'shared-storage' marker file.
847
self.assertEqualDiff('', t.get('shared-storage').read())
848
# We should have a marker for the no-working-trees flag.
849
self.assertEqualDiff('', t.get('no-working-trees').read())
850
# The marker should go when we toggle the setting.
851
repo.set_make_working_trees(True)
852
self.assertFalse(t.has('no-working-trees'))
853
self.check_databases(t)
855
def test_adding_revision_creates_pack_indices(self):
856
format = self.get_format()
857
tree = self.make_branch_and_tree('.', format=format)
858
trans = tree.branch.repository.bzrdir.get_repository_transport(None)
860
list(GraphIndex(trans, 'pack-names', None).iter_all_entries()))
861
tree.commit('foobarbaz')
862
index = GraphIndex(trans, 'pack-names', None)
863
index_nodes = list(index.iter_all_entries())
864
self.assertEqual(1, len(index_nodes))
865
node = index_nodes[0]
867
# the pack sizes should be listed in the index
869
sizes = [int(digits) for digits in pack_value.split(' ')]
870
for size, suffix in zip(sizes, ['.rix', '.iix', '.tix', '.six']):
871
stat = trans.stat('indices/%s%s' % (name, suffix))
872
self.assertEqual(size, stat.st_size)
874
def test_pulling_nothing_leads_to_no_new_names(self):
875
format = self.get_format()
876
tree1 = self.make_branch_and_tree('1', format=format)
877
tree2 = self.make_branch_and_tree('2', format=format)
878
tree1.branch.repository.fetch(tree2.branch.repository)
879
trans = tree1.branch.repository.bzrdir.get_repository_transport(None)
881
list(GraphIndex(trans, 'pack-names', None).iter_all_entries()))
883
def test_commit_across_pack_shape_boundary_autopacks(self):
884
format = self.get_format()
885
tree = self.make_branch_and_tree('.', format=format)
886
trans = tree.branch.repository.bzrdir.get_repository_transport(None)
887
# This test could be a little cheaper by replacing the packs
888
# attribute on the repository to allow a different pack distribution
889
# and max packs policy - so we are checking the policy is honoured
890
# in the test. But for now 11 commits is not a big deal in a single
893
tree.commit('commit %s' % x)
894
# there should be 9 packs:
895
index = GraphIndex(trans, 'pack-names', None)
896
self.assertEqual(9, len(list(index.iter_all_entries())))
897
# insert some files in obsolete_packs which should be removed by pack.
898
trans.put_bytes('obsolete_packs/foo', '123')
899
trans.put_bytes('obsolete_packs/bar', '321')
900
# committing one more should coalesce to 1 of 10.
901
tree.commit('commit triggering pack')
902
index = GraphIndex(trans, 'pack-names', None)
903
self.assertEqual(1, len(list(index.iter_all_entries())))
904
# packing should not damage data
905
tree = tree.bzrdir.open_workingtree()
906
check_result = tree.branch.repository.check(
907
[tree.branch.last_revision()])
908
# We should have 50 (10x5) files in the obsolete_packs directory.
909
obsolete_files = list(trans.list_dir('obsolete_packs'))
910
self.assertFalse('foo' in obsolete_files)
911
self.assertFalse('bar' in obsolete_files)
912
self.assertEqual(50, len(obsolete_files))
913
# XXX: Todo check packs obsoleted correctly - old packs and indices
914
# in the obsolete_packs directory.
915
large_pack_name = list(index.iter_all_entries())[0][1][0]
916
# finally, committing again should not touch the large pack.
917
tree.commit('commit not triggering pack')
918
index = GraphIndex(trans, 'pack-names', None)
919
self.assertEqual(2, len(list(index.iter_all_entries())))
920
pack_names = [node[1][0] for node in index.iter_all_entries()]
921
self.assertTrue(large_pack_name in pack_names)
923
def test_pack_after_two_commits_packs_everything(self):
924
format = self.get_format()
925
tree = self.make_branch_and_tree('.', format=format)
926
trans = tree.branch.repository.bzrdir.get_repository_transport(None)
928
tree.commit('more work')
929
tree.branch.repository.pack()
930
# there should be 1 pack:
931
index = GraphIndex(trans, 'pack-names', None)
932
self.assertEqual(1, len(list(index.iter_all_entries())))
933
self.assertEqual(2, len(tree.branch.repository.all_revision_ids()))
935
def test_pack_layout(self):
936
format = self.get_format()
937
tree = self.make_branch_and_tree('.', format=format)
938
trans = tree.branch.repository.bzrdir.get_repository_transport(None)
939
tree.commit('start', rev_id='1')
940
tree.commit('more work', rev_id='2')
941
tree.branch.repository.pack()
943
self.addCleanup(tree.unlock)
944
pack = tree.branch.repository._pack_collection.get_pack_by_name(
945
tree.branch.repository._pack_collection.names()[0])
946
# revision access tends to be tip->ancestor, so ordering that way on
947
# disk is a good idea.
948
for _1, key, val, refs in pack.revision_index.iter_all_entries():
950
pos_1 = int(val[1:].split()[0])
952
pos_2 = int(val[1:].split()[0])
953
self.assertTrue(pos_2 < pos_1)
955
def test_pack_repositories_support_multiple_write_locks(self):
956
format = self.get_format()
957
self.make_repository('.', shared=True, format=format)
958
r1 = repository.Repository.open('.')
959
r2 = repository.Repository.open('.')
961
self.addCleanup(r1.unlock)
965
def _add_text(self, repo, fileid):
966
"""Add a text to the repository within a write group."""
967
vf =repo.weave_store.get_weave(fileid, repo.get_transaction())
968
vf.add_lines('samplerev+' + fileid, [], [])
970
def test_concurrent_writers_merge_new_packs(self):
971
format = self.get_format()
972
self.make_repository('.', shared=True, format=format)
973
r1 = repository.Repository.open('.')
974
r2 = repository.Repository.open('.')
977
# access enough data to load the names list
978
list(r1.all_revision_ids())
981
# access enough data to load the names list
982
list(r2.all_revision_ids())
983
r1.start_write_group()
985
r2.start_write_group()
987
self._add_text(r1, 'fileidr1')
988
self._add_text(r2, 'fileidr2')
990
r2.abort_write_group()
993
r1.abort_write_group()
995
# both r1 and r2 have open write groups with data in them
996
# created while the other's write group was open.
997
# Commit both which requires a merge to the pack-names.
999
r1.commit_write_group()
1001
r1.abort_write_group()
1002
r2.abort_write_group()
1004
r2.commit_write_group()
1005
# tell r1 to reload from disk
1006
r1._pack_collection.reset()
1007
# Now both repositories should know about both names
1008
r1._pack_collection.ensure_loaded()
1009
r2._pack_collection.ensure_loaded()
1010
self.assertEqual(r1._pack_collection.names(), r2._pack_collection.names())
1011
self.assertEqual(2, len(r1._pack_collection.names()))
1017
def test_concurrent_writer_second_preserves_dropping_a_pack(self):
1018
format = self.get_format()
1019
self.make_repository('.', shared=True, format=format)
1020
r1 = repository.Repository.open('.')
1021
r2 = repository.Repository.open('.')
1022
# add a pack to drop
1025
r1.start_write_group()
1027
self._add_text(r1, 'fileidr1')
1029
r1.abort_write_group()
1032
r1.commit_write_group()
1033
r1._pack_collection.ensure_loaded()
1034
name_to_drop = r1._pack_collection.all_packs()[0].name
1039
# access enough data to load the names list
1040
list(r1.all_revision_ids())
1043
# access enough data to load the names list
1044
list(r2.all_revision_ids())
1045
r1._pack_collection.ensure_loaded()
1047
r2.start_write_group()
1049
# in r1, drop the pack
1050
r1._pack_collection._remove_pack_from_memory(
1051
r1._pack_collection.get_pack_by_name(name_to_drop))
1053
self._add_text(r2, 'fileidr2')
1055
r2.abort_write_group()
1058
r1._pack_collection.reset()
1060
# r1 has a changed names list, and r2 an open write groups with
1062
# save r1, and then commit the r2 write group, which requires a
1063
# merge to the pack-names, which should not reinstate
1066
r1._pack_collection._save_pack_names()
1067
r1._pack_collection.reset()
1069
r2.abort_write_group()
1072
r2.commit_write_group()
1074
r2.abort_write_group()
1076
# Now both repositories should now about just one name.
1077
r1._pack_collection.ensure_loaded()
1078
r2._pack_collection.ensure_loaded()
1079
self.assertEqual(r1._pack_collection.names(), r2._pack_collection.names())
1080
self.assertEqual(1, len(r1._pack_collection.names()))
1081
self.assertFalse(name_to_drop in r1._pack_collection.names())
1087
def test_lock_write_does_not_physically_lock(self):
1088
repo = self.make_repository('.', format=self.get_format())
1090
self.addCleanup(repo.unlock)
1091
self.assertFalse(repo.get_physical_lock_status())
1093
def prepare_for_break_lock(self):
1094
# Setup the global ui factory state so that a break-lock method call
1095
# will find usable input in the input stream.
1096
old_factory = bzrlib.ui.ui_factory
1097
def restoreFactory():
1098
bzrlib.ui.ui_factory = old_factory
1099
self.addCleanup(restoreFactory)
1100
bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
1101
bzrlib.ui.ui_factory.stdin = StringIO("y\n")
1103
def test_break_lock_breaks_physical_lock(self):
1104
repo = self.make_repository('.', format=self.get_format())
1105
repo._pack_collection.lock_names()
1106
repo2 = repository.Repository.open('.')
1107
self.assertTrue(repo.get_physical_lock_status())
1108
self.prepare_for_break_lock()
1110
self.assertFalse(repo.get_physical_lock_status())
1112
def test_broken_physical_locks_error_on__unlock_names_lock(self):
1113
repo = self.make_repository('.', format=self.get_format())
1114
repo._pack_collection.lock_names()
1115
self.assertTrue(repo.get_physical_lock_status())
1116
repo2 = repository.Repository.open('.')
1117
self.prepare_for_break_lock()
1119
self.assertRaises(errors.LockBroken, repo._pack_collection._unlock_names)
1121
def test_fetch_without_find_ghosts_ignores_ghosts(self):
1122
# we want two repositories at this point:
1123
# one with a revision that is a ghost in the other
1125
# 'ghost' is present in has_ghost, 'ghost' is absent in 'missing_ghost'.
1126
# 'references' is present in both repositories, and 'tip' is present
1127
# just in has_ghost.
1128
# has_ghost missing_ghost
1129
#------------------------------
1131
# 'references' 'references'
1133
# In this test we fetch 'tip' which should not fetch 'ghost'
1134
has_ghost = self.make_repository('has_ghost', format=self.get_format())
1135
missing_ghost = self.make_repository('missing_ghost',
1136
format=self.get_format())
1138
def add_commit(repo, revision_id, parent_ids):
1140
repo.start_write_group()
1141
inv = inventory.Inventory(revision_id=revision_id)
1142
inv.root.revision = revision_id
1143
root_id = inv.root.file_id
1144
sha1 = repo.add_inventory(revision_id, inv, [])
1145
vf = repo.weave_store.get_weave_or_empty(root_id,
1146
repo.get_transaction())
1147
vf.add_lines(revision_id, [], [])
1148
rev = bzrlib.revision.Revision(timestamp=0,
1150
committer="Foo Bar <foo@example.com>",
1152
inventory_sha1=sha1,
1153
revision_id=revision_id)
1154
rev.parent_ids = parent_ids
1155
repo.add_revision(revision_id, rev)
1156
repo.commit_write_group()
1158
add_commit(has_ghost, 'ghost', [])
1159
add_commit(has_ghost, 'references', ['ghost'])
1160
add_commit(missing_ghost, 'references', ['ghost'])
1161
add_commit(has_ghost, 'tip', ['references'])
1162
missing_ghost.fetch(has_ghost, 'tip')
1163
# missing ghost now has tip and not ghost.
1164
rev = missing_ghost.get_revision('tip')
1165
inv = missing_ghost.get_inventory('tip')
1166
self.assertRaises(errors.NoSuchRevision,
1167
missing_ghost.get_revision, 'ghost')
1168
self.assertRaises(errors.RevisionNotPresent,
1169
missing_ghost.get_inventory, 'ghost')
1172
class TestKnitPackSubtrees(TestKnitPackNoSubtrees):
1174
def get_format(self):
1175
return bzrdir.format_registry.make_bzrdir(
1176
'pack-0.92-subtree')
1178
def check_format(self, t):
1179
self.assertEqualDiff(
1180
"Bazaar pack repository format 1 with subtree support (needs bzr 0.92)\n",
1181
t.get('format').read())
1184
class TestRepositoryPackCollection(TestCaseWithTransport):
1186
def get_format(self):
1187
return bzrdir.format_registry.make_bzrdir('pack-0.92')
1189
def test__max_pack_count(self):
1190
"""The maximum pack count is a function of the number of revisions."""
1191
format = self.get_format()
1192
repo = self.make_repository('.', format=format)
1193
packs = repo._pack_collection
1194
# no revisions - one pack, so that we can have a revision free repo
1195
# without it blowing up
1196
self.assertEqual(1, packs._max_pack_count(0))
1197
# after that the sum of the digits, - check the first 1-9
1198
self.assertEqual(1, packs._max_pack_count(1))
1199
self.assertEqual(2, packs._max_pack_count(2))
1200
self.assertEqual(3, packs._max_pack_count(3))
1201
self.assertEqual(4, packs._max_pack_count(4))
1202
self.assertEqual(5, packs._max_pack_count(5))
1203
self.assertEqual(6, packs._max_pack_count(6))
1204
self.assertEqual(7, packs._max_pack_count(7))
1205
self.assertEqual(8, packs._max_pack_count(8))
1206
self.assertEqual(9, packs._max_pack_count(9))
1207
# check the boundary cases with two digits for the next decade
1208
self.assertEqual(1, packs._max_pack_count(10))
1209
self.assertEqual(2, packs._max_pack_count(11))
1210
self.assertEqual(10, packs._max_pack_count(19))
1211
self.assertEqual(2, packs._max_pack_count(20))
1212
self.assertEqual(3, packs._max_pack_count(21))
1213
# check some arbitrary big numbers
1214
self.assertEqual(25, packs._max_pack_count(112894))
1216
def test_pack_distribution_zero(self):
1217
format = self.get_format()
1218
repo = self.make_repository('.', format=format)
1219
packs = repo._pack_collection
1220
self.assertEqual([0], packs.pack_distribution(0))
1222
def test_ensure_loaded_unlocked(self):
1223
format = self.get_format()
1224
repo = self.make_repository('.', format=format)
1225
self.assertRaises(errors.ObjectNotLocked,
1226
repo._pack_collection.ensure_loaded)
1228
def test_pack_distribution_one_to_nine(self):
1229
format = self.get_format()
1230
repo = self.make_repository('.', format=format)
1231
packs = repo._pack_collection
1232
self.assertEqual([1],
1233
packs.pack_distribution(1))
1234
self.assertEqual([1, 1],
1235
packs.pack_distribution(2))
1236
self.assertEqual([1, 1, 1],
1237
packs.pack_distribution(3))
1238
self.assertEqual([1, 1, 1, 1],
1239
packs.pack_distribution(4))
1240
self.assertEqual([1, 1, 1, 1, 1],
1241
packs.pack_distribution(5))
1242
self.assertEqual([1, 1, 1, 1, 1, 1],
1243
packs.pack_distribution(6))
1244
self.assertEqual([1, 1, 1, 1, 1, 1, 1],
1245
packs.pack_distribution(7))
1246
self.assertEqual([1, 1, 1, 1, 1, 1, 1, 1],
1247
packs.pack_distribution(8))
1248
self.assertEqual([1, 1, 1, 1, 1, 1, 1, 1, 1],
1249
packs.pack_distribution(9))
1251
def test_pack_distribution_stable_at_boundaries(self):
1252
"""When there are multi-rev packs the counts are stable."""
1253
format = self.get_format()
1254
repo = self.make_repository('.', format=format)
1255
packs = repo._pack_collection
1257
self.assertEqual([10], packs.pack_distribution(10))
1258
self.assertEqual([10, 1], packs.pack_distribution(11))
1259
self.assertEqual([10, 10], packs.pack_distribution(20))
1260
self.assertEqual([10, 10, 1], packs.pack_distribution(21))
1262
self.assertEqual([100], packs.pack_distribution(100))
1263
self.assertEqual([100, 1], packs.pack_distribution(101))
1264
self.assertEqual([100, 10, 1], packs.pack_distribution(111))
1265
self.assertEqual([100, 100], packs.pack_distribution(200))
1266
self.assertEqual([100, 100, 1], packs.pack_distribution(201))
1267
self.assertEqual([100, 100, 10, 1], packs.pack_distribution(211))
1269
def test_plan_pack_operations_2009_revisions_skip_all_packs(self):
1270
format = self.get_format()
1271
repo = self.make_repository('.', format=format)
1272
packs = repo._pack_collection
1273
existing_packs = [(2000, "big"), (9, "medium")]
1274
# rev count - 2009 -> 2x1000 + 9x1
1275
pack_operations = packs.plan_autopack_combinations(
1276
existing_packs, [1000, 1000, 1, 1, 1, 1, 1, 1, 1, 1, 1])
1277
self.assertEqual([], pack_operations)
1279
def test_plan_pack_operations_2010_revisions_skip_all_packs(self):
1280
format = self.get_format()
1281
repo = self.make_repository('.', format=format)
1282
packs = repo._pack_collection
1283
existing_packs = [(2000, "big"), (9, "medium"), (1, "single")]
1284
# rev count - 2010 -> 2x1000 + 1x10
1285
pack_operations = packs.plan_autopack_combinations(
1286
existing_packs, [1000, 1000, 10])
1287
self.assertEqual([], pack_operations)
1289
def test_plan_pack_operations_2010_combines_smallest_two(self):
1290
format = self.get_format()
1291
repo = self.make_repository('.', format=format)
1292
packs = repo._pack_collection
1293
existing_packs = [(1999, "big"), (9, "medium"), (1, "single2"),
1295
# rev count - 2010 -> 2x1000 + 1x10 (3)
1296
pack_operations = packs.plan_autopack_combinations(
1297
existing_packs, [1000, 1000, 10])
1298
self.assertEqual([[2, ["single2", "single1"]], [0, []]], pack_operations)
1300
def test_all_packs_none(self):
1301
format = self.get_format()
1302
tree = self.make_branch_and_tree('.', format=format)
1304
self.addCleanup(tree.unlock)
1305
packs = tree.branch.repository._pack_collection
1306
packs.ensure_loaded()
1307
self.assertEqual([], packs.all_packs())
1309
def test_all_packs_one(self):
1310
format = self.get_format()
1311
tree = self.make_branch_and_tree('.', format=format)
1312
tree.commit('start')
1314
self.addCleanup(tree.unlock)
1315
packs = tree.branch.repository._pack_collection
1316
packs.ensure_loaded()
1318
packs.get_pack_by_name(packs.names()[0])],
1321
def test_all_packs_two(self):
1322
format = self.get_format()
1323
tree = self.make_branch_and_tree('.', format=format)
1324
tree.commit('start')
1325
tree.commit('continue')
1327
self.addCleanup(tree.unlock)
1328
packs = tree.branch.repository._pack_collection
1329
packs.ensure_loaded()
1331
packs.get_pack_by_name(packs.names()[0]),
1332
packs.get_pack_by_name(packs.names()[1]),
1333
], packs.all_packs())
1335
def test_get_pack_by_name(self):
1336
format = self.get_format()
1337
tree = self.make_branch_and_tree('.', format=format)
1338
tree.commit('start')
1340
self.addCleanup(tree.unlock)
1341
packs = tree.branch.repository._pack_collection
1342
packs.ensure_loaded()
1343
name = packs.names()[0]
1344
pack_1 = packs.get_pack_by_name(name)
1345
# the pack should be correctly initialised
1346
rev_index = GraphIndex(packs._index_transport, name + '.rix',
1347
packs._names[name][0])
1348
inv_index = GraphIndex(packs._index_transport, name + '.iix',
1349
packs._names[name][1])
1350
txt_index = GraphIndex(packs._index_transport, name + '.tix',
1351
packs._names[name][2])
1352
sig_index = GraphIndex(packs._index_transport, name + '.six',
1353
packs._names[name][3])
1354
self.assertEqual(pack_repo.ExistingPack(packs._pack_transport,
1355
name, rev_index, inv_index, txt_index, sig_index), pack_1)
1356
# and the same instance should be returned on successive calls.
1357
self.assertTrue(pack_1 is packs.get_pack_by_name(name))
1360
class TestPack(TestCaseWithTransport):
1361
"""Tests for the Pack object."""
1363
def assertCurrentlyEqual(self, left, right):
1364
self.assertTrue(left == right)
1365
self.assertTrue(right == left)
1366
self.assertFalse(left != right)
1367
self.assertFalse(right != left)
1369
def assertCurrentlyNotEqual(self, left, right):
1370
self.assertFalse(left == right)
1371
self.assertFalse(right == left)
1372
self.assertTrue(left != right)
1373
self.assertTrue(right != left)
1375
def test___eq____ne__(self):
1376
left = pack_repo.ExistingPack('', '', '', '', '', '')
1377
right = pack_repo.ExistingPack('', '', '', '', '', '')
1378
self.assertCurrentlyEqual(left, right)
1379
# change all attributes and ensure equality changes as we do.
1380
left.revision_index = 'a'
1381
self.assertCurrentlyNotEqual(left, right)
1382
right.revision_index = 'a'
1383
self.assertCurrentlyEqual(left, right)
1384
left.inventory_index = 'a'
1385
self.assertCurrentlyNotEqual(left, right)
1386
right.inventory_index = 'a'
1387
self.assertCurrentlyEqual(left, right)
1388
left.text_index = 'a'
1389
self.assertCurrentlyNotEqual(left, right)
1390
right.text_index = 'a'
1391
self.assertCurrentlyEqual(left, right)
1392
left.signature_index = 'a'
1393
self.assertCurrentlyNotEqual(left, right)
1394
right.signature_index = 'a'
1395
self.assertCurrentlyEqual(left, right)
1397
self.assertCurrentlyNotEqual(left, right)
1399
self.assertCurrentlyEqual(left, right)
1400
left.transport = 'a'
1401
self.assertCurrentlyNotEqual(left, right)
1402
right.transport = 'a'
1403
self.assertCurrentlyEqual(left, right)
1405
def test_file_name(self):
1406
pack = pack_repo.ExistingPack('', 'a_name', '', '', '', '')
1407
self.assertEqual('a_name.pack', pack.file_name())
1410
class TestNewPack(TestCaseWithTransport):
1411
"""Tests for pack_repo.NewPack."""
1413
def test_new_instance_attributes(self):
1414
upload_transport = self.get_transport('upload')
1415
pack_transport = self.get_transport('pack')
1416
index_transport = self.get_transport('index')
1417
upload_transport.mkdir('.')
1418
pack = pack_repo.NewPack(upload_transport, index_transport,
1420
self.assertIsInstance(pack.revision_index, InMemoryGraphIndex)
1421
self.assertIsInstance(pack.inventory_index, InMemoryGraphIndex)
1422
self.assertIsInstance(pack._hash, type(md5.new()))
1423
self.assertTrue(pack.upload_transport is upload_transport)
1424
self.assertTrue(pack.index_transport is index_transport)
1425
self.assertTrue(pack.pack_transport is pack_transport)
1426
self.assertEqual(None, pack.index_sizes)
1427
self.assertEqual(20, len(pack.random_name))
1428
self.assertIsInstance(pack.random_name, str)
1429
self.assertIsInstance(pack.start_time, float)
1432
class TestPacker(TestCaseWithTransport):
1433
"""Tests for the packs repository Packer class."""
1435
# To date, this class has been factored out and nothing new added to it;
1436
# thus there are not yet any tests.
1439
class TestInterDifferingSerializer(TestCaseWithTransport):
1441
def test_progress_bar(self):
1442
tree = self.make_branch_and_tree('tree')
1443
tree.commit('rev1', rev_id='rev-1')
1444
tree.commit('rev2', rev_id='rev-2')
1445
tree.commit('rev3', rev_id='rev-3')
1446
repo = self.make_repository('repo')
1447
inter_repo = repository.InterDifferingSerializer(
1448
tree.branch.repository, repo)
1449
pb = progress.InstrumentedProgress(to_file=StringIO())
1450
pb.never_throttle = True
1451
inter_repo.fetch('rev-1', pb)
1452
self.assertEqual('Transferring revisions', pb.last_msg)
1453
self.assertEqual(1, pb.last_cnt)
1454
self.assertEqual(1, pb.last_total)
1455
inter_repo.fetch('rev-3', pb)
1456
self.assertEqual(2, pb.last_cnt)
1457
self.assertEqual(2, pb.last_total)