Rev 4333: Fix bug 360791 by not raising an error when a smart server is asked for more content than it has locally; the client is assumed to be monitoring what it gets. in http://people.ubuntu.com/~robertc/baz2.0/pending/bug-360791

Robert Collins robertc at robertcollins.net
Wed May 6 03:05:39 BST 2009


At http://people.ubuntu.com/~robertc/baz2.0/pending/bug-360791

------------------------------------------------------------
revno: 4333
revision-id: robertc at robertcollins.net-20090506020536-xckeehz4vv1x66hr
parent: pqm at pqm.ubuntu.com-20090505195559-0qmeyyua7e407sym
committer: Robert Collins <robertc at robertcollins.net>
branch nick: bug-360791
timestamp: Wed 2009-05-06 12:05:36 +1000
message:
  Fix bug 360791 by not raising an error when a smart server is asked for more content than it has locally; the client is assumed to be monitoring what it gets.
=== modified file 'NEWS'
--- a/NEWS	2009-05-05 18:48:00 +0000
+++ b/NEWS	2009-05-06 02:05:36 +0000
@@ -70,6 +70,12 @@
 * Several bugs related to unicode symlinks have been fixed and the test suite
   enhanced to better catch regressions for them. (Vincent Ladeuil)
 
+* The smart server will no longer raise 'NoSuchRevision' when streaming
+  content with a size mismatch in a reconstructed graph search: it assumes
+  that the client will make sure it is happy with what it got, and this
+  sort of mismatch is normal for stacked environments.
+  (Robert Collins, #360791)
+
 Documentation
 *************
 

=== modified file 'bzrlib/smart/repository.py'
--- a/bzrlib/smart/repository.py	2009-03-24 23:19:12 +0000
+++ b/bzrlib/smart/repository.py	2009-05-06 02:05:36 +0000
@@ -71,18 +71,34 @@
         # is expected)
         return None
 
-    def recreate_search(self, repository, search_bytes):
+    def recreate_search(self, repository, search_bytes, discard_excess=False):
+        """Recreate a search from its serialised form.
+
+        :param discard_excess: If True, and the search refers to data we don't
+            have, just silently accept that fact - the verb calling
+            recreate_search trusts that clients will look for missing things
+            they expected and get it from elsewhere.
+        """
         lines = search_bytes.split('\n')
         if lines[0] == 'ancestry-of':
             heads = lines[1:]
             search_result = graph.PendingAncestryResult(heads, repository)
             return search_result, None
         elif lines[0] == 'search':
-            return self.recreate_search_from_recipe(repository, lines[1:])
+            return self.recreate_search_from_recipe(repository, lines[1:],
+                discard_excess=discard_excess)
         else:
             return (None, FailedSmartServerResponse(('BadSearch',)))
 
-    def recreate_search_from_recipe(self, repository, lines):
+    def recreate_search_from_recipe(self, repository, lines,
+        discard_excess=False):
+        """Recreate a specific revision search (vs a from-tip search).
+
+        :param discard_excess: If True, and the search refers to data we don't
+            have, just silently accept that fact - the verb calling
+            recreate_search trusts that clients will look for missing things
+            they expected and get it from elsewhere.
+        """
         start_keys = set(lines[0].split(' '))
         exclude_keys = set(lines[1].split(' '))
         revision_count = int(lines[2])
@@ -97,7 +113,8 @@
                     break
                 search.stop_searching_any(exclude_keys.intersection(next_revs))
             search_result = search.get_result()
-            if search_result.get_recipe()[3] != revision_count:
+            if (not discard_excess and
+                search_result.get_recipe()[3] != revision_count):
                 # we got back a different amount of data than expected, this
                 # gets reported as NoSuchRevision, because less revisions
                 # indicates missing revisions, and more should never happen as
@@ -379,7 +396,8 @@
         repository = self._repository
         repository.lock_read()
         try:
-            search_result, error = self.recreate_search(repository, body_bytes)
+            search_result, error = self.recreate_search(repository, body_bytes,
+                discard_excess=True)
             if error is not None:
                 repository.unlock()
                 return error

=== modified file 'bzrlib/tests/test_remote.py'
--- a/bzrlib/tests/test_remote.py	2009-04-27 16:10:10 +0000
+++ b/bzrlib/tests/test_remote.py	2009-05-06 02:05:36 +0000
@@ -2600,6 +2600,21 @@
         # from the backing branch, and one from the stacked on branch.
         self.assertLength(2, self.hpss_calls)
 
+    def test_stacked_pull_more_than_stacking_has_bug_360791(self):
+        # When pulling some fixed amount of content that is more than the
+        # source has (because some is coming from a fallback branch, no error
+        # should be received. This was reported as bug 360791.
+        # Need three branches: a trunk, a stacked branch, and a preexisting
+        # branch pulling content from stacked and trunk.
+        self.setup_smart_server_with_call_log()
+        trunk = self.make_branch_and_tree('trunk', format="1.9-rich-root")
+        r1 = trunk.commit('start')
+        stacked_branch = trunk.branch.create_clone_on_transport(
+            self.get_transport('stacked'), stacked_on=trunk.branch.base)
+        local = self.make_branch('local', format='1.9-rich-root')
+        local.repository.fetch(stacked_branch.repository,
+            stacked_branch.last_revision())
+
 
 class TestRemoteBranchEffort(tests.TestCaseWithTransport):
 




More information about the bazaar-commits mailing list