Rev 4293: Merge with .dev. in http://people.ubuntu.com/~robertc/baz2.0/pending/push.roundtrips

Robert Collins robertc at robertcollins.net
Wed Apr 15 01:01:13 BST 2009


At http://people.ubuntu.com/~robertc/baz2.0/pending/push.roundtrips

------------------------------------------------------------
revno: 4293 [merge]
revision-id: robertc at robertcollins.net-20090415000035-h0xsked0o73un7gi
parent: robertc at robertcollins.net-20090414071101-kmlsxria9ok4ldx5
parent: pqm at pqm.ubuntu.com-20090414031543-gqbs23oebd68p7h7
committer: Robert Collins <robertc at robertcollins.net>
branch nick: push.roundtrips
timestamp: Wed 2009-04-15 10:00:35 +1000
message:
  Merge with .dev.
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/branchbuilder.py        branchbuilder.py-20070427022007-zlxpqz2lannhk6y8-1
  bzrlib/fetch.py                fetch.py-20050818234941-26fea6105696365d
  bzrlib/remote.py               remote.py-20060720103555-yeeg2x51vn0rbtdp-1
  bzrlib/repository.py           rev_storage.py-20051111201905-119e9401e46257e3
  bzrlib/tests/__init__.py       selftest.py-20050531073622-8d0e3c8845c97a64
  bzrlib/tests/blackbox/test_push.py test_push.py-20060329002750-929af230d5d22663
  bzrlib/tests/interrepository_implementations/__init__.py __init__.py-20060220054744-baf49a1f88f17b1a
  bzrlib/tests/interrepository_implementations/test_fetch.py test_fetch.py-20080425213627-j60cjh782ufm83ry-1
