Rev 5561: Bug #375013, Basic support for filling in basis inventories in http://bazaar.launchpad.net/~jameinel/bzr/2.3-commit-to-stacked

John Arbash Meinel john at arbash-meinel.com
Fri Dec 3 22:09:29 GMT 2010


At http://bazaar.launchpad.net/~jameinel/bzr/2.3-commit-to-stacked

------------------------------------------------------------
revno: 5561
revision-id: john at arbash-meinel.com-20101203220912-5ryprs3cpss3ydxb
parent: john at arbash-meinel.com-20101203200232-22082dxipu67v89m
fixes bug(s): https://launchpad.net/bugs/375013
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: 2.3-commit-to-stacked
timestamp: Fri 2010-12-03 16:09:12 -0600
message:
  Bug #375013, Basic support for filling in basis inventories
  
  In short, when we go to commit to a stacked repository, we just check for the
  presence of any required parent inventories. If they aren't there, we fetch
  them from whatever fallbacks we have. We are able to use the Stream interface
  which is what the stacking code uses today anyway.
  The write-group handling is a bit ugly, but I'll bring that up in review.
-------------- next part --------------
=== modified file 'bzrlib/commit.py'
--- a/bzrlib/commit.py	2010-11-10 02:01:33 +0000
+++ b/bzrlib/commit.py	2010-12-03 22:09:12 +0000
@@ -432,6 +432,7 @@
             self.rev_id = self.builder.commit(self.message)
 
         except Exception, e:
+            import pdb; pdb.set_trace()
             mutter("aborting commit write group because of exception:")
             trace.log_exception_quietly()
             note("aborting commit write group: %r" % (e,))

=== modified file 'bzrlib/repository.py'
--- a/bzrlib/repository.py	2010-12-03 20:00:29 +0000
+++ b/bzrlib/repository.py	2010-12-03 22:09:12 +0000
@@ -186,6 +186,33 @@
         """
         if not self.repository._fallback_repositories:
             return
+        # This is a stacked repo, we need to make sure we have the parent
+        # inventories for the parents.
+        parent_keys = [(p,) for p in self.parents]
+        parent_map = self.repository.inventories._index.get_parent_map(parent_keys)
+        missing_parent_keys = set([pk for pk in parent_keys
+                                       if pk not in parent_map])
+        fallback_repos = list(reversed(self.repository._fallback_repositories))
+        # Right now, we are already in a write group, and insert_stream needs
+        # its own write group. Ideally we would just share it, but the current
+        # mechanism is suspend+resume.
+        # However, we don't want to immediately resume the write group,
+        # because, insert_stream finalizes the commit.
+        saved_resume_tokens = self.repository.suspend_write_group()
+
+        missing_keys = [('inventories', pk[0])
+                        for pk in missing_parent_keys]
+        resume_tokens = []
+        while missing_keys and fallback_repos:
+            fallback_repo = fallback_repos.pop()
+            source = fallback_repo._get_source(self.repository._format)
+            sink = self.repository._get_sink()
+            stream = source.get_stream_for_missing_keys(missing_keys)
+            resume_tokens, missing_keys = sink.insert_stream(
+                stream, self.repository._format, resume_tokens)
+        if resume_tokens or missing_keys:
+            raise RuntimeError('failure will robinson')
+        self.repository.resume_write_group(saved_resume_tokens)
 
     def commit(self, message):
         """Make the actual commit.

=== modified file 'bzrlib/tests/per_repository_reference/test_commit_with_stacking.py'
--- a/bzrlib/tests/per_repository_reference/test_commit_with_stacking.py	2010-12-03 20:02:32 +0000
+++ b/bzrlib/tests/per_repository_reference/test_commit_with_stacking.py	2010-12-03 22:09:12 +0000
@@ -38,6 +38,8 @@
         # We open the repository without fallbacks to ensure the data is
         # locally true
         stacked_only_repo = stacked_tree.bzrdir.open_repository()
+        stacked_only_repo.lock_read()
+        self.addCleanup(stacked_only_repo.unlock)
         r1_key = ('initial-rev-id',)
         self.assertEqual([r1_key],
             sorted(stacked_only_repo.inventories.get_parent_map([r1_key])))
