541
544
repo_b).__class__)
547
class TestInterRemoteToOther(TestCaseWithTransport):
549
def make_remote_repository(self, path, backing_format=None):
550
"""Make a RemoteRepository object backed by a real repository that will
551
be created at the given path."""
552
self.make_repository(path, format=backing_format)
553
smart_server = server.SmartTCPServer_for_testing()
555
remote_transport = get_transport(smart_server.get_url()).clone(path)
556
self.addCleanup(smart_server.tearDown)
557
remote_bzrdir = bzrdir.BzrDir.open_from_transport(remote_transport)
558
remote_repo = remote_bzrdir.open_repository()
561
def test_is_compatible_same_format(self):
562
"""InterRemoteToOther is compatible with a remote repository and a
563
second repository that have the same format."""
564
local_repo = self.make_repository('local')
565
remote_repo = self.make_remote_repository('remote')
566
is_compatible = repository.InterRemoteToOther.is_compatible
568
is_compatible(remote_repo, local_repo),
569
"InterRemoteToOther(%r, %r) is false" % (remote_repo, local_repo))
571
def test_is_incompatible_different_format(self):
572
local_repo = self.make_repository('local', 'dirstate')
573
remote_repo = self.make_remote_repository('a', 'dirstate-with-subtree')
574
is_compatible = repository.InterRemoteToOther.is_compatible
576
is_compatible(remote_repo, local_repo),
577
"InterRemoteToOther(%r, %r) is true" % (local_repo, remote_repo))
579
def test_is_incompatible_different_format_both_remote(self):
580
remote_repo_a = self.make_remote_repository(
581
'a', 'dirstate-with-subtree')
582
remote_repo_b = self.make_remote_repository('b', 'dirstate')
583
is_compatible = repository.InterRemoteToOther.is_compatible
585
is_compatible(remote_repo_a, remote_repo_b),
586
"InterRemoteToOther(%r, %r) is true"
587
% (remote_repo_a, remote_repo_b))
544
590
class TestRepositoryConverter(TestCaseWithTransport):
546
592
def test_convert_empty(self):
597
643
self.assertRaises(errors.OutSideTransaction,
598
644
inv.add_lines, 'foo', [], [])
647
class TestWithBrokenRepo(TestCaseWithTransport):
649
def make_broken_repository(self):
650
# XXX: This function is borrowed from Aaron's "Reconcile can fix bad
651
# parent references" branch which is due to land in bzr.dev soon. Once
652
# it does, this duplication should be removed.
653
repo = self.make_repository('broken-repo')
657
cleanups.append(repo.unlock)
658
repo.start_write_group()
659
cleanups.append(repo.commit_write_group)
660
# make rev1a: A well-formed revision, containing 'file1'
661
inv = inventory.Inventory(revision_id='rev1a')
662
inv.root.revision = 'rev1a'
663
self.add_file(repo, inv, 'file1', 'rev1a', [])
664
repo.add_inventory('rev1a', inv, [])
665
revision = _mod_revision.Revision('rev1a',
666
committer='jrandom@example.com', timestamp=0,
667
inventory_sha1='', timezone=0, message='foo', parent_ids=[])
668
repo.add_revision('rev1a',revision, inv)
670
# make rev1b, which has no Revision, but has an Inventory, and
672
inv = inventory.Inventory(revision_id='rev1b')
673
inv.root.revision = 'rev1b'
674
self.add_file(repo, inv, 'file1', 'rev1b', [])
675
repo.add_inventory('rev1b', inv, [])
677
# make rev2, with file1 and file2
679
# file1 has 'rev1b' as an ancestor, even though this is not
680
# mentioned by 'rev1a', making it an unreferenced ancestor
681
inv = inventory.Inventory()
682
self.add_file(repo, inv, 'file1', 'rev2', ['rev1a', 'rev1b'])
683
self.add_file(repo, inv, 'file2', 'rev2', [])
684
self.add_revision(repo, 'rev2', inv, ['rev1a'])
686
# make ghost revision rev1c
687
inv = inventory.Inventory()
688
self.add_file(repo, inv, 'file2', 'rev1c', [])
690
# make rev3 with file2
691
# file2 refers to 'rev1c', which is a ghost in this repository, so
692
# file2 cannot have rev1c as its ancestor.
693
inv = inventory.Inventory()
694
self.add_file(repo, inv, 'file2', 'rev3', ['rev1c'])
695
self.add_revision(repo, 'rev3', inv, ['rev1c'])
698
for cleanup in reversed(cleanups):
701
def add_revision(self, repo, revision_id, inv, parent_ids):
702
inv.revision_id = revision_id
703
inv.root.revision = revision_id
704
repo.add_inventory(revision_id, inv, parent_ids)
705
revision = _mod_revision.Revision(revision_id,
706
committer='jrandom@example.com', timestamp=0, inventory_sha1='',
707
timezone=0, message='foo', parent_ids=parent_ids)
708
repo.add_revision(revision_id,revision, inv)
710
def add_file(self, repo, inv, filename, revision, parents):
711
file_id = filename + '-id'
712
entry = inventory.InventoryFile(file_id, filename, 'TREE_ROOT')
713
entry.revision = revision
716
vf = repo.weave_store.get_weave_or_empty(file_id,
717
repo.get_transaction())
718
vf.add_lines(revision, parents, ['line\n'])
720
def test_insert_from_broken_repo(self):
721
"""Inserting a data stream from a broken repository won't silently
722
corrupt the target repository.
724
broken_repo = self.make_broken_repository()
725
empty_repo = self.make_repository('empty-repo')
726
stream = broken_repo.get_data_stream(['rev1a', 'rev2', 'rev3'])
728
errors.KnitCorrupt, empty_repo.insert_data_stream, stream)