Rev 3173: Repository has a new method ``has_revisions`` which signals the presence in http://people.ubuntu.com/~robertc/baz2.0/has_revisions

Robert Collins robertc at robertcollins.net
Fri Jan 11 03:55:14 GMT 2008


At http://people.ubuntu.com/~robertc/baz2.0/has_revisions

------------------------------------------------------------
revno: 3173
revision-id:robertc at robertcollins.net-20080111035451-52at4031ohbmtoh2
parent: pqm at pqm.ubuntu.com-20080110025628-6tl4b9cmdn335suw
committer: Robert Collins <robertc at robertcollins.net>
branch nick: has_revisions
timestamp: Fri 2008-01-11 14:54:51 +1100
message:
  Repository has a new method ``has_revisions`` which signals the presence
  of many revisions by returning a set of the revisions listed which are
  present. This can be done by index queries without reading data for parent
  revision names etc. (Robert Collins)
added:
  bzrlib/tests/repository_implementations/test_has_revisions.py test_has_revisions.p-20080111035443-xaupgdsx5fw1q54b-1
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/remote.py               remote.py-20060720103555-yeeg2x51vn0rbtdp-1
  bzrlib/repofmt/knitrepo.py     knitrepo.py-20070206081537-pyy4a00xdas0j4pf-1
  bzrlib/repofmt/pack_repo.py    pack_repo.py-20070813041115-gjv5ma7ktfqwsjgn-1
  bzrlib/repofmt/weaverepo.py    presplitout.py-20070125045333-wfav3tsh73oxu3zk-1
  bzrlib/repository.py           rev_storage.py-20051111201905-119e9401e46257e3
  bzrlib/tests/repository_implementations/__init__.py __init__.py-20060131092037-9564957a7d4a841b
=== modified file 'NEWS'
--- a/NEWS	2008-01-10 01:45:17 +0000
+++ b/NEWS	2008-01-11 03:54:51 +0000
@@ -166,6 +166,11 @@
    * Reduce selftest overhead to establish test names by memoization.
      (Vincent Ladeuil)
 
+   * Repository has a new method ``has_revisions`` which signals the presence
+     of many revisions by returning a set of the revisions listed which are
+     present. This can be done by index queries without reading data for parent
+     revision names etc. (Robert Collins)
+
   API BREAKS:
 
   TESTING:

=== modified file 'bzrlib/remote.py'
--- a/bzrlib/remote.py	2008-01-07 01:27:38 +0000
+++ b/bzrlib/remote.py	2008-01-11 03:54:51 +0000
@@ -38,6 +38,7 @@
     deprecated_method,
     zero_ninetyone,
     )
+from bzrlib.revision import NULL_REVISION
 from bzrlib.trace import note
 
 # Note: RemoteBzrDirFormat is in bzrdir.py
@@ -367,7 +368,7 @@
 
     def has_revision(self, revision_id):
         """See Repository.has_revision()."""
-        if revision_id is None:
+        if revision_id == NULL_REVISION:
             # The null revision is always present.
             return True
         path = self.bzrdir._path_for_remote_call(self._client)
@@ -375,6 +376,14 @@
         assert response[0] in ('yes', 'no'), 'unexpected response code %s' % (response,)
         return response[0] == 'yes'
 
+    def has_revisions(self, revision_ids):
+        """See Repository.has_revisions()."""
+        result = set()
+        for revision_id in revision_ids:
+            if self.has_revision(revision_id):
+                result.add(revision_id)
+        return result
+
     def has_same_location(self, other):
         return (self.__class__ == other.__class__ and
                 self.bzrdir.transport.base == other.bzrdir.transport.base)

