Rev 2990: New Repository API find_text_key_references for use by reconcile and check. in http://people.ubuntu.com/~robertc/baz2.0/reconcile
Robert Collins
robertc at robertcollins.net
Wed Nov 14 04:24:35 GMT 2007
At http://people.ubuntu.com/~robertc/baz2.0/reconcile
------------------------------------------------------------
revno: 2990
revision-id:robertc at robertcollins.net-20071114042424-ww2cu4nqfo5fv6c4
parent: robertc at robertcollins.net-20071114022530-prb0wv25n7os0ee1
committer: Robert Collins <robertc at robertcollins.net>
branch nick: find_text_key_references
timestamp: Wed 2007-11-14 15:24:24 +1100
message:
New Repository API find_text_key_references for use by reconcile and check.
added:
bzrlib/tests/repository_implementations/test_find_text_key_references.py test_find_text_key_r-20071114033605-v73bakal8x77qlfi-1
modified:
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/repository.py rev_storage.py-20051111201905-119e9401e46257e3
bzrlib/tests/repository_implementations/__init__.py __init__.py-20060131092037-9564957a7d4a841b
bzrlib/tests/repository_implementations/test_check_reconcile.py test_broken.py-20070928125406-62236394w0jpbpd6-2
=== added file 'bzrlib/tests/repository_implementations/test_find_text_key_references.py'
--- a/bzrlib/tests/repository_implementations/test_find_text_key_references.py 1970-01-01 00:00:00 +0000
+++ b/bzrlib/tests/repository_implementations/test_find_text_key_references.py 2007-11-14 04:24:24 +0000
@@ -0,0 +1,30 @@
+# Copyright (C) 2007 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+"""Test the find_text_key_references API."""
+
+
+from bzrlib.tests.repository_implementations import TestCaseWithRepository
+
+
+class TestFindTextKeyReferences(TestCaseWithRepository):
+
+ def test_empty(self):
+ repo = self.make_repository('.')
+ repo.lock_read()
+ self.addCleanup(repo.unlock)
+ self.assertEqual({}, repo.find_text_key_references())
=== modified file 'bzrlib/remote.py'
--- a/bzrlib/remote.py 2007-11-04 20:35:32 +0000
+++ b/bzrlib/remote.py 2007-11-14 04:24:24 +0000
@@ -305,6 +305,20 @@
#self._real_repository = self.bzrdir._real_bzrdir.open_repository()
self._set_real_repository(self.bzrdir._real_bzrdir.open_repository())
+ def find_text_key_references(self):
+ """Find the text key references within the repository.
+
+ :return: a dictionary mapping (file_id, revision_id) tuples to altered file-ids to an iterable of
+ revision_ids. Each altered file-ids has the exact revision_ids that
+ altered it listed explicitly.
+ :return: A dictionary mapping text keys ((fileid, revision_id) tuples)
+ to whether they were referred to by the inventory of the
+ revision_id that they contain. The inventory texts from all present
+ revision ids are assessed to generate this report.
+ """
+ self._ensure_real()
+ return self._real_repository.find_text_key_references()
+
def get_revision_graph(self, revision_id=None):
"""See Repository.get_revision_graph()."""
if revision_id is None:
=== modified file 'bzrlib/repository.py'
--- a/bzrlib/repository.py 2007-11-14 02:25:30 +0000
+++ b/bzrlib/repository.py 2007-11-14 04:24:24 +0000
@@ -1055,6 +1055,27 @@
signature,
self.get_transaction())
+ def find_text_key_references(self):
+ """Find the text key references within the repository.
+
+ :return: a dictionary mapping (file_id, revision_id) tuples to altered file-ids to an iterable of
+ revision_ids. Each altered file-ids has the exact revision_ids that
+ altered it listed explicitly.
+ :return: A dictionary mapping text keys ((fileid, revision_id) tuples)
+ to whether they were referred to by the inventory of the
+ revision_id that they contain. The inventory texts from all present
+ revision ids are assessed to generate this report.
+ """
+ revision_ids = self.all_revision_ids()
+ w = self.get_inventory_weave()
+ pb = ui.ui_factory.nested_progress_bar()
+ try:
+ return self._find_text_key_references_from_xml_inventory_lines(
+ w.iter_lines_added_or_present_in_versions(revision_ids, pb=pb))
+ finally:
+ pb.finished()
+
+
def _find_text_key_references_from_xml_inventory_lines(self,
line_iterator):
"""Core routine for extracting references to texts from inventories.
@@ -1068,6 +1089,10 @@
not part of the line_iterator's output then False will be given -
even though it may actually refer to that key.
"""
+ assert self._serializer.support_altered_by_hack, \
+ ("_find_text_key_references_from_xml_inventory_lines only "
+ "supported for branches which store inventory as unnested xml, "
+ "not on %r" % self)
result = {}
# this code needs to read every new line in every inventory for the
@@ -1164,9 +1189,6 @@
revision_ids. Each altered file-ids has the exact revision_ids that
altered it listed explicitly.
"""
- assert self._serializer.support_altered_by_hack, \
- ("fileids_altered_by_revision_ids only supported for branches "
- "which store inventory as unnested xml, not on %r" % self)
selected_revision_ids = set(revision_ids)
w = self.get_inventory_weave()
pb = ui.ui_factory.nested_progress_bar()
=== modified file 'bzrlib/tests/repository_implementations/__init__.py'
--- a/bzrlib/tests/repository_implementations/__init__.py 2007-11-03 14:26:37 +0000
+++ b/bzrlib/tests/repository_implementations/__init__.py 2007-11-14 04:24:24 +0000
@@ -168,6 +168,14 @@
inv = self.make_one_file_inventory(
repo, 'rev1a', [], root_revision='rev1a')
self.add_revision(repo, 'rev1a', inv, [])
+ self.versioned_root = repo.supports_rich_root()
+
+ def repository_text_key_references(self):
+ result = {}
+ if self.versioned_root:
+ result.update({('TREE_ROOT', 'rev1a'): True})
+ result.update({('a-file-id', 'rev1a'): True})
+ return result
class FileParentIsNotInRevisionAncestryScenario(BrokenRepoScenario):
@@ -217,6 +225,16 @@
inv = self.make_one_file_inventory(
repo, 'rev2', ['rev1a', 'rev1b'])
self.add_revision(repo, 'rev2', inv, ['rev1a'])
+ self.versioned_root = repo.supports_rich_root()
+
+ def repository_text_key_references(self):
+ result = {}
+ if self.versioned_root:
+ result.update({('TREE_ROOT', 'rev1a'): True,
+ ('TREE_ROOT', 'rev2'): True})
+ result.update({('a-file-id', 'rev1a'): True,
+ ('a-file-id', 'rev2'): True})
+ return result
class FileParentHasInaccessibleInventoryScenario(BrokenRepoScenario):
@@ -267,6 +285,16 @@
# a-file cannot have rev1c as its ancestor.
inv = self.make_one_file_inventory(repo, 'rev3', ['rev1c'])
self.add_revision(repo, 'rev3', inv, ['rev1c', 'rev1a'])
+ self.versioned_root = repo.supports_rich_root()
+
+ def repository_text_key_references(self):
+ result = {}
+ if self.versioned_root:
+ result.update({('TREE_ROOT', 'rev2'): True,
+ ('TREE_ROOT', 'rev3'): True})
+ result.update({('a-file-id', 'rev2'): True,
+ ('a-file-id', 'rev3'): True})
+ return result
class FileParentsNotReferencedByAnyInventoryScenario(BrokenRepoScenario):
@@ -386,6 +414,24 @@
# parents for the per file graph.
inv = self.make_one_file_inventory(repo, 'rev5', ['rev2', 'rev2c'])
self.add_revision(repo, 'rev5', inv, ['rev2', 'rev2c'])
+ self.versioned_root = repo.supports_rich_root()
+
+ def repository_text_key_references(self):
+ result = {}
+ if self.versioned_root:
+ result.update({('TREE_ROOT', 'rev1a'): True,
+ ('TREE_ROOT', 'rev2'): True,
+ ('TREE_ROOT', 'rev2b'): True,
+ ('TREE_ROOT', 'rev2c'): True,
+ ('TREE_ROOT', 'rev3'): True,
+ ('TREE_ROOT', 'rev4'): True,
+ ('TREE_ROOT', 'rev5'): True})
+ result.update({('a-file-id', 'rev1a'): True,
+ ('a-file-id', 'rev2c'): True,
+ ('a-file-id', 'rev3'): True,
+ ('a-file-id', 'rev4'): True,
+ ('a-file-id', 'rev5'): True})
+ return result
class UnreferencedFileParentsFromNoOpMergeScenario(BrokenRepoScenario):
@@ -454,6 +500,21 @@
# rev4: a modification of a-file on top of rev3.
inv = self.make_one_file_inventory(repo, 'rev4', ['rev2'])
self.add_revision(repo, 'rev4', inv, ['rev3'])
+ self.versioned_root = repo.supports_rich_root()
+
+ def repository_text_key_references(self):
+ result = {}
+ if self.versioned_root:
+ result.update({('TREE_ROOT', 'rev1a'): True,
+ ('TREE_ROOT', 'rev1b'): True,
+ ('TREE_ROOT', 'rev2'): True,
+ ('TREE_ROOT', 'rev3'): True,
+ ('TREE_ROOT', 'rev4'): True})
+ result.update({('a-file-id', 'rev1a'): True,
+ ('a-file-id', 'rev1b'): True,
+ ('a-file-id', 'rev2'): False,
+ ('a-file-id', 'rev4'): True})
+ return result
class TooManyParentsScenario(BrokenRepoScenario):
@@ -503,7 +564,19 @@
inv = self.make_one_file_inventory(
repo, 'broken-revision', ('good-parent', 'bad-parent'))
self.add_revision(repo, 'broken-revision', inv, ('good-parent',))
+ self.versioned_root = repo.supports_rich_root()
+ def repository_text_key_references(self):
+ result = {}
+ if self.versioned_root:
+ result.update({('TREE_ROOT', 'bad-parent'): True,
+ ('TREE_ROOT', 'broken-revision'): True,
+ ('TREE_ROOT', 'good-parent'): True})
+ result.update({('a-file-id', 'bad-parent'): True,
+ ('a-file-id', 'broken-revision'): True,
+ ('a-file-id', 'good-parent'): True})
+ return result
+
class ClaimedFileParentDidNotModifyFileScenario(BrokenRepoScenario):
"""A scenario where the file parent is the same as the revision parent, but
@@ -562,7 +635,18 @@
inv = self.make_one_file_inventory(
repo, 'current', ('modified-something-else',))
self.add_revision(repo, 'current', inv, ('modified-something-else',))
+ self.versioned_root = repo.supports_rich_root()
+ def repository_text_key_references(self):
+ result = {}
+ if self.versioned_root:
+ result.update({('TREE_ROOT', 'basis'): True,
+ ('TREE_ROOT', 'current'): True,
+ ('TREE_ROOT', 'modified-something-else'): True})
+ result.update({('a-file-id', 'basis'): True,
+ ('a-file-id', 'current'): True})
+ return result
+
class IncorrectlyOrderedParentsScenario(BrokenRepoScenario):
"""A scenario where the set parents of a version of a file are correct, but
@@ -626,7 +710,21 @@
repo, 'broken-revision-2-1', ['parent-1', 'parent-2'])
self.add_revision(
repo, 'broken-revision-2-1', inv, ['parent-2', 'parent-1'])
+ self.versioned_root = repo.supports_rich_root()
+ def repository_text_key_references(self):
+ result = {}
+ if self.versioned_root:
+ result.update({('TREE_ROOT', 'broken-revision-1-2'): True,
+ ('TREE_ROOT', 'broken-revision-2-1'): True,
+ ('TREE_ROOT', 'parent-1'): True,
+ ('TREE_ROOT', 'parent-2'): True})
+ result.update({('a-file-id', 'broken-revision-1-2'): True,
+ ('a-file-id', 'broken-revision-2-1'): True,
+ ('a-file-id', 'parent-1'): True,
+ ('a-file-id', 'parent-2'): True})
+ return result
+
all_broken_scenario_classes = [
UndamagedRepositoryScenario,
@@ -671,6 +769,7 @@
'test_commit_builder',
'test_fetch',
'test_fileid_involved',
+ 'test_find_text_key_references',
'test_has_same_location',
'test_is_write_locked',
'test_iter_reverse_revision_history',
=== modified file 'bzrlib/tests/repository_implementations/test_check_reconcile.py'
--- a/bzrlib/tests/repository_implementations/test_check_reconcile.py 2007-11-03 14:26:37 +0000
+++ b/bzrlib/tests/repository_implementations/test_check_reconcile.py 2007-11-14 04:24:24 +0000
@@ -134,6 +134,16 @@
% (when_description, version, found_parents,
expected_parents))
+ def prepare_test_repository(self):
+ """Prepare a repository to test with from the test scenario.
+
+ :return: A repository, and the scenario instance.
+ """
+ scenario = self.scenario_class(self)
+ repo = self.make_populated_repository(scenario.populate_repository)
+ self.require_repo_suffers_text_parent_corruption(repo)
+ return repo, scenario
+
def shas_for_versions_of_file(self, repo, versions):
"""Get the SHA-1 hashes of the versions of 'a-file' in the repository.
@@ -149,9 +159,7 @@
"""Populate a repository and reconcile it, verifying the state before
and after.
"""
- scenario = self.scenario_class(self)
- repo = self.make_populated_repository(scenario.populate_repository)
- self.require_repo_suffers_text_parent_corruption(repo)
+ repo, scenario = self.prepare_test_repository()
repo.lock_read()
try:
self.assertParentsMatch(scenario.populated_parents(), repo,
@@ -183,9 +191,7 @@
def test_check_behaviour(self):
"""Populate a repository and check it, and verify the output."""
- scenario = self.scenario_class(self)
- repo = self.make_populated_repository(scenario.populate_repository)
- self.require_repo_suffers_text_parent_corruption(repo)
+ repo, scenario = self.prepare_test_repository()
check_result = repo.check()
check_result.report_results(verbose=True)
for pattern in scenario.check_regexes(repo):
@@ -193,3 +199,10 @@
self._get_log(keep_log_file=True),
pattern)
+ def test_find_text_key_references(self):
+ """Test that find_text_key_references finds erroneous references."""
+ repo, scenario = self.prepare_test_repository()
+ repo.lock_read()
+ self.addCleanup(repo.unlock)
+ self.assertEqual(scenario.repository_text_key_references(),
+ repo.find_text_key_references())
More information about the bazaar-commits
mailing list