@@ -51,8 +53,9 @@
     def test_merge_commit(self):
         base_tree, stacked_tree = self.make_stacked_target()
         self.build_tree_contents([('base/f1.txt', 'new content\n')])
-        base_tree.commit('second base', 'base2-rev-id')
-        to_be_merged_tree = base_tree.bzrdir.sprout('merged')
+        base_tree.commit('second base', rev_id='base2-rev-id')
+        to_be_merged_tree = base_tree.bzrdir.sprout('merged'
+            ).open_workingtree()
         self.build_tree(['merged/f2.txt'])
         to_be_merged_tree.add(['f2.txt'], ['f2.txt-id'])
         to_be_merged_tree.commit('new-to-be-merged', rev_id='to-merge-rev-id')
@@ -64,6 +67,8 @@
         # which is in base. So we should have its inventory, but not its
         # revision-id.
         stacked_only_repo = stacked_tree.bzrdir.open_repository()
+        stacked_only_repo.lock_read()
+        self.addCleanup(stacked_only_repo.unlock)
         r1_key = ('initial-rev-id',)
         r2_key = ('base2-rev-id',)
         r3_key = ('to-merge-rev-id',)
@@ -77,7 +82,7 @@
     def test_merge_from_master(self):
         base_tree, stacked_tree = self.make_stacked_target()
         self.build_tree_contents([('base/f1.txt', 'new content\n')])
-        base_tree.commit('second base', 'base2-rev-id')
+        base_tree.commit('second base', rev_id='base2-rev-id')
         stacked_tree.merge_from_branch(base_tree.branch)
         stacked_tree.commit('merge', rev_id='merged-rev-id')
         r1_key = ('initial-rev-id',)
@@ -87,6 +92,8 @@
         # We shouldn't have any of the base revisions in the local repo, but we
         # should have both base inventories.
         stacked_only_repo = stacked_tree.bzrdir.open_repository()
+        stacked_only_repo.lock_read()
+        self.addCleanup(stacked_only_repo.unlock)
         self.assertEqual(sorted([r3_key]),
             sorted(stacked_only_repo.revisions.get_parent_map(all_keys)))
         self.assertEqual(sorted(all_keys),
@@ -99,15 +106,19 @@
         stacked_tree.add(['f2.txt'], ['f2.txt-id'])
         stacked_tree.commit('add f2', rev_id='stacked-rev-id')
         stacked2_tree = stacked_tree.bzrdir.sprout('stacked2',
+                            revision_id='initial-rev-id',
                             stacked=True).open_workingtree()
-        # stacked2 is stacked on stacked, but we revert its content to rev1, so
-        # that it needs to pull the basis information from a
-        # fallback-of-fallback.
-        stacked2_tree.update(revision='initial-rev-id')
+        # stacked2 is stacked on stacked, but its content is rev1, so
+        # it needs to pull the basis information from a fallback-of-fallback.
         self.build_tree(['stacked2/f3.txt'])
         stacked2_tree.add(['f3.txt'], ['f3.txt-id'])
-        stacked_tree.commit('add f3', rev_id='stacked2-rev-id')
+        stacked2_tree.commit('add f3', rev_id='stacked2-rev-id')
         stacked2_only_repo = stacked2_tree.bzrdir.open_repository()
+        stacked2_only_repo.lock_read()
+        self.addCleanup(stacked2_only_repo.unlock)
         r1_key = ('initial-rev-id',)
         self.assertEqual([r1_key],
             sorted(stacked2_only_repo.inventories.get_parent_map([r1_key])))
+
+# TOOD: We need to run the above tests for when the source and/or the target
+#       are remote repositories.

=== modified file 'doc/en/release-notes/bzr-2.3.txt'
--- a/doc/en/release-notes/bzr-2.3.txt	2010-12-02 16:24:54 +0000
+++ b/doc/en/release-notes/bzr-2.3.txt	2010-12-03 22:09:12 +0000
@@ -32,6 +32,10 @@
 .. Fixes for situations where bzr would previously crash or give incorrect
    or undesirable results.
 
+* You are now able to commit directly to a stacked branch. Any needed
+  parent inventories will be filled in as part of the commit process.
+  (John Arbash Meinel, #375013)
+
 Documentation
 *************
 



More information about the bazaar-commits mailing list