Rev 3237: Add a shallow parameter to bzrdir.sprout, which involved fixing a lateny bug in pack to pack fetching with ghost discovery. in http://people.ubuntu.com/~robertc/baz2.0/shallow-branch

Robert Collins robertc at robertcollins.net
Thu Feb 28 05:56:12 GMT 2008


At http://people.ubuntu.com/~robertc/baz2.0/shallow-branch

------------------------------------------------------------
revno: 3237
revision-id:robertc at robertcollins.net-20080228055607-moxe31bg70mi88ho
parent: robertc at robertcollins.net-20080227114240-8r0okhnf1q3oh5kn
committer: Robert Collins <robertc at robertcollins.net>
branch nick: StackableBranch
timestamp: Thu 2008-02-28 16:56:07 +1100
message:
  Add a shallow parameter to bzrdir.sprout, which involved fixing a lateny bug in pack to pack fetching with ghost discovery.
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/branch.py               branch.py-20050309040759-e4baf4e0d046576e
  bzrlib/bzrdir.py               bzrdir.py-20060131065624-156dfea39c4387cb
  bzrlib/repository.py           rev_storage.py-20051111201905-119e9401e46257e3
  bzrlib/tests/branch_implementations/test_stacking.py test_stacking.py-20080214020755-msjlkb7urobwly0f-1
=== modified file 'NEWS'
--- a/NEWS	2008-02-27 11:42:40 +0000
+++ b/NEWS	2008-02-28 05:56:07 +0000
@@ -68,6 +68,9 @@
 
   INTERNALS:
 
