162
163
def test_adding_revision_creates_pack_indices(self):
163
164
format = self.get_format()
164
165
tree = self.make_branch_and_tree('.', format=format)
165
trans = tree.branch.repository.controldir.get_repository_transport(None)
166
trans = tree.branch.repository.controldir.get_repository_transport(
166
168
self.assertEqual([],
167
list(self.index_class(trans, 'pack-names', None).iter_all_entries()))
169
list(self.index_class(trans, 'pack-names', None).iter_all_entries()))
168
170
tree.commit('foobarbaz')
169
171
index = self.index_class(trans, 'pack-names', None)
170
172
index_nodes = list(index.iter_all_entries())
183
185
tree1 = self.make_branch_and_tree('1', format=format)
184
186
tree2 = self.make_branch_and_tree('2', format=format)
185
187
tree1.branch.repository.fetch(tree2.branch.repository)
186
trans = tree1.branch.repository.controldir.get_repository_transport(None)
188
trans = tree1.branch.repository.controldir.get_repository_transport(
187
190
self.assertEqual([],
188
list(self.index_class(trans, 'pack-names', None).iter_all_entries()))
191
list(self.index_class(trans, 'pack-names', None).iter_all_entries()))
190
193
def test_commit_across_pack_shape_boundary_autopacks(self):
191
194
format = self.get_format()
192
195
tree = self.make_branch_and_tree('.', format=format)
193
trans = tree.branch.repository.controldir.get_repository_transport(None)
196
trans = tree.branch.repository.controldir.get_repository_transport(
194
198
# This test could be a little cheaper by replacing the packs
195
199
# attribute on the repository to allow a different pack distribution
196
200
# and max packs policy - so we are checking the policy is honoured
212
216
tree = tree.controldir.open_workingtree()
213
217
check_result = tree.branch.repository.check(
214
218
[tree.branch.last_revision()])
215
nb_files = 5 # .pack, .rix, .iix, .tix, .six
219
nb_files = 5 # .pack, .rix, .iix, .tix, .six
216
220
if tree.branch.repository._format.supports_chks:
218
222
# We should have 10 x nb_files files in the obsolete_packs directory.
219
223
obsolete_files = list(trans.list_dir('obsolete_packs'))
220
224
self.assertFalse('foo' in obsolete_files)
249
253
inv.root.revision = revid
250
254
repo.texts.add_lines((inv.root.file_id, revid), [], [])
251
255
rev = _mod_revision.Revision(timestamp=0, timezone=None,
252
committer="Foo Bar <foo@example.com>", message="Message",
256
committer="Foo Bar <foo@example.com>", message="Message",
254
258
rev.parent_ids = ()
255
259
repo.add_revision(revid, rev, inv=inv)
296
300
combined_indices.difference([combined_index]),
297
301
combined_index._sibling_indices)
303
def test_pack_with_signatures(self):
304
format = self.get_format()
305
tree = self.make_branch_and_tree('.', format=format)
306
trans = tree.branch.repository.controldir.get_repository_transport(
308
revid1 = tree.commit('start')
309
revid2 = tree.commit('more work')
310
strategy = gpg.LoopbackGPGStrategy(None)
311
repo = tree.branch.repository
312
self.addCleanup(repo.lock_write().unlock)
313
repo.start_write_group()
314
repo.sign_revision(revid1, strategy)
315
repo.commit_write_group()
316
repo.start_write_group()
317
repo.sign_revision(revid2, strategy)
318
repo.commit_write_group()
319
tree.branch.repository.pack()
320
# there should be 1 pack:
321
index = self.index_class(trans, 'pack-names', None)
322
self.assertEqual(1, len(list(index.iter_all_entries())))
323
self.assertEqual(2, len(tree.branch.repository.all_revision_ids()))
299
325
def test_pack_after_two_commits_packs_everything(self):
300
326
format = self.get_format()
301
327
tree = self.make_branch_and_tree('.', format=format)
302
trans = tree.branch.repository.controldir.get_repository_transport(None)
328
trans = tree.branch.repository.controldir.get_repository_transport(
303
330
tree.commit('start')
304
331
tree.commit('more work')
305
332
tree.branch.repository.pack()
389
417
def _add_text(self, repo, fileid):
390
418
"""Add a text to the repository within a write group."""
391
repo.texts.add_lines((fileid, b'samplerev+'+fileid), [],
392
[b'smaplerev+'+fileid])
419
repo.texts.add_lines((fileid, b'samplerev+' + fileid), [],
420
[b'smaplerev+' + fileid])
394
422
def test_concurrent_writers_merge_new_packs(self):
395
423
format = self.get_format()
631
663
# 'references' is present in both repositories, and 'tip' is present
632
664
# just in has_ghost.
633
665
# has_ghost missing_ghost
634
#------------------------------
666
# ------------------------------
636
668
# 'references' 'references'
638
670
# In this test we fetch 'tip' which should not fetch 'ghost'
639
671
has_ghost = self.make_repository('has_ghost', format=self.get_format())
640
672
missing_ghost = self.make_repository('missing_ghost',
641
format=self.get_format())
673
format=self.get_format())
643
675
def add_commit(repo, revision_id, parent_ids):
644
676
repo.lock_write()
667
699
rev = missing_ghost.get_revision(b'tip')
668
700
inv = missing_ghost.get_inventory(b'tip')
669
701
self.assertRaises(errors.NoSuchRevision,
670
missing_ghost.get_revision, b'ghost')
702
missing_ghost.get_revision, b'ghost')
671
703
self.assertRaises(errors.NoSuchRevision,
672
missing_ghost.get_inventory, b'ghost')
704
missing_ghost.get_inventory, b'ghost')
674
706
def make_write_ready_repo(self):
675
707
format = self.get_format()
713
745
def test_supports_external_lookups(self):
714
746
repo = self.make_repository('.', format=self.get_format())
715
747
self.assertEqual(self.format_supports_external_lookups,
716
repo._format.supports_external_lookups)
748
repo._format.supports_external_lookups)
718
750
def _lock_write(self, write_lockable):
719
751
"""Lock write_lockable, add a cleanup and return the result.
721
753
:param write_lockable: An object with a lock_write method.
722
754
:return: The result of write_lockable.lock_write().
766
798
wg_tokens = repo.suspend_write_group()
767
799
expected_pack_name = wg_tokens[0] + '.pack'
768
800
expected_names = [wg_tokens[0] + ext for ext in
769
('.rix', '.iix', '.tix', '.six')]
801
('.rix', '.iix', '.tix', '.six')]
770
802
if repo.chk_bytes is not None:
771
803
expected_names.append(wg_tokens[0] + '.cix')
772
804
expected_names.append(expected_pack_name)
909
941
repo.add_fallback_repository(base)
910
942
# you can't stack on something with incompatible data
911
943
bad_repo = self.make_repository('mismatch',
912
format=mismatching_format_name)
944
format=mismatching_format_name)
913
945
e = self.assertRaises(errors.IncompatibleRepositories,
914
repo.add_fallback_repository, bad_repo)
946
repo.add_fallback_repository, bad_repo)
915
947
self.assertContainsRe(str(e),
916
r'(?m)KnitPackRepository.*/mismatch/.*\nis not compatible with\n'
917
r'.*Repository.*/repo/.*\n'
918
r'different rich-root support')
948
r'(?m)KnitPackRepository.*/mismatch/.*\nis not compatible with\n'
949
r'.*Repository.*/repo/.*\n'
950
r'different rich-root support')
920
952
def test_stack_checks_serializers_compatibility(self):
921
953
repo = self.make_repository('repo', format=self.get_format())
933
965
mismatching_format_name = 'pack-0.92-subtree'
935
967
raise TestNotApplicable('No formats use non-v5 serializer'
936
' without having rich-root also set')
968
' without having rich-root also set')
937
969
base = self.make_repository('base', format=matching_format_name)
938
970
repo.add_fallback_repository(base)
939
971
# you can't stack on something with incompatible data
940
972
bad_repo = self.make_repository('mismatch',
941
format=mismatching_format_name)
973
format=mismatching_format_name)
942
974
e = self.assertRaises(errors.IncompatibleRepositories,
943
repo.add_fallback_repository, bad_repo)
975
repo.add_fallback_repository, bad_repo)
944
976
self.assertContainsRe(str(e),
945
r'(?m)KnitPackRepository.*/mismatch/.*\nis not compatible with\n'
946
r'.*Repository.*/repo/.*\n'
947
r'different serializers')
977
r'(?m)KnitPackRepository.*/mismatch/.*\nis not compatible with\n'
978
r'.*Repository.*/repo/.*\n'
979
r'different serializers')
949
981
def test_adding_pack_does_not_record_pack_names_from_other_repositories(self):
950
982
base = self.make_branch_and_tree('base', format=self.get_format())
951
983
base.commit('foo')
952
referencing = self.make_branch_and_tree('repo', format=self.get_format())
953
referencing.branch.repository.add_fallback_repository(base.branch.repository)
984
referencing = self.make_branch_and_tree(
985
'repo', format=self.get_format())
986
referencing.branch.repository.add_fallback_repository(
987
base.branch.repository)
954
988
local_tree = referencing.branch.create_checkout('local')
955
989
local_tree.commit('bar')
956
990
new_instance = referencing.controldir.open_repository()
985
1020
tree = tree.controldir.open_workingtree()
986
1021
check_result = tree.branch.repository.check(
987
1022
[tree.branch.last_revision()])
988
nb_files = 5 # .pack, .rix, .iix, .tix, .six
1023
nb_files = 5 # .pack, .rix, .iix, .tix, .six
989
1024
if tree.branch.repository._format.supports_chks:
1025
nb_files += 1 # .cix
991
1026
# We should have 10 x nb_files files in the obsolete_packs directory.
992
1027
obsolete_files = list(trans.list_dir('obsolete_packs'))
993
1028
self.assertFalse('foo' in obsolete_files)
1113
1149
self.hpss_calls = []
1114
1150
tree.commit('commit triggering pack')
1115
1151
tree.branch.push(remote_branch)
1116
autopack_calls = len([call for call in self.hpss_calls if call ==
1117
b'PackRepository.autopack'])
1152
autopack_calls = len([call for call in self.hpss_calls if call
1153
== b'PackRepository.autopack'])
1118
1154
streaming_calls = len([call for call in self.hpss_calls if call in
1119
(b'Repository.insert_stream', b'Repository.insert_stream_1.19')])
1155
(b'Repository.insert_stream', b'Repository.insert_stream_1.19')])
1120
1156
if autopack_calls:
1121
1157
# Non streaming server
1122
1158
self.assertEqual(1, autopack_calls)
1134
1170
# these give the bzrdir canned format name, and the repository on-disk
1135
1171
# format string
1136
1172
scenarios_params = [
1137
dict(format_name='pack-0.92',
1138
format_string="Bazaar pack repository format 1 (needs bzr 0.92)\n",
1139
format_supports_external_lookups=False,
1140
index_class=GraphIndex),
1141
dict(format_name='pack-0.92-subtree',
1142
format_string="Bazaar pack repository format 1 "
1143
"with subtree support (needs bzr 0.92)\n",
1144
format_supports_external_lookups=False,
1145
index_class=GraphIndex),
1146
dict(format_name='1.6',
1147
format_string="Bazaar RepositoryFormatKnitPack5 (bzr 1.6)\n",
1148
format_supports_external_lookups=True,
1149
index_class=GraphIndex),
1150
dict(format_name='1.6.1-rich-root',
1151
format_string="Bazaar RepositoryFormatKnitPack5RichRoot "
1153
format_supports_external_lookups=True,
1154
index_class=GraphIndex),
1155
dict(format_name='1.9',
1156
format_string="Bazaar RepositoryFormatKnitPack6 (bzr 1.9)\n",
1157
format_supports_external_lookups=True,
1158
index_class=BTreeGraphIndex),
1159
dict(format_name='1.9-rich-root',
1160
format_string="Bazaar RepositoryFormatKnitPack6RichRoot "
1162
format_supports_external_lookups=True,
1163
index_class=BTreeGraphIndex),
1164
dict(format_name='2a',
1165
format_string="Bazaar repository format 2a "
1166
"(needs bzr 1.16 or later)\n",
1167
format_supports_external_lookups=True,
1168
index_class=BTreeGraphIndex),
1173
dict(format_name='pack-0.92',
1174
format_string="Bazaar pack repository format 1 (needs bzr 0.92)\n",
1175
format_supports_external_lookups=False,
1176
index_class=GraphIndex),
1177
dict(format_name='pack-0.92-subtree',
1178
format_string="Bazaar pack repository format 1 "
1179
"with subtree support (needs bzr 0.92)\n",
1180
format_supports_external_lookups=False,
1181
index_class=GraphIndex),
1182
dict(format_name='1.6',
1183
format_string="Bazaar RepositoryFormatKnitPack5 (bzr 1.6)\n",
1184
format_supports_external_lookups=True,
1185
index_class=GraphIndex),
1186
dict(format_name='1.6.1-rich-root',
1187
format_string="Bazaar RepositoryFormatKnitPack5RichRoot "
1189
format_supports_external_lookups=True,
1190
index_class=GraphIndex),
1191
dict(format_name='1.9',
1192
format_string="Bazaar RepositoryFormatKnitPack6 (bzr 1.9)\n",
1193
format_supports_external_lookups=True,
1194
index_class=BTreeGraphIndex),
1195
dict(format_name='1.9-rich-root',
1196
format_string="Bazaar RepositoryFormatKnitPack6RichRoot "
1198
format_supports_external_lookups=True,
1199
index_class=BTreeGraphIndex),
1200
dict(format_name='2a',
1201
format_string="Bazaar repository format 2a "
1202
"(needs bzr 1.16 or later)\n",
1203
format_supports_external_lookups=True,
1204
index_class=BTreeGraphIndex),
1170
1206
# name of the scenario is the format name
1171
1207
scenarios = [(s['format_name'], s) for s in scenarios_params]
1172
1208
return tests.multiply_tests(basic_tests, scenarios, loader.suiteClass())