651
651
def test_suspend_write_group(self):
652
652
self.vfs_transport_factory = memory.MemoryServer
653
repo = self.make_repository('repo')
653
repo = self.make_repository('repo', format=self.get_format())
654
654
token = repo.lock_write()
655
655
self.addCleanup(repo.unlock)
656
656
repo.start_write_group()
657
657
repo.texts.add_lines(('file-id', 'revid'), (), ['lines'])
658
658
wg_tokens = repo.suspend_write_group()
659
659
expected_pack_name = wg_tokens[0] + '.pack'
660
expected_names = [wg_tokens[0] + ext for ext in
661
('.rix', '.iix', '.tix', '.six')]
662
if repo.chk_bytes is not None:
663
expected_names.append(wg_tokens[0] + '.cix')
664
expected_names.append(expected_pack_name)
660
665
upload_transport = repo._pack_collection._upload_transport
661
666
limbo_files = upload_transport.list_dir('')
662
self.assertTrue(expected_pack_name in limbo_files, limbo_files)
667
self.assertEqual(sorted(expected_names), sorted(limbo_files))
663
668
md5 = osutils.md5(upload_transport.get_bytes(expected_pack_name))
664
669
self.assertEqual(wg_tokens[0], md5.hexdigest())
671
def test_resume_chk_bytes(self):
672
self.vfs_transport_factory = memory.MemoryServer
673
repo = self.make_repository('repo', format=self.get_format())
674
if repo.chk_bytes is None:
675
raise TestNotApplicable('no chk_bytes for this repository')
676
token = repo.lock_write()
677
self.addCleanup(repo.unlock)
678
repo.start_write_group()
679
text = 'a bit of text\n'
680
key = ('sha1:' + osutils.sha_string(text),)
681
repo.chk_bytes.add_lines(key, (), [text])
682
wg_tokens = repo.suspend_write_group()
683
same_repo = repo.bzrdir.open_repository()
684
same_repo.lock_write()
685
self.addCleanup(same_repo.unlock)
686
same_repo.resume_write_group(wg_tokens)
687
self.assertEqual([key], list(same_repo.chk_bytes.keys()))
689
text, same_repo.chk_bytes.get_record_stream([key],
690
'unordered', True).next().get_bytes_as('fulltext'))
691
same_repo.abort_write_group()
692
self.assertEqual([], list(same_repo.chk_bytes.keys()))
666
694
def test_resume_write_group_then_abort(self):
667
695
# Create a repo, start a write group, insert some data, suspend.
668
696
self.vfs_transport_factory = memory.MemoryServer
669
repo = self.make_repository('repo')
697
repo = self.make_repository('repo', format=self.get_format())
670
698
token = repo.lock_write()
671
699
self.addCleanup(repo.unlock)
672
700
repo.start_write_group()
685
713
self.assertEqual(
686
714
[], same_repo._pack_collection._pack_transport.list_dir(''))
716
def test_commit_resumed_write_group(self):
717
self.vfs_transport_factory = memory.MemoryServer
718
repo = self.make_repository('repo', format=self.get_format())
719
token = repo.lock_write()
720
self.addCleanup(repo.unlock)
721
repo.start_write_group()
722
text_key = ('file-id', 'revid')
723
repo.texts.add_lines(text_key, (), ['lines'])
724
wg_tokens = repo.suspend_write_group()
725
# Get a fresh repository object for the repo on the filesystem.
726
same_repo = repo.bzrdir.open_repository()
728
same_repo.lock_write()
729
self.addCleanup(same_repo.unlock)
730
same_repo.resume_write_group(wg_tokens)
731
same_repo.commit_write_group()
732
expected_pack_name = wg_tokens[0] + '.pack'
733
expected_names = [wg_tokens[0] + ext for ext in
734
('.rix', '.iix', '.tix', '.six')]
735
if repo.chk_bytes is not None:
736
expected_names.append(wg_tokens[0] + '.cix')
738
[], same_repo._pack_collection._upload_transport.list_dir(''))
739
index_names = repo._pack_collection._index_transport.list_dir('')
740
self.assertEqual(sorted(expected_names), sorted(index_names))
741
pack_names = repo._pack_collection._pack_transport.list_dir('')
742
self.assertEqual([expected_pack_name], pack_names)
688
744
def test_resume_malformed_token(self):
689
745
self.vfs_transport_factory = memory.MemoryServer
690
746
# Make a repository with a suspended write group
691
repo = self.make_repository('repo')
747
repo = self.make_repository('repo', format=self.get_format())
692
748
token = repo.lock_write()
693
749
self.addCleanup(repo.unlock)
694
750
repo.start_write_group()
732
788
# can only stack on repositories that have compatible internal
734
790
if getattr(repo._format, 'supports_tree_reference', False):
791
matching_format_name = 'pack-0.92-subtree'
735
793
if repo._format.supports_chks:
736
794
matching_format_name = 'development6-rich-root'
738
matching_format_name = 'pack-0.92-subtree'
740
matching_format_name = 'rich-root-pack'
796
matching_format_name = 'rich-root-pack'
741
797
mismatching_format_name = 'pack-0.92'
743
799
# We don't have a non-rich-root CHK format.
763
819
if getattr(repo._format, 'supports_tree_reference', False):
764
820
# can only stack on repositories that have compatible internal
766
if repo._format.supports_chks:
767
# No CHK subtree formats in bzr.dev, so this doesn't execute.
768
matching_format_name = 'development6-subtree'
770
matching_format_name = 'pack-0.92-subtree'
822
matching_format_name = 'pack-0.92-subtree'
771
823
mismatching_format_name = 'rich-root-pack'
773
825
if repo.supports_rich_root():
774
matching_format_name = 'rich-root-pack'
826
if repo._format.supports_chks:
827
matching_format_name = 'development6-rich-root'
829
matching_format_name = 'rich-root-pack'
775
830
mismatching_format_name = 'pack-0.92-subtree'
777
832
raise TestNotApplicable('No formats use non-v5 serializer'
844
899
self.assertTrue(large_pack_name in pack_names)
902
class TestKeyDependencies(TestCaseWithTransport):
904
def get_format(self):
905
return bzrdir.format_registry.make_bzrdir(self.format_name)
907
def create_source_and_target(self):
908
builder = self.make_branch_builder('source', format=self.get_format())
909
builder.start_series()
910
builder.build_snapshot('A-id', None, [
911
('add', ('', 'root-id', 'directory', None))])
912
builder.build_snapshot('B-id', ['A-id', 'ghost-id'], [])
913
builder.finish_series()
914
repo = self.make_repository('target')
915
b = builder.get_branch()
917
self.addCleanup(b.unlock)
919
self.addCleanup(repo.unlock)
920
return b.repository, repo
922
def test_key_dependencies_cleared_on_abort(self):
923
source_repo, target_repo = self.create_source_and_target()
924
target_repo.start_write_group()
926
stream = source_repo.revisions.get_record_stream([('B-id',)],
928
target_repo.revisions.insert_record_stream(stream)
929
key_refs = target_repo.revisions._index._key_dependencies
930
self.assertEqual([('B-id',)], sorted(key_refs.get_referrers()))
932
target_repo.abort_write_group()
933
self.assertEqual([], sorted(key_refs.get_referrers()))
935
def test_key_dependencies_cleared_on_suspend(self):
936
source_repo, target_repo = self.create_source_and_target()
937
target_repo.start_write_group()
939
stream = source_repo.revisions.get_record_stream([('B-id',)],
941
target_repo.revisions.insert_record_stream(stream)
942
key_refs = target_repo.revisions._index._key_dependencies
943
self.assertEqual([('B-id',)], sorted(key_refs.get_referrers()))
945
target_repo.suspend_write_group()
946
self.assertEqual([], sorted(key_refs.get_referrers()))
948
def test_key_dependencies_cleared_on_commit(self):
949
source_repo, target_repo = self.create_source_and_target()
950
target_repo.start_write_group()
952
stream = source_repo.revisions.get_record_stream([('B-id',)],
954
target_repo.revisions.insert_record_stream(stream)
955
key_refs = target_repo.revisions._index._key_dependencies
956
self.assertEqual([('B-id',)], sorted(key_refs.get_referrers()))
958
target_repo.commit_write_group()
959
self.assertEqual([], sorted(key_refs.get_referrers()))
847
962
class TestSmartServerAutopack(TestCaseWithTransport):
931
1046
dict(format_name='development6-rich-root',
932
1047
format_string='Bazaar development format - group compression '
933
1048
'and chk inventory (needs bzr.dev from 1.14)\n',
934
format_supports_external_lookups=False,
1049
format_supports_external_lookups=True,
935
1050
index_class=BTreeGraphIndex),
937
1052
# name of the scenario is the format name