Rev 4578: Fix fetching from smart servers where there is a chain of stacked repositories rather than a single stacking point. (Robert Collins, bug #406597) in http://bazaar.launchpad.net/~lifeless/bzr/bug-406597

Robert Collins robertc at robertcollins.net
Thu Jul 30 05:27:15 BST 2009


At http://bazaar.launchpad.net/~lifeless/bzr/bug-406597

------------------------------------------------------------
revno: 4578
revision-id: robertc at robertcollins.net-20090730042705-450o2abhbh9ta3nq
parent: pqm at pqm.ubuntu.com-20090729225922-ct2n8v4ebyr46xwq
committer: Robert Collins <robertc at robertcollins.net>
branch nick: bug-406597
timestamp: Thu 2009-07-30 14:27:05 +1000
message:
  Fix fetching from smart servers where there is a chain of stacked repositories rather than a single stacking point. (Robert Collins, bug #406597)
=== modified file 'NEWS'
--- a/NEWS	2009-07-29 21:38:13 +0000
+++ b/NEWS	2009-07-30 04:27:05 +0000
@@ -84,6 +84,9 @@
   lots of backtraces about ``UnknownSmartMethod``, ``do_chunk`` or
   ``do_end``.  (Andrew Bennetts, #338561)
   
+* Streaming from bzr servers where there is a chain of stacked branches
+  (A stacked on B stacked on C) will now work. (Robert Collins, #406597)
+
 * The optional ``_knit_load_data_pyx`` C extension was never being
   imported.  This caused significant slowdowns when reading data from
   repositories.  (Andrew Bennetts, #405653)

=== modified file 'bzrlib/remote.py'
--- a/bzrlib/remote.py	2009-07-27 08:02:52 +0000
+++ b/bzrlib/remote.py	2009-07-30 04:27:05 +0000
@@ -1733,8 +1733,17 @@
         if (self.from_repository._fallback_repositories and
             self.to_format._fetch_order == 'topological'):
             return self._real_stream(self.from_repository, search)
-        return self.missing_parents_chain(search, [self.from_repository] +
-            self.from_repository._fallback_repositories)
+        sources = []
+        seen = set()
+        repos = [self.from_repository]
+        while repos:
+            repo = repos.pop(0)
+            if repo in seen:
+                continue
+            seen.add(repo)
+            repos.extend(repo._fallback_repositories)
+            sources.append(repo)
+        return self.missing_parents_chain(search, sources)
 
     def _real_stream(self, repo, search):
         """Get a stream for search from repo.

=== modified file 'bzrlib/tests/test_remote.py'
--- a/bzrlib/tests/test_remote.py	2009-07-16 05:22:50 +0000
+++ b/bzrlib/tests/test_remote.py	2009-07-30 04:27:05 +0000
@@ -2679,11 +2679,13 @@
                     result.append(content.key[-1])
         return result
 
-    def get_ordered_revs(self, format, order):
+    def get_ordered_revs(self, format, order, branch_factory=None):
         """Get a list of the revisions in a stream to format format.
 
         :param format: The format of the target.
         :param order: the order that target should have requested.
+        :param branch_factory: A callable to create a trunk and stacked branch
+            to fetch from. If none, self.prepare_stacked_remote_branch is used.
         :result: The revision ids in the stream, in the order seen,
             the topological order of revisions in the source.
         """
@@ -2691,7 +2693,9 @@
         target_repository_format = unordered_format.repository_format
         # Cross check
         self.assertEqual(order, target_repository_format._fetch_order)
-        trunk, stacked = self.prepare_stacked_remote_branch()
+        if branch_factory is None:
+            branch_factory = self.prepare_stacked_remote_branch
+        _, stacked = branch_factory()
         source = stacked.repository._get_source(target_repository_format)
         tip = stacked.last_revision()
         revs = stacked.repository.get_ancestry(tip)
@@ -2716,6 +2720,24 @@
         # from the server, then one from the backing branch.
         self.assertLength(2, self.hpss_calls)
 
+    def test_stacked_on_stacked_get_stream_unordered(self):
+        # Repository._get_source.get_stream() from a stacked repository which
+        # is itself stacked yields the full data from all three sources.
+        def make_stacked_stacked():
+            _, stacked = self.prepare_stacked_remote_branch()
+            tree = stacked.bzrdir.sprout('tree3', stacked=True
+                ).open_workingtree()
+            tree.commit('more local changes are better')
+            branch = Branch.open(self.get_url('tree3'))
+            branch.lock_read()
+            return None, branch
+        rev_ord, expected_revs = self.get_ordered_revs('1.9', 'unordered',
+            branch_factory=make_stacked_stacked)
+        self.assertEqual(set(expected_revs), set(rev_ord))
+        # Getting unordered results should have made a streaming data request
+        # from the server, and one from each backing repo
+        self.assertLength(3, self.hpss_calls)
+
     def test_stacked_get_stream_topological(self):
         # Repository._get_source.get_stream() from a stacked repository with
         # topological sorting yields the full data from both stacked and




More information about the bazaar-commits mailing list