+    * ``bzrlib.bzrdir.BzrDir.sprout`` now accepts ``shallow`` to control
+      creating shallow branches. (Robert Collins)
+
     * New module ``tools/package_mf.py`` provide custom module finder for
       python packages (improves standard python library's modulefinder.py)
       used by ``setup.py`` script while building standalone bzr.exe.

=== modified file 'bzrlib/branch.py'
--- a/bzrlib/branch.py	2008-02-27 11:42:40 +0000
+++ b/bzrlib/branch.py	2008-02-28 05:56:07 +0000
@@ -19,6 +19,7 @@
 
 from bzrlib.lazy_import import lazy_import
 lazy_import(globals(), """
+from itertools import chain
 from warnings import warn
 
 import bzrlib
@@ -1883,10 +1884,14 @@
 
 class BzrBranch7(BzrBranch5):
 
+    def _get_fallback_repository(self, url):
+        """Get the repository we fallback to at url."""
+        return bzrdir.BzrDir.open(url).open_branch().repository
+
     def _activate_fallback_location(self, url):
         """Activate the branch/repository from url as a fallback repository."""
-        new_repo = bzrdir.BzrDir.open(url).open_branch().repository
-        self.repository.add_fallback_repository(new_repo)
+        self.repository.add_fallback_repository(
+            self._get_fallback_repository(url))
 
     def _open_hook(self):
         try:
@@ -2028,11 +2033,22 @@
     def set_stacked_on(self, url):
         self._check_stackable_repo()
         if not url:
+            try:
+                old_url = self.get_stacked_on()
+            except (errors.NotStacked, errors.UnstackableBranchFormat,
+                errors.UnstackableRepositoryFormat):
+                return
             url = ''
             # repositories don't offer an interface to remove fallback
             # repositories today; take the conceptually simpler option and just
             # reopen it.
             self.repository = self.bzrdir.find_repository()
+            # for every revision reference the branch has, ensure it is pulled
+            # in.
+            source_repository = self._get_fallback_repository(old_url)
+            for revision_id in chain([self.last_revision()],
+                self.tags.get_reverse_tag_dict()):
+                self.repository.fetch(source_repository, revision_id, find_ghosts=True)
         else:
             self._activate_fallback_location(url)
         # write this out after the repository is stacked to avoid setting a

=== modified file 'bzrlib/bzrdir.py'
--- a/bzrlib/bzrdir.py	2008-02-27 11:42:40 +0000
+++ b/bzrlib/bzrdir.py	2008-02-28 05:56:07 +0000
@@ -890,7 +890,7 @@
 
     def sprout(self, url, revision_id=None, force_new_repo=False,
                recurse='down', possible_transports=None,
-               accelerator_tree=None, hardlink=False):
+               accelerator_tree=None, hardlink=False, shallow=False):
         """Create a copy of this bzrdir prepared for use as a new line of
         development.
 
@@ -909,6 +909,8 @@
             content is different.
         :param hardlink: If true, hard-link files from accelerator_tree,
             where possible.
+        :param shallow: If true, create a shallow branch referring to the
+            location of this control directory.
         """
         target_transport = get_transport(url, possible_transports)
         target_transport.ensure_base()
@@ -917,6 +919,15 @@
         try:
             source_branch = self.open_branch()
             source_repository = source_branch.repository
+            if shallow:
+                shallow_branch_url = self.root_transport.base
+            else:
+                shallow_branch_url = None
+                try:
+                    shallow_branch_url = source_branch.get_stacked_on()
+                except (errors.NotStacked, errors.UnstackableBranchFormat,
+                    errors.UnstackableRepositoryFormat):
+                    shallow_branch_url = None
         except errors.NotBranchError:
             source_branch = None
             try:
@@ -935,6 +946,16 @@
         elif source_repository is None and result_repo is None:
             # no repo available, make a new one
             result.create_repository()
+        elif shallow_branch_url:
+            if result_repo is None:
+                result_repo = source_repository._format.initialize(result)
+            stacked_dir = BzrDir.open(shallow_branch_url)
+            try:
+                stacked_repo = stacked_dir.open_branch().repository
+            except errors.NotBranchError:
+                stacked_repo = stacked_dir.open_repository()
+            result_repo.add_fallback_repository(stacked_repo)
+            result_repo.fetch(source_repository, revision_id=revision_id)
         elif source_repository is not None and result_repo is None:
             # have source, and want to make a new target repo
             result_repo = source_repository.sprout(result,
@@ -948,9 +969,11 @@
                 # so we can override the copy method
                 result_repo.fetch(source_repository, revision_id=revision_id)
         if source_branch is not None:
-            source_branch.sprout(result, revision_id=revision_id)
+            result_branch = source_branch.sprout(result, revision_id=revision_id)
         else:
-            result.create_branch()
+            result_branch = result.create_branch()
+        if shallow_branch_url:
+            result_branch.set_stacked_on(shallow_branch_url)
         if isinstance(target_transport, LocalTransport) and (
             result_repo is None or result_repo.make_working_trees()):
             wt = result.create_workingtree(accelerator_tree=accelerator_tree,
@@ -1124,8 +1147,11 @@
 
     def sprout(self, url, revision_id=None, force_new_repo=False,
                possible_transports=None, accelerator_tree=None,
-               hardlink=False):
+               hardlink=False, shallow=False):
         """See BzrDir.sprout()."""
+        if shallow:
+            raise errors.UnstackableBranchFormat(
+                self._format, self.root_transport.base)
         from bzrlib.workingtree import WorkingTreeFormat2
         self._make_tail(url)
         result = self._format._initialize_for_clone(url)

=== modified file 'bzrlib/repository.py'
--- a/bzrlib/repository.py	2008-02-22 01:53:18 +0000
+++ b/bzrlib/repository.py	2008-02-28 05:56:07 +0000
@@ -18,6 +18,7 @@
 
 from bzrlib.lazy_import import lazy_import
 lazy_import(globals(), """
+from itertools import chain
 import re
 import time
 
@@ -2767,7 +2768,9 @@
             # to fetch from all packs to one without
             # inventory parsing etc, IFF nothing to be copied is in the target.
             # till then:
-            revision_ids = self.source.all_revision_ids()
+            source_revision_ids = frozenset(self.source.all_revision_ids())
+            revision_ids = source_revision_ids - \
+                frozenset(self.target.get_parent_map(source_revision_ids))
             # implementing the TODO will involve:
             # - detecting when all of a pack is selected
             # - avoiding as much as possible pre-selection, so the
@@ -2807,17 +2810,23 @@
         if not find_ghosts and revision_id is not None:
             return self._walk_to_common_revisions([revision_id])
         elif revision_id is not None:
-            source_ids = self.source.get_ancestry(revision_id)
-            assert source_ids[0] is None
-            source_ids.pop(0)
+            # Find ghosts: search for revisions pointing from one repository to
+            # the other, and viceversa, anywhere in the history of revision_id.
+            graph = self.target.get_graph(other_repository=self.source)
+            found_ids = frozenset(chain(*graph._make_breadth_first_searcher(
+                [revision_id])))
+            # Double query here: should be able to avoid this by changing the
+            # graph api further.
+            result_set = found_ids - frozenset(
+                self.target.get_graph().get_parent_map(found_ids))
         else:
             source_ids = self.source.all_revision_ids()
-        # source_ids is the worst possible case we may need to pull.
-        # now we want to filter source_ids against what we actually
-        # have in target, but don't try to check for existence where we know
-        # we do not have a revision as that would be pointless.
-        target_ids = set(self.target.all_revision_ids())
-        result_set = set(source_ids).difference(target_ids)
+            # source_ids is the worst possible case we may need to pull.
+            # now we want to filter source_ids against what we actually
+            # have in target, but don't try to check for existence where we know
+            # we do not have a revision as that would be pointless.
+            target_ids = set(self.target.all_revision_ids())
+            result_set = set(source_ids).difference(target_ids)
         return self.source.revision_ids_to_search_result(result_set)
 
 

=== modified file 'bzrlib/tests/branch_implementations/test_stacking.py'
--- a/bzrlib/tests/branch_implementations/test_stacking.py	2008-02-15 03:26:10 +0000
+++ b/bzrlib/tests/branch_implementations/test_stacking.py	2008-02-28 05:56:07 +0000
@@ -44,3 +44,17 @@
         self.assertEqual(target.base, branch.get_stacked_on())
         branch.set_stacked_on(None)
         self.assertRaises(errors.NotStacked, branch.get_stacked_on)
+
+    def test_set_stacked_on_fetches(self):
+        # We have a mainline
+        trunk_tree = self.make_branch_and_tree('mainline')
+        trunk_revid = trunk_tree.commit('mainline')
+        # and make branch from it which is shallow
+        try:
+            new_dir = trunk_tree.bzrdir.sprout('newbranch', shallow=True)
+        except (errors.UnstackableBranchFormat, errors.UnstackableRepositoryFormat):
+            # not a testable combination.
+            return
+        new_tree = new_dir.open_workingtree()
+        new_tree.commit('something local')
+



More information about the bazaar-commits mailing list