Rev 4166: Fix bzr failing to stack when a server requests it and the branch it is pushing from cannot stack but the branch it should stack on can. in http://people.ubuntu.com/~robertc/baz2.0/pending/bug-345169

Robert Collins robertc at robertcollins.net
Thu Mar 19 04:08:27 GMT 2009


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

------------------------------------------------------------
revno: 4166
revision-id: robertc at robertcollins.net-20090319040821-c1id0avkcpjvr0hw
parent: pqm at pqm.ubuntu.com-20090319035632-3o6ewx7kwnk42b63
committer: Robert Collins <robertc at robertcollins.net>
branch nick: bug-345169
timestamp: Thu 2009-03-19 15:08:21 +1100
message:
  Fix bzr failing to stack when a server requests it and the branch it is pushing from cannot stack but the branch it should stack on can.
=== modified file 'NEWS'
--- a/NEWS	2009-03-19 03:13:24 +0000
+++ b/NEWS	2009-03-19 04:08:21 +0000
@@ -83,6 +83,12 @@
 
 * ``merge --force`` works again. (Robert Collins, #342105)
 
+* Pushing a new branch to a server that has a stacking policy will now
+  upgrade from the local branch format when the stacking policy points at
+  a branch which is itself stackable, because we know the client can read
+  both branches, we know that the trunk for the project can be read too,
+  so the upgrade will not inconvenience users. (Robert Collins, #345169)
+
 * The GNU Changelog formatter is slightly improved in the case where
   the delta is empty, and now correctly claims not to support tags.
   (Andrea Bolognani)

=== modified file 'bzrlib/bzrdir.py'
--- a/bzrlib/bzrdir.py	2009-03-18 15:38:56 +0000
+++ b/bzrlib/bzrdir.py	2009-03-19 04:08:21 +0000
@@ -192,6 +192,8 @@
         transport.ensure_base()
         require_stacking = (stacked_on is not None)
         format = self.cloning_metadir(require_stacking)
+        # Bug: We create a metadir without knowing if it can support stacking,
+        # we should look up the policy needs first.
         result = format.initialize_on_transport(transport)
         repository_policy = None
         try:
@@ -387,8 +389,8 @@
                                     stack_on_pwd=None, require_stacking=False):
         """Return an object representing a policy to use.
 
-        This controls whether a new repository is created, or a shared
-        repository used instead.
+        This controls whether a new repository is created, and the format of
+        that repository, or some existing shared repository used instead.
 
         If stack_on is supplied, will not seek a containing shared repo.
 
@@ -408,8 +410,6 @@
                 if stack_on is not None:
                     stack_on_pwd = found_bzrdir.root_transport.base
                     stop = True
-                    note('Using default stacking branch %s at %s', stack_on,
-                         stack_on_pwd)
             # does it have a repository ?
             try:
                 repository = found_bzrdir.open_repository()
@@ -418,7 +418,9 @@
             else:
                 if ((found_bzrdir.root_transport.base !=
                      self.root_transport.base) and not repository.is_shared()):
+                    # Don't look higher, can't use a higher shared repo.
                     repository = None
+                    stop = True
                 else:
                     stop = True
             if not stop:
@@ -2833,14 +2835,15 @@
         # Always return a RemoteRepositoryFormat object, but if a specific bzr
         # repository format has been asked for, tell the RemoteRepositoryFormat
         # that it should use that for init() etc.
-        result =  remote.RemoteRepositoryFormat()
+        result = remote.RemoteRepositoryFormat()
         custom_format = getattr(self, '_repository_format', None)
         if custom_format:
-            # We will use the custom format to create repositories over the
-            # wire; expose its details like rich_root_data for code to query
             if isinstance(custom_format, remote.RemoteRepositoryFormat):
-                result._custom_format = custom_format._custom_format
+                return custom_format
             else:
+                # We will use the custom format to create repositories over the
+                # wire; expose its details like rich_root_data for code to
+                # query
                 result._custom_format = custom_format
         return result
 
@@ -3148,6 +3151,50 @@
 
         Creates the desired repository in the bzrdir we already have.
         """
+        stack_on = self._get_full_stack_on()
+        if stack_on:
+            # Stacking is desired. requested by the target, but does the place it
+            # points at support stacking? If it doesn't then we should
+            # not implicitly upgrade. We check this here.
+            format = self._bzrdir._format
+            if not (format.repository_format.supports_external_lookups
+                and format.get_branch_format().supports_stacking()):
+                # May need to upgrade - but only do if the target also
+                # supports stacking. Note that this currently wastes
+                # network round trips to check - but we only do this
+                # when the source can't stack so it will fade away
+                # as people do upgrade.
+                try:
+                    target_dir = BzrDir.open(stack_on,
+                        possible_transports=[self._bzrdir.root_transport])
+                except errors.NotBranchError:
+                    # Nothing there, don't change formats
+                    pass
+                else:
+                    try:
+                        target_branch = target_dir.open_branch()
+                    except errors.NotBranchError:
+                        # No branch, don't change formats
+                        pass
+                    else:
+                        branch_format = target_branch._format
+                        repo_format = target_branch.repository._format
+                        if not (branch_format.supports_stacking()
+                            and repo_format.supports_external_lookups):
+                            # Doesn't stack itself, don't force an upgrade
+                            pass
+                        else:
+                            # Does support stacking, use its format.
+                            format.repository_format = repo_format
+                            format.set_branch_format(branch_format)
+                            note('Source format does not support stacking, '
+                                'using format: \'%s\'\n  %s\n',
+                                branch_format.get_format_description(),
+                                repo_format.get_format_description())
+            if not self._require_stacking:
+                # We have picked up automatic stacking somewhere.
+                note('Using default stacking branch %s at %s', self._stack_on,
+                    self._stack_on_pwd)
         repository = self._bzrdir.create_repository(shared=shared)
         self._add_fallback(repository,
                            possible_transports=[self._bzrdir.transport])

=== modified file 'bzrlib/tests/blackbox/test_push.py'
--- a/bzrlib/tests/blackbox/test_push.py	2009-03-16 05:33:31 +0000
+++ b/bzrlib/tests/blackbox/test_push.py	2009-03-19 04:08:21 +0000
@@ -392,6 +392,23 @@
         self.assertContainsRe(err,
                               'Using default stacking branch stack_on at .*')
 
+    def test_push_stacks_with_default_stacking_if_target_is_stackable(self):
+        self.make_branch('stack_on', format='1.6')
+        self.make_bzrdir('.').get_config().set_default_stack_on('stack_on')
+        self.make_branch('from', format='pack-0.92')
+        out, err = self.run_bzr('push -d from to')
+        branch = Branch.open('to')
+        self.assertEqual('../stack_on', branch.get_stacked_on_url())
+
+    def test_push_does_not_change_format_with_default_if_target_cannot(self):
+        self.make_branch('stack_on', format='pack-0.92')
+        self.make_bzrdir('.').get_config().set_default_stack_on('stack_on')
+        self.make_branch('from', format='pack-0.92')
+        out, err = self.run_bzr('push -d from to')
+        branch = Branch.open('to')
+        self.assertRaises(errors.UnstackableBranchFormat,
+            branch.get_stacked_on_url)
+
     def test_push_doesnt_create_broken_branch(self):
         """Pushing a new standalone branch works even when there's a default
         stacking policy at the destination.




More information about the bazaar-commits mailing list