[PATCH 1 of 2] subrepo: look for local pull source first

Martin Geisler mg at aragost.com
Fri Mar 25 10:07:54 CDT 2011


# HG changeset patch
# User Martin Geisler <mg at aragost.com>
# Date 1300989966 -3600
# Node ID a8019f68e1463d6b1d5406f5f22d17f9aa8c828c
# Parent  e45780ac829283080ad6b5a5e064e59a163c08d6
subrepo: look for local pull source first

With this change, a subrepository will always try to find the
changesets it needs in a repository relative to the pull source of the
top-most parent repository. So if we have

  repo/
    sub/

and make a clone with 'hg clone repo clone', then clone/sub will pull
in changesets from repo/sub, regardless of what the .hgsub file says.

This will allow you to make clones of repositories where the .hgsub
file uses 'sub = ../sub' paths. The problem with these repositories is
that they are structurally different from where they were cloned from.
By looking for the subrepository in-place, we avoid this problem.

It will also allow you to make clones while offline, even if a
repository uses subrepositories that are specified with remote URLs.

Note that this wont help in creating hardlinks because subrepositories
are always created empty and then filled with changesets using pull,
the initial clone will not be hardlinked.

diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py
--- a/mercurial/subrepo.py
+++ b/mercurial/subrepo.py
@@ -433,11 +433,25 @@
     def _get(self, state):
         source, revision, kind = state
         if revision not in self._repo:
-            self._repo._subsource = source
-            srcurl = _abssource(self._repo)
+            try:
+                # look for a suitable parent repository first
+                parent = self._repo
+                while hasattr(parent, '_subparent'):
+                    parent = parent._subparent
+                parenturl = _abssource(parent, abort=False)
+                if not parenturl or '://' in parenturl:
+                    raise error.RepoError()
+                srcurl = os.path.join(parenturl, subrelpath(self))
+                other = hg.repository(self._repo.ui, srcurl)
+                other.lookup(revision)
+            except error.RepoError:
+                # found no parent repository
+                self._repo._subsource = source
+                srcurl = _abssource(self._repo)
+                other = hg.repository(self._repo.ui, srcurl)
+
             self._repo.ui.status(_('pulling subrepo %s from %s\n')
                                  % (subrelpath(self), srcurl))
-            other = hg.repository(self._repo.ui, srcurl)
             self._repo.pull(other)
             bookmarks.updatefromremote(self._repo.ui, self._repo, other)
 
diff --git a/tests/test-subrepo-deep-nested-change.t b/tests/test-subrepo-deep-nested-change.t
--- a/tests/test-subrepo-deep-nested-change.t
+++ b/tests/test-subrepo-deep-nested-change.t
@@ -27,7 +27,7 @@
   $ echo "sub1 = ../sub1" > main/.hgsub
   $ hg clone sub1 main/sub1
   updating to branch default
-  pulling subrepo sub2 from $TESTTMP/sub2
+  pulling subrepo sub2 from $TESTTMP/sub1/sub2
   requesting all changes
   adding changesets
   adding manifests


More information about the Mercurial-devel mailing list