------------------------------------------------------------
Use --levels 0 (or -n0) to see merged revisions.
=== modified file 'NEWS'
--- a/NEWS	2009-04-14 07:11:01 +0000
+++ b/NEWS	2009-04-15 00:00:35 +0000
@@ -252,6 +252,14 @@
   both branches, we know that the trunk for the project can be read too,
   so the upgrade will not inconvenience users. (Robert Collins, #345169)
 
+* Pushing a new stacked branch will also push the parent inventories for
+  revisions at the stacking boundary.  This makes sure that the stacked
+  branch has enough data to calculate inventory deltas for all of its
+  revisions (without requiring the fallback branch).  This avoids
+  "'AbsentContentFactory' object has no attribute 'get_bytes_as'" errors
+  when fetching the stacked branch from a 1.13 (or later) smart server.
+  This partially fixes #354036.  (Andrew Bennetts, Robert Collins)
+
 * The full test suite is passing again on OSX. Several minor issues (mostly
   test related) have been fixed. (Vincent Ladeuil, #355273).
 

=== modified file 'bzrlib/branchbuilder.py'
--- a/bzrlib/branchbuilder.py	2009-03-23 14:59:43 +0000
+++ b/bzrlib/branchbuilder.py	2009-04-09 02:59:17 +0000
@@ -56,7 +56,7 @@
         a series in progress, it should be None.
     """
 
-    def __init__(self, transport, format=None):
+    def __init__(self, transport=None, format=None, branch=None):
         """Construct a BranchBuilder on transport.
 
         :param transport: The transport the branch should be created on.
@@ -64,15 +64,26 @@
             it will be created.
         :param format: Either a BzrDirFormat, or the name of a format in the
             bzrdir format registry for the branch to be built.
+        :param branch: An already constructed branch to use.  This param is
+            mutually exclusive with the transport and format params.
         """
-        if not transport.has('.'):
-            transport.mkdir('.')
-        if format is None:
-            format = 'default'
-        if isinstance(format, str):
-            format = bzrdir.format_registry.make_bzrdir(format)
-        self._branch = bzrdir.BzrDir.create_branch_convenience(transport.base,
-            format=format, force_new_tree=False)
+        if branch is not None:
+            if format is not None:
+                raise AssertionError(
+                    "branch and format kwargs are mutually exclusive")
+            if transport is not None:
+                raise AssertionError(
+                    "branch and transport kwargs are mutually exclusive")
+            self._branch = branch
+        else:
+            if not transport.has('.'):
+                transport.mkdir('.')
+            if format is None:
+                format = 'default'
+            if isinstance(format, str):
+                format = bzrdir.format_registry.make_bzrdir(format)
+            self._branch = bzrdir.BzrDir.create_branch_convenience(
+                transport.base, format=format, force_new_tree=False)
         self._tree = None
 
     def build_commit(self, **commit_kwargs):

=== modified file 'bzrlib/fetch.py'
--- a/bzrlib/fetch.py	2009-03-30 11:49:32 +0000
+++ b/bzrlib/fetch.py	2009-04-14 03:15:43 +0000
@@ -136,6 +136,18 @@
             pb.update("Inserting stream")
             resume_tokens, missing_keys = self.sink.insert_stream(
                 stream, from_format, [])
+            if self.to_repository._fallback_repositories:
+                # Find all the parent revisions referenced by the stream, but
+                # not present in the stream, and make sure we have their
+                # inventories.
+                revision_ids = search.get_keys()
+                parent_maps = self.to_repository.get_parent_map(revision_ids)
+                parents = set()
+                map(parents.update, parent_maps.itervalues())
+                parents.difference_update(revision_ids)
+                parents.discard(NULL_REVISION)
+                missing_keys.update(
+                    ('inventories', rev_id) for rev_id in parents)
             if missing_keys:
                 pb.update("Missing keys")
                 stream = source.get_stream_for_missing_keys(missing_keys)

=== modified file 'bzrlib/remote.py'
--- a/bzrlib/remote.py	2009-04-14 07:11:01 +0000
+++ b/bzrlib/remote.py	2009-04-15 00:00:35 +0000
@@ -1644,7 +1644,7 @@
         if response[0][0] == 'missing-basis':
             tokens, missing_keys = bencode.bdecode_as_tuple(response[0][1])
             resume_tokens = tokens
-            return resume_tokens, missing_keys
+            return resume_tokens, set(missing_keys)
         else:
             self.target_repo.refresh_data()
             return [], set()

=== modified file 'bzrlib/repository.py'
--- a/bzrlib/repository.py	2009-04-09 20:23:07 +0000
+++ b/bzrlib/repository.py	2009-04-14 03:15:43 +0000
@@ -3362,7 +3362,7 @@
     @classmethod
     def _get_repo_format_to_test(self):
         from bzrlib.repofmt import pack_repo
-        return pack_repo.RepositoryFormatKnitPack1()
+        return pack_repo.RepositoryFormatKnitPack6RichRoot()
 
     @staticmethod
     def is_compatible(source, target):
@@ -3626,9 +3626,28 @@
         to_texts.insert_record_stream(from_texts.get_record_stream(
             text_keys, self.target._format._fetch_order,
             not self.target._format._fetch_uses_deltas))
-        # insert deltas
+        # insert inventory deltas
         for delta in pending_deltas:
             self.target.add_inventory_by_delta(*delta)
+        if self.target._fallback_repositories:
+            # Make sure this stacked repository has all the parent inventories
+            # for the new revisions that we are about to insert.  We do this
+            # before adding the revisions so that no revision is added until
+            # all the inventories it may depend on are added.
+            parent_ids = set()
+            revision_ids = set()
+            for revision in pending_revisions:
+                revision_ids.add(revision.revision_id)
+                parent_ids.update(revision.parent_ids)
+            parent_ids.difference_update(revision_ids)
+            parent_ids.discard(_mod_revision.NULL_REVISION)
+            parent_map = self.source.get_parent_map(parent_ids)
+            for parent_tree in self.source.revision_trees(parent_ids):
+                basis_id, delta = self._get_delta_for_revision(tree, parent_ids, basis_id, cache)
+                current_revision_id = parent_tree.get_revision_id()
+                parents_parents = parent_map[current_revision_id]
+                self.target.add_inventory_by_delta(
+                    basis_id, delta, current_revision_id, parents_parents)
         # insert signatures and revisions
         for revision in pending_revisions:
             try:

=== modified file 'bzrlib/tests/__init__.py'
--- a/bzrlib/tests/__init__.py	2009-04-09 23:12:55 +0000
+++ b/bzrlib/tests/__init__.py	2009-04-14 03:15:43 +0000
@@ -2154,8 +2154,8 @@
         return memorytree.MemoryTree.create_on_branch(b)
 
     def make_branch_builder(self, relpath, format=None):
-        return branchbuilder.BranchBuilder(self.get_transport(relpath),
-            format=format)
+        branch = self.make_branch(relpath, format=format)
+        return branchbuilder.BranchBuilder(branch=branch)
 
     def overrideEnvironmentForTesting(self):
         os.environ['HOME'] = self.test_home_dir

=== modified file 'bzrlib/tests/blackbox/test_push.py'
--- a/bzrlib/tests/blackbox/test_push.py	2009-04-14 07:11:01 +0000
+++ b/bzrlib/tests/blackbox/test_push.py	2009-04-15 00:00:35 +0000
@@ -217,7 +217,7 @@
         # being too low. If rpc_count increases, more network roundtrips have
         # become necessary for this use case. Please do not adjust this number
         # upwards without agreement from bzr's network support maintainers.
-        self.assertLength(36, self.hpss_calls)
+        self.assertLength(37, self.hpss_calls)
         remote = Branch.open('public')
         self.assertEndsWith(remote.get_stacked_on_url(), '/parent')
 

=== modified file 'bzrlib/tests/interrepository_implementations/__init__.py'
--- a/bzrlib/tests/interrepository_implementations/__init__.py	2009-03-23 14:59:43 +0000
+++ b/bzrlib/tests/interrepository_implementations/__init__.py	2009-04-09 02:59:17 +0000
@@ -32,9 +32,10 @@
     )
 
 from bzrlib.repository import (
-                               InterKnitRepo,
-                               InterRepository,
-                               )
+    InterDifferingSerializer,
+    InterKnitRepo,
+    InterRepository,
+    )
 from bzrlib.tests import (
                           default_transport,
                           multiply_tests,
@@ -107,6 +108,9 @@
     result.append((InterKnitRepo,
                    pack_repo.RepositoryFormatKnitPack3(),
                    pack_repo.RepositoryFormatKnitPack4()))
+    result.append((InterDifferingSerializer,
+                   pack_repo.RepositoryFormatKnitPack1(),
+                   pack_repo.RepositoryFormatKnitPack6RichRoot()))
     return result
 
 

=== modified file 'bzrlib/tests/interrepository_implementations/test_fetch.py'
--- a/bzrlib/tests/interrepository_implementations/test_fetch.py	2009-03-30 11:49:32 +0000
+++ b/bzrlib/tests/interrepository_implementations/test_fetch.py	2009-04-14 03:15:43 +0000
@@ -124,6 +124,44 @@
             to_repo.texts.get_record_stream([('foo', revid)],
             'unordered', True).next().get_bytes_as('fulltext'))
 
+    def test_fetch_parent_inventories_at_stacking_boundary(self):
+        """Fetch to a stacked branch copies inventories for parents of
+        revisions at the stacking boundary.
+
+        This is necessary so that the server is able to determine the file-ids
+        altered by all revisions it contains, which means that it needs both
+        the inventory for any revision it has, and the inventories of all that
+        revision's parents.
+        """
+        to_repo = self.make_to_repository('to')
+        if not to_repo._format.supports_external_lookups:
+            raise TestNotApplicable("Need stacking support in the target.")
+        builder = self.make_branch_builder('branch')
+        builder.start_series()
+        builder.build_snapshot('base', None, [
+            ('add', ('', 'root-id', 'directory', ''))])
+        builder.build_snapshot('left', ['base'], [])
+        builder.build_snapshot('right', ['base'], [])
+        builder.build_snapshot('merge', ['left', 'right'], [])
+        builder.finish_series()
+        branch = builder.get_branch()
+        repo = self.make_to_repository('trunk')
+        trunk = repo.bzrdir.create_branch()
+        trunk.repository.fetch(branch.repository, 'left')
+        trunk.repository.fetch(branch.repository, 'right')
+        repo = self.make_to_repository('stacked')
+        stacked_branch = repo.bzrdir.create_branch()
+        stacked_branch.set_stacked_on_url(trunk.base)
+        stacked_branch.repository.fetch(branch.repository, 'merge')
+        unstacked_repo = stacked_branch.bzrdir.open_repository()
+        unstacked_repo.lock_read()
+        self.addCleanup(unstacked_repo.unlock)
+        self.assertFalse(unstacked_repo.has_revision('left'))
+        self.assertFalse(unstacked_repo.has_revision('right'))
+        self.assertEqual(
+            set([('left',), ('right',), ('merge',)]),
+            unstacked_repo.inventories.keys())
+
     def test_fetch_missing_basis_text(self):
         """If fetching a delta, we should die if a basis is not present."""
         tree = self.make_branch_and_tree('tree')




More information about the bazaar-commits mailing list