subrepos: support remapping of .hgsub source paths
authorMartin Geisler <mg@lazybytes.net>
Thu, 15 Jul 2010 18:10:05 +0200
changeset 11775 a8614c5a5e9a
parent 11774 91c4e6d2c9e5
child 11780 3cdd6fdc3d9e
subrepos: support remapping of .hgsub source paths Given a .hgsub file containing lib/libfoo = http://server/libfoo the 'lib/libfoo' subrepo will be cloned from 'http://server/libfoo'. This changeset introduces a remapping mechanism whereby the source paths (the right-hand sides) in the .hgsub file can be remapped. This subpaths section [subpaths] http://server = /local will result in the 'lib/libfoo' subrepo being cloned from '/local/libfoo' instead of from 'http://server/libfoo'. The patterns (left-hand sides) are really regular expressions and the replacement strings (right-hand sides) can refer to matched groups using normal backreferences. This can be used for more complicated replacements such as [subpaths] http://server/(.*)-hg/ = http://hg.server/\1/ which replaces 'http://server/foo-hg/' with 'http://hg.server/foo/'. All patterns are applied in the order by which they are listed in the config files.
mercurial/context.py
mercurial/subrepo.py
tests/test-subrepo-paths
tests/test-subrepo-paths.out
--- a/mercurial/context.py	Tue Aug 10 16:55:38 2010 +0200
+++ b/mercurial/context.py	Thu Jul 15 18:10:05 2010 +0200
@@ -75,7 +75,7 @@
 
     @propertycache
     def substate(self):
-        return subrepo.state(self)
+        return subrepo.state(self, self._repo.ui)
 
     def __contains__(self, key):
         return key in self._manifest
--- a/mercurial/subrepo.py	Tue Aug 10 16:55:38 2010 +0200
+++ b/mercurial/subrepo.py	Thu Jul 15 18:10:05 2010 +0200
@@ -12,7 +12,7 @@
 
 nullstate = ('', '', 'empty')
 
-def state(ctx):
+def state(ctx, ui):
     """return a state dict, mapping subrepo paths configured in .hgsub
     to tuple: (source from .hgsub, revision from .hgsubstate, kind
     (key in types dict))
@@ -27,6 +27,9 @@
     if '.hgsub' in ctx:
         read('.hgsub')
 
+    for path, src in ui.configitems('subpaths'):
+        p.set('subpaths', path, src, ui.configsource('subpaths', path))
+
     rev = {}
     if '.hgsubstate' in ctx:
         try:
@@ -45,6 +48,14 @@
                 raise util.Abort(_('missing ] in subrepo source'))
             kind, src = src.split(']', 1)
             kind = kind[1:]
+
+        for pattern, repl in p.items('subpaths'):
+            try:
+                src = re.sub(pattern, repl, src, 1)
+            except re.error, e:
+                raise util.Abort(_("bad subrepository pattern in %s: %s")
+                                 % (p.source('subpaths', pattern), e))
+
         state[path] = (src.strip(), rev.get(path, ''), kind)
 
     return state
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-subrepo-paths	Thu Jul 15 18:10:05 2010 +0200
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+hg init outer
+cd outer
+
+echo 'sub = http://example.net/libfoo' > .hgsub
+hg add .hgsub
+
+echo '% hg debugsub with no remapping'
+hg debugsub
+
+cat > .hg/hgrc <<EOF
+[subpaths]
+http://example.net = ssh://localhost
+EOF
+
+echo '% hg debugsub with remapping'
+hg debugsub
+
+echo '% test bad subpaths pattern'
+cat > .hg/hgrc <<EOF
+[subpaths]
+.* = \1
+EOF
+hg debugsub 2>&1 | "$TESTDIR/filtertmp.py"
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-subrepo-paths.out	Thu Jul 15 18:10:05 2010 +0200
@@ -0,0 +1,10 @@
+% hg debugsub with no remapping
+path sub
+ source   http://example.net/libfoo
+ revision 
+% hg debugsub with remapping
+path sub
+ source   ssh://localhost/libfoo
+ revision 
+% test bad subpaths pattern
+abort: bad subrepository pattern in $HGTMP/test-subrepo-paths/outer/.hg/hgrc:2: invalid group reference