diff --git a/hgwebdir.cgi b/hgwebdir.cgi --- a/hgwebdir.cgi +++ b/hgwebdir.cgi @@ -32,6 +32,7 @@ import mercurial.hgweb.wsgicgi as wsgicg # virtual/path2 = /real/path2 # virtual/root = /real/root/* # / = /real/root2/* +# virtual/root2 = /real/root2/** # # [collections] # /prefix/to/strip/off = /root/of/tree/full/of/repos @@ -41,15 +42,18 @@ import mercurial.hgweb.wsgicgi as wsgicg # * First two lines mount one repository into one virtual path, like # '/real/path1' into 'virtual/path1'. # -# * The third entry tells every mercurial repository found in -# '/real/root', recursively, should be mounted in 'virtual/root'. This -# format is preferred over the [collections] one, using absolute paths -# as configuration keys is not supported on every platform (including -# Windows). +# * The third entry mounts every mercurial repository found in '/real/root' +# in 'virtual/root'. This format is preferred over the [collections] one, +# since using absolute paths as configuration keys is not support on every +# platform (especially on Windows). # -# * The last entry is a special case mounting all repositories in +# * The fourth entry is a special case mounting all repositories in # /'real/root2' in the root of the virtual directory. # +# * The fifth entry recursively finds all repositories under the real root, +# and mounts them using their relative path (to given real root) under the +# virtual root. +# # collections example: say directory tree /foo contains repos /foo/bar, # /foo/quux/baz. Give this config section: # [collections] diff --git a/mercurial/hgweb/hgwebdir_mod.py b/mercurial/hgweb/hgwebdir_mod.py --- a/mercurial/hgweb/hgwebdir_mod.py +++ b/mercurial/hgweb/hgwebdir_mod.py @@ -54,13 +54,18 @@ class hgwebdir(object): paths = cleannames(cp.items('paths')) for prefix, root in paths: roothead, roottail = os.path.split(root) - if roottail != '*': + # "foo = /bar/*" makes every subrepo of /bar/ to be + # mounted as foo/subrepo + # and "foo = /bar/**" does even recurse inside the + # subdirectories, remember to use it without working dir. + try: + recurse = {'*': False, '**': True}[roottail] + except KeyError: self.repos.append((prefix, root)) continue - # "foo = /bar/*" makes every subrepo of /bar/ to be - # mounted as foo/subrepo roothead = os.path.normpath(roothead) - for path in util.walkrepos(roothead, followsym=True): + for path in util.walkrepos(roothead, followsym=True, + recurse=recurse): path = os.path.normpath(path) name = util.pconvert(path[len(roothead):]).strip('/') if prefix: diff --git a/mercurial/util.py b/mercurial/util.py --- a/mercurial/util.py +++ b/mercurial/util.py @@ -1876,7 +1876,7 @@ def ellipsis(text, maxlength=400): else: return "%s..." % (text[:maxlength-3]) -def walkrepos(path, followsym=False, seen_dirs=None): +def walkrepos(path, followsym=False, seen_dirs=None, recurse=False): '''yield every hg repository under path, recursively.''' def errhandler(err): if err.filename == path: @@ -1901,11 +1901,16 @@ def walkrepos(path, followsym=False, see _add_dir_if_not_there(seen_dirs, path) for root, dirs, files in os.walk(path, topdown=True, onerror=errhandler): if '.hg' in dirs: - dirs[:] = [] # don't descend further yield root # found a repository - qroot = os.path.join(root, '.hg', 'patches') - if os.path.isdir(os.path.join(qroot, '.hg')): - yield qroot # we have a patch queue repo here + if recurse: + # avoid recursing inside the .hg directory + # the mq repository is added in any case + dirs.remove('.hg') + qroot = os.path.join(root, '.hg', 'patches') + if os.path.isdir(os.path.join(qroot, '.hg')): + yield qroot # we have a patch queue repo here + else: + dirs[:] = [] # don't descend further elif followsym: newdirs = [] for d in dirs: diff --git a/tests/test-hgwebdir b/tests/test-hgwebdir --- a/tests/test-hgwebdir +++ b/tests/test-hgwebdir @@ -8,16 +8,25 @@ cd webdir hg init a echo a > a/a hg --cwd a ci -Ama -d'1 0' +# create a mercurial queue repository +hg --cwd a qinit --config extensions.hgext.mq= -c hg init b echo b > b/b hg --cwd b ci -Amb -d'2 0' +# create a nested repository +cd b +hg init d +echo d > d/d +hg --cwd d ci -Amd -d'3 0' +cd .. + hg init c echo c > c/c hg --cwd c ci -Amc -d'3 0' + root=`pwd` - cd .. cat > paths.conf < paths.conf < collections.conf <> $DAEMON_PIDS -echo % should succeed +echo % collections: should succeed "$TESTDIR/get-with-headers.py" localhost:$HGPORT2 '/?style=raw' "$TESTDIR/get-with-headers.py" localhost:$HGPORT2 '/a/file/tip/a?style=raw' "$TESTDIR/get-with-headers.py" localhost:$HGPORT2 '/b/file/tip/b?style=raw' diff --git a/tests/test-hgwebdir.out b/tests/test-hgwebdir.out --- a/tests/test-hgwebdir.out +++ b/tests/test-hgwebdir.out @@ -1,5 +1,6 @@ adding a adding b +adding d adding c % should give a 404 - file does not exist 404 Not Found @@ -32,6 +33,11 @@ 200 Script output follows /coll/a/ /coll/b/ /coll/c/ +/rcoll/a/ +/rcoll/a/.hg/patches/ +/rcoll/b/ +/rcoll/b/d/ +/rcoll/c/ /t/a/ 200 Script output follows @@ -115,7 +121,19 @@ 200 Script output follows 200 Script output follows a -% should succeed +200 Script output follows + + +/rcoll/a/ +/rcoll/a/.hg/patches/ +/rcoll/b/ +/rcoll/b/d/ +/rcoll/c/ + +200 Script output follows + +d +% collections: should succeed 200 Script output follows