1696
1696
self.assertTrue(new_pack.signature_index._optimize_for_size)
1699
class TestGCCHKPacker(TestCaseWithTransport):
1701
def make_abc_branch(self):
1702
builder = self.make_branch_builder('source')
1703
builder.start_series()
1704
builder.build_snapshot('A', None, [
1705
('add', ('', 'root-id', 'directory', None)),
1706
('add', ('file', 'file-id', 'file', 'content\n')),
1708
builder.build_snapshot('B', ['A'], [
1709
('add', ('dir', 'dir-id', 'directory', None))])
1710
builder.build_snapshot('C', ['B'], [
1711
('modify', ('file-id', 'new content\n'))])
1712
builder.finish_series()
1713
return builder.get_branch()
1715
def make_branch_with_disjoint_inventory_and_revision(self):
1716
"""a repo with separate packs for a revisions Revision and Inventory.
1718
There will be one pack file that holds the Revision content, and one
1719
for the Inventory content.
1721
:return: (repository,
1722
pack_name_with_rev_A_Revision,
1723
pack_name_with_rev_A_Inventory,
1724
pack_name_with_rev_C_content)
1726
b_source = self.make_abc_branch()
1727
b_base = b_source.bzrdir.sprout('base', revision_id='A').open_branch()
1728
b_stacked = b_base.bzrdir.sprout('stacked', stacked=True).open_branch()
1729
b_stacked.lock_write()
1730
self.addCleanup(b_stacked.unlock)
1731
b_stacked.fetch(b_source, 'B')
1732
# Now re-open the stacked repo directly (no fallbacks) so that we can
1733
# fill in the A rev.
1734
repo_not_stacked = b_stacked.bzrdir.open_repository()
1735
repo_not_stacked.lock_write()
1736
self.addCleanup(repo_not_stacked.unlock)
1737
# Now we should have a pack file with A's inventory, but not its
1739
self.assertEqual([('A',), ('B',)],
1740
sorted(repo_not_stacked.inventories.keys()))
1741
self.assertEqual([('B',)],
1742
sorted(repo_not_stacked.revisions.keys()))
1743
stacked_pack_names = repo_not_stacked._pack_collection.names()
1744
# We have a couple names here, figure out which has A's inventory
1745
for name in stacked_pack_names:
1746
pack = repo_not_stacked._pack_collection.get_pack_by_name(name)
1747
keys = [n[1] for n in pack.inventory_index.iter_all_entries()]
1749
inv_a_pack_name = name
1752
self.fail('Could not find pack containing A\'s inventory')
1753
repo_not_stacked.fetch(b_source.repository, 'A')
1754
self.assertEqual([('A',), ('B',)],
1755
sorted(repo_not_stacked.revisions.keys()))
1756
new_pack_names = set(repo_not_stacked._pack_collection.names())
1757
rev_a_pack_names = new_pack_names.difference(stacked_pack_names)
1758
self.assertEqual(1, len(rev_a_pack_names))
1759
rev_a_pack_name = list(rev_a_pack_names)[0]
1760
# Now fetch 'C', so we have a couple pack files to join
1761
repo_not_stacked.fetch(b_source.repository, 'C')
1762
rev_c_pack_names = set(repo_not_stacked._pack_collection.names())
1763
rev_c_pack_names = rev_c_pack_names.difference(new_pack_names)
1764
self.assertEqual(1, len(rev_c_pack_names))
1765
rev_c_pack_name = list(rev_c_pack_names)[0]
1766
return (repo_not_stacked, rev_a_pack_name, inv_a_pack_name,
1769
def test_pack_with_distant_inventories(self):
1770
# See https://bugs.launchpad.net/bzr/+bug/437003
1771
# When repacking, it is possible to have an inventory in a different
1772
# pack file than the associated revision. An autopack can then come
1773
# along, and miss that inventory, and complain.
1774
(repo, rev_a_pack_name, inv_a_pack_name, rev_c_pack_name
1775
) = self.make_branch_with_disjoint_inventory_and_revision()
1776
a_pack = repo._pack_collection.get_pack_by_name(rev_a_pack_name)
1777
c_pack = repo._pack_collection.get_pack_by_name(rev_c_pack_name)
1778
packer = groupcompress_repo.GCCHKPacker(repo._pack_collection,
1779
[a_pack, c_pack], '.test-pack')
1780
# This would raise ValueError in bug #437003, but should not raise an
1784
def test_pack_with_missing_inventory(self):
1785
# Similar to test_pack_with_missing_inventory, but this time, we force
1786
# the A inventory to actually be gone from the repository.
1787
(repo, rev_a_pack_name, inv_a_pack_name, rev_c_pack_name
1788
) = self.make_branch_with_disjoint_inventory_and_revision()
1789
inv_a_pack = repo._pack_collection.get_pack_by_name(inv_a_pack_name)
1790
repo._pack_collection._remove_pack_from_memory(inv_a_pack)
1791
packer = groupcompress_repo.GCCHKPacker(repo._pack_collection,
1792
repo._pack_collection.all_packs(), '.test-pack')
1793
e = self.assertRaises(ValueError, packer.pack)
1794
packer.new_pack.abort()
1795
self.assertContainsRe(str(e),
1796
r"We are missing inventories for revisions: .*'A'")
1699
1799
class TestCrossFormatPacks(TestCaseWithTransport):
1701
1801
def log_pack(self, hint=None):