=== modified file 'bzrlib/repofmt/knitrepo.py'
--- a/bzrlib/repofmt/knitrepo.py	2008-01-02 05:32:20 +0000
+++ b/bzrlib/repofmt/knitrepo.py	2008-01-11 03:54:51 +0000
@@ -265,6 +265,15 @@
         """
         return self._get_revision_vf()
 
+    def has_revisions(self, revision_ids):
+        """See Repository.has_revisions()."""
+        result = set()
+        transaction = self.get_transaction()
+        for revision_id in revision_ids:
+            if self._revision_store.has_revision_id(revision_id, transaction):
+                result.add(revision_id)
+        return result
+
     @needs_write_lock
     def reconcile(self, other=None, thorough=False):
         """Reconcile this repository."""

=== modified file 'bzrlib/repofmt/pack_repo.py'
--- a/bzrlib/repofmt/pack_repo.py	2008-01-04 00:56:35 +0000
+++ b/bzrlib/repofmt/pack_repo.py	2008-01-11 03:54:51 +0000
@@ -1926,6 +1926,17 @@
             found_parents[key[0]] = parents
         return found_parents
 
+    def has_revisions(self, revision_ids):
+        """See Repository.has_revisions()."""
+        revision_ids = set(revision_ids)
+        result = revision_ids.intersection(
+            set([None, _mod_revision.NULL_REVISION]))
+        revision_ids.difference_update(result)
+        index = self._pack_collection.revision_index.combined_index
+        keys = [(revision_id,) for revision_id in revision_ids]
+        result.update(node[1][0] for node in index.iter_entries(keys))
+        return result
+
     def _make_parents_provider(self):
         return graph.CachingParentsProvider(self)
 

=== modified file 'bzrlib/repofmt/weaverepo.py'
--- a/bzrlib/repofmt/weaverepo.py	2007-10-30 17:39:11 +0000
+++ b/bzrlib/repofmt/weaverepo.py	2008-01-11 03:54:51 +0000
@@ -176,6 +176,15 @@
                         pending.add(revision_id)
             return result
 
+    def has_revisions(self, revision_ids):
+        """See Repository.has_revisions()."""
+        result = set()
+        transaction = self.get_transaction()
+        for revision_id in revision_ids:
+            if self._revision_store.has_revision_id(revision_id, transaction):
+                result.add(revision_id)
+        return result
+
     @needs_read_lock
     def is_shared(self):
         """AllInOne repositories cannot be shared."""
@@ -308,6 +317,15 @@
                         pending.add(revision_id)
             return result
 
+    def has_revisions(self, revision_ids):
+        """See Repository.has_revisions()."""
+        result = set()
+        transaction = self.get_transaction()
+        for revision_id in revision_ids:
+            if self._revision_store.has_revision_id(revision_id, transaction):
+                result.add(revision_id)
+        return result
+
     def revision_graph_can_have_wrong_parents(self):
         # XXX: This is an old format that we don't support full checking on, so
         # just claim that checking for this inconsistency is not required.

=== modified file 'bzrlib/repository.py'
--- a/bzrlib/repository.py	2008-01-10 01:30:10 +0000
+++ b/bzrlib/repository.py	2008-01-11 03:54:51 +0000
@@ -1020,8 +1020,16 @@
     @needs_read_lock
     def has_revision(self, revision_id):
         """True if this repository has a copy of the revision."""
-        if 'evil' in debug.debug_flags:
-            mutter_callsite(3, "has_revision is a LBYL symptom.")
+        return revision_id in self.has_revisions((revision_id,))
+
+    def has_revisions(self, revision_ids):
+        """Probe to find out the presence of multiple revisions.
+
+        :param revision_ids: An iterable of revision_ids.
+        :return: A set of the revision_ids that were present.
+        """
+        raise NotImplementedError(self.has_revisions)
+
         return self._revision_store.has_revision_id(revision_id,
                                                     self.get_transaction())
 
@@ -2650,8 +2658,6 @@
             graph = self.source.get_graph()
             missing_revs = set()
             searcher = graph._make_breadth_first_searcher([revision_id])
-            target_index = \
-                self.target._pack_collection.revision_index.combined_index
             null_set = frozenset([_mod_revision.NULL_REVISION])
             while True:
                 try:
@@ -2659,9 +2665,7 @@
                 except StopIteration:
                     break
                 next_revs.difference_update(null_set)
-                target_keys = [(key,) for key in next_revs]
-                have_revs = frozenset(node[1][0] for node in
-                    target_index.iter_entries(target_keys))
+                have_revs = self.target.has_revisions(next_revs)
                 missing_revs.update(next_revs - have_revs)
                 searcher.stop_searching_any(have_revs)
             if next_revs - have_revs == set([revision_id]):

=== modified file 'bzrlib/tests/repository_implementations/__init__.py'
--- a/bzrlib/tests/repository_implementations/__init__.py	2007-12-19 08:12:34 +0000
+++ b/bzrlib/tests/repository_implementations/__init__.py	2008-01-11 03:54:51 +0000
@@ -868,6 +868,7 @@
         'test_find_text_key_references',
         'test__generate_text_key_index',
         'test_has_same_location',
+        'test_has_revisions',
         'test_is_write_locked',
         'test_iter_reverse_revision_history',
         'test_pack',

=== added file 'bzrlib/tests/repository_implementations/test_has_revisions.py'
--- a/bzrlib/tests/repository_implementations/test_has_revisions.py	1970-01-01 00:00:00 +0000
+++ b/bzrlib/tests/repository_implementations/test_has_revisions.py	2008-01-11 03:54:51 +0000
@@ -0,0 +1,43 @@
+# Copyright (C) 2008 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
+
+"""Tests for implementations of Repository.has_revisions."""
+
+from bzrlib.revision import NULL_REVISION
+from bzrlib.tests.repository_implementations import TestCaseWithRepository
+
+
+class TestHasRevisions(TestCaseWithRepository):
+
+    def test_empty_list(self):
+        repo = self.make_repository('.')
+        self.assertEqual(set(), repo.has_revisions([]))
+
+    def test_superset(self):
+        tree = self.make_branch_and_tree('.')
+        repo = tree.branch.repository
+        rev1 = tree.commit('1')
+        rev2 = tree.commit('2')
+        rev3 = tree.commit('3')
+        self.assertEqual(set([rev1, rev3]),
+            repo.has_revisions([rev1, rev3, 'foobar:']))
+
+    def test_NULL(self):
+        # NULL_REVISION is always present. So for
+        # compatibility with 'has_revision' we make this work.
+        repo = self.make_repository('.')
+        self.assertEqual(set([NULL_REVISION]),
+            repo.has_revisions([NULL_REVISION]))



More information about the bazaar-commits mailing list