Improvement to how subrepos are found?

Martin Geisler mg at
Tue Jan 4 04:10:55 CST 2011

Hi everybody,

My client sent me the suggestion below, and I think it has some
interesting elements. The proposal is to make the right-hand side of the
.hgsub file a fallback location instead of being the main location.

So when you have a .hgsub file with

  libs/foo =

then the first clone will grab libfoo from the URL.

But when you make a new clone of the clone, then the subrepo will be
cloned from libs/foo. So

  hg clone A B

will make Mercurial do the equivalent of

  mkdir B/libs
  hg clone A/libs/foo B/libs/foo

when it checkouts the subrepo.

This has a chance of working for 'hg clone' since the checkout done as
part of the clone has access to the clone URL. Later 'hg update' calls
could use the default path, if one is configured.

This would also solve the problem of not being able make clones of
clones containing subrepos that use relative paths. If a .hgsub file

  sub = ../mysub

then 'hg clone A B' does not create a B clone with the same structure as
the A clone -- the B clone will naturally miss the B/../mysub
repository. That would be okay if a later 'hg clone B C' would look
inside B for the subrepo.

> Hi Martin,
> I would like to have a small discussion about an improvement in
> subrepo path remapping. A consequence of what we have done so far is
> the fact that when you clone a clone, the subrepos aren't taken from
> the clone but from the original repos. You can see that here:
> clone of team repo:
>   bash-3.2$ hg clone ../team/parent/ clone_of_parent
>   updating to branch default
>   pulling subrepo foo from /home/sedlock/team/foo
> clone of clone:
>   bash-3.2$ hg clone clone_of_parent/ clone_of_clone
>   updating to branch default
>   pulling subrepo foo from /home/sedlock/team/foo
> This is not so great: what one would normally want is that the
> subrepos are taken from the clone. After all, they are already there.
> Why go back to the remote location?

(I pointed out that SVN subrepos must to back to the source since a SVN
working copy cannot be used as a source for new checkouts.)

> I knew about that and thought an easy solution was simply to copy the
> clone in the operating system rather than clone in Mercurial. The
> downside is that the stores aren't hardlinked.
> I thought that at least in linux this could be done with the -al
> option for copy (with the source repo bare), but I'm not so confident.
> I made a quick try and it seemed to work:
>   bash-3.2$ cp -al clone_of_parent/ copy_of_clone
>   bash-3.2$ cd copy_of_clone/
>   bash-3.2$ hg parent
>   changeset:   2:3ac38a760cfc
>   tag:         tip
>   user:        sedlock
>   date:        Thu Nov 11 17:33:54 2010 +0100
>   summary:     foo
>   bash-3.2$ touch file1.txt
>   bash-3.2$ hg st
>   ? file1.txt
>   bash-3.2$ hg commit -A -m file1
>   adding file1.txt
>   bash-3.2$ hg parent
>   changeset:   3:7224a3822277
>   tag:         tip
>   user:        sedlock
>   date:        Thu Dec 23 14:08:24 2010 +0100
>   summary:     file1
>   bash-3.2$ hg parent -R ../clone_of_parent/
>   changeset:   2:3ac38a760cfc
>   tag:         tip
>   user:        sedlock
>   date:        Thu Nov 11 17:33:54 2010 +0100
>   summary:     foo
> Could you comment on this "copy with hardlink" technique? I suspect
> Mercurial might not hard link every file in the store, which leads me
> to be suspicious. There is also the problem that if the repo is not
> bare, the working files would also be hardlinked, which I think is not
> good.

(I pointed out that 'hg help clone' mentions 'cp -al' too, albeit with a
warning about a potential problem with MQ that I could not reproduce.)

> Anyway, even if this does work for linux, we are left with no solution
> in windows. So, again, back to the point that if the subrepos are
> actually in the source repo, it seems counterintuitive to go somewhere
> else for them.

(I told him about the relink extension here.)

> So what about this idea: By default, if clone or pull (via update in
> the parent) find subrepos in the source parent repo (i.e. exactly
> where they should be without applying subrepo path remapping!), they
> ignore the remapping rules. Only in the case that the subrepos are not
> there are the rules applied and the "official" location used. This
> leads to the following natural scenario:
> 1) The user makes a clone of the parent team repo. Since the subrepos
>    are not inside this repo, they are taken from the locations
>    specified in the remapping rules.
> 2) He decides he needs a clone and, rather than going back to the
>    parent team repo, clones his clone. Since the subrepos are inside
>    the clone, they are taken from there rather than from the
>    "official" locations.
> 3) He now decides to pull from the parent team repo in his 2nd clone -
>    and update. The update triggers a pull of the subrepos, and now,
>    since again the subrepos aren't in the parent, they are taken from
>    the locations specified in the remapping rules.
> This seems like intuitive behavior to me. If it doesn't seem that way
> to you or others, I'd at least like to see an option to clone and pull
> like "use source subrepos", which has the same effect: the subrepos in
> the source repo are used if they exist.
> What do you think?

Martin Geisler

aragost Trifork
Professional Mercurial support

More information about the Mercurial-devel mailing list