[PATCH] hgweb: support directory and subrepository navigation when descend mode is disabled
Paul Boddie
paul at boddie.org.uk
Sun Jan 29 13:03:48 CST 2012
# HG changeset patch
# User Paul Boddie <paul at boddie.org.uk>
# Date 1327863292 -3600
# Branch stable
# Node ID 967d0f22ee70762029beb539e15daf97b36ace86
# Parent f8955a7f82e6a06a682cd95631fd1c5e55f46103
hgweb: support directory and subrepository navigation when descend mode is disabled
diff -r f8955a7f82e6 -r 967d0f22ee70 mercurial/hgweb/hgwebdir_mod.py
--- a/mercurial/hgweb/hgwebdir_mod.py Fri Jan 27 03:00:32 2012 +0100
+++ b/mercurial/hgweb/hgwebdir_mod.py Sun Jan 29 19:54:52 2012 +0100
@@ -245,12 +245,61 @@
def rawentries(subdir="", **map):
descend = self.ui.configbool('web', 'descend', True)
+ seenrepos = set()
+ seendirs = set()
for name, path in self.repos:
if not name.startswith(subdir):
continue
name = name[len(subdir):]
+ directory = False
+
if not descend and '/' in name:
+ nameparts = name.split('/')
+ rootname = nameparts[0]
+
+ if rootname in seendirs:
+ continue
+ elif rootname in seenrepos:
+ pass
+ else:
+ directory = True
+ name = rootname
+
+ # redefine the path to refer to the directory
+ discarded = '/'.join(nameparts[1:])
+
+ # remove name parts plus accompanying slash
+ path = path[:-len(discarded) - 1]
+
+ parts = [name]
+ if 'PATH_INFO' in req.env:
+ parts.insert(0, req.env['PATH_INFO'].rstrip('/'))
+ if req.env['SCRIPT_NAME']:
+ parts.insert(0, req.env['SCRIPT_NAME'])
+ url = re.sub(r'/+', '/', '/'.join(parts) + '/')
+
+ # show either a directory entry or a repository
+ if directory:
+ # get the directory's time information
+ try:
+ d = (get_mtime(path), util.makedate()[1])
+ except OSError:
+ continue
+
+ row = dict(contact="",
+ contact_sort="",
+ name=name,
+ name_sort=name,
+ url=url,
+ description="",
+ description_sort="",
+ lastchange=d,
+ lastchange_sort=d[1]-d[0],
+ archives=[])
+
+ seendirs.add(name)
+ yield row
continue
u = self.ui.copy()
@@ -267,13 +316,6 @@
if not self.read_allowed(u, req):
continue
-
- parts = [name]
- if 'PATH_INFO' in req.env:
- parts.insert(0, req.env['PATH_INFO'].rstrip('/'))
- if req.env['SCRIPT_NAME']:
- parts.insert(0, req.env['SCRIPT_NAME'])
- url = re.sub(r'/+', '/', '/'.join(parts) + '/')
# update time with local timezone
try:
@@ -302,6 +344,8 @@
lastchange=d,
lastchange_sort=d[1]-d[0],
archives=archivelist(u, "tip", url))
+
+ seenrepos.add(name)
yield row
sortdefault = None, False
diff -r f8955a7f82e6 -r 967d0f22ee70 tests/test-hgwebdir.t
--- a/tests/test-hgwebdir.t Fri Jan 27 03:00:32 2012 +0100
+++ b/tests/test-hgwebdir.t Sun Jan 29 19:54:52 2012 +0100
@@ -30,6 +30,28 @@
$ echo c > c/c
$ hg --cwd c ci -Amc -d'3 0'
adding c
+
+create a subdirectory containing repositories and subrepositories
+
+ $ mkdir notrepo
+ $ cd notrepo
+ $ hg init e
+ $ echo e > e/e
+ $ hg --cwd e ci -Ame -d'4 0'
+ adding e
+ $ hg init e/e2
+ $ echo e2 > e/e2/e2
+ $ hg --cwd e/e2 ci -Ame2 -d '4 0'
+ adding e2
+ $ hg init f
+ $ echo f > f/f
+ $ hg --cwd f ci -Amf -d'4 0'
+ adding f
+ $ hg init f/f2
+ $ echo f2 > f/f2/f2
+ $ hg --cwd f/f2 ci -Amf2 -d '4 0'
+ adding f2
+ $ cd ..
create repository without .hg/store
@@ -119,20 +141,32 @@
/coll/a/.hg/patches/
/coll/b/
/coll/c/
+ /coll/notrepo/e/
+ /coll/notrepo/f/
/rcoll/a/
/rcoll/a/.hg/patches/
/rcoll/b/
/rcoll/b/d/
/rcoll/c/
+ /rcoll/notrepo/e/
+ /rcoll/notrepo/e/e2/
+ /rcoll/notrepo/f/
+ /rcoll/notrepo/f/f2/
/star/webdir/a/
/star/webdir/a/.hg/patches/
/star/webdir/b/
/star/webdir/c/
+ /star/webdir/notrepo/e/
+ /star/webdir/notrepo/f/
/starstar/webdir/a/
/starstar/webdir/a/.hg/patches/
/starstar/webdir/b/
/starstar/webdir/b/d/
/starstar/webdir/c/
+ /starstar/webdir/notrepo/e/
+ /starstar/webdir/notrepo/e/e2/
+ /starstar/webdir/notrepo/f/
+ /starstar/webdir/notrepo/f/f2/
/astar/
/astar/.hg/patches/
@@ -217,6 +251,22 @@
</tr>
<tr class="parity0">
+ <td><a href="/coll/notrepo/e/?style=paper">coll/notrepo/e</a></td>
+ <td>unknown</td>
+ <td>Foo Bar <foo.bar@example.com></td>
+ <td class="age">*</td> (glob)
+ <td class="indexlinks"></td>
+ </tr>
+
+ <tr class="parity1">
+ <td><a href="/coll/notrepo/f/?style=paper">coll/notrepo/f</a></td>
+ <td>unknown</td>
+ <td>Foo Bar <foo.bar@example.com></td>
+ <td class="age">*</td> (glob)
+ <td class="indexlinks"></td>
+ </tr>
+
+ <tr class="parity0">
<td><a href="/rcoll/a/?style=paper">rcoll/a</a></td>
<td>unknown</td>
<td>Foo Bar <foo.bar@example.com></td>
@@ -257,6 +307,38 @@
</tr>
<tr class="parity1">
+ <td><a href="/rcoll/notrepo/e/?style=paper">rcoll/notrepo/e</a></td>
+ <td>unknown</td>
+ <td>Foo Bar <foo.bar@example.com></td>
+ <td class="age">*</td> (glob)
+ <td class="indexlinks"></td>
+ </tr>
+
+ <tr class="parity0">
+ <td><a href="/rcoll/notrepo/e/e2/?style=paper">rcoll/notrepo/e/e2</a></td>
+ <td>unknown</td>
+ <td>Foo Bar <foo.bar@example.com></td>
+ <td class="age">*</td> (glob)
+ <td class="indexlinks"></td>
+ </tr>
+
+ <tr class="parity1">
+ <td><a href="/rcoll/notrepo/f/?style=paper">rcoll/notrepo/f</a></td>
+ <td>unknown</td>
+ <td>Foo Bar <foo.bar@example.com></td>
+ <td class="age">*</td> (glob)
+ <td class="indexlinks"></td>
+ </tr>
+
+ <tr class="parity0">
+ <td><a href="/rcoll/notrepo/f/f2/?style=paper">rcoll/notrepo/f/f2</a></td>
+ <td>unknown</td>
+ <td>Foo Bar <foo.bar@example.com></td>
+ <td class="age">*</td> (glob)
+ <td class="indexlinks"></td>
+ </tr>
+
+ <tr class="parity1">
<td><a href="/star/webdir/a/?style=paper">star/webdir/a</a></td>
<td>unknown</td>
<td>Foo Bar <foo.bar@example.com></td>
@@ -282,6 +364,22 @@
<tr class="parity0">
<td><a href="/star/webdir/c/?style=paper">star/webdir/c</a></td>
+ <td>unknown</td>
+ <td>Foo Bar <foo.bar@example.com></td>
+ <td class="age">*</td> (glob)
+ <td class="indexlinks"></td>
+ </tr>
+
+ <tr class="parity1">
+ <td><a href="/star/webdir/notrepo/e/?style=paper">star/webdir/notrepo/e</a></td>
+ <td>unknown</td>
+ <td>Foo Bar <foo.bar@example.com></td>
+ <td class="age">*</td> (glob)
+ <td class="indexlinks"></td>
+ </tr>
+
+ <tr class="parity0">
+ <td><a href="/star/webdir/notrepo/f/?style=paper">star/webdir/notrepo/f</a></td>
<td>unknown</td>
<td>Foo Bar <foo.bar@example.com></td>
<td class="age">*</td> (glob)
@@ -322,6 +420,38 @@
<tr class="parity1">
<td><a href="/starstar/webdir/c/?style=paper">starstar/webdir/c</a></td>
+ <td>unknown</td>
+ <td>Foo Bar <foo.bar@example.com></td>
+ <td class="age">*</td> (glob)
+ <td class="indexlinks"></td>
+ </tr>
+
+ <tr class="parity0">
+ <td><a href="/starstar/webdir/notrepo/e/?style=paper">starstar/webdir/notrepo/e</a></td>
+ <td>unknown</td>
+ <td>Foo Bar <foo.bar@example.com></td>
+ <td class="age">*</td> (glob)
+ <td class="indexlinks"></td>
+ </tr>
+
+ <tr class="parity1">
+ <td><a href="/starstar/webdir/notrepo/e/e2/?style=paper">starstar/webdir/notrepo/e/e2</a></td>
+ <td>unknown</td>
+ <td>Foo Bar <foo.bar@example.com></td>
+ <td class="age">*</td> (glob)
+ <td class="indexlinks"></td>
+ </tr>
+
+ <tr class="parity0">
+ <td><a href="/starstar/webdir/notrepo/f/?style=paper">starstar/webdir/notrepo/f</a></td>
+ <td>unknown</td>
+ <td>Foo Bar <foo.bar@example.com></td>
+ <td class="age">*</td> (glob)
+ <td class="indexlinks"></td>
+ </tr>
+
+ <tr class="parity1">
+ <td><a href="/starstar/webdir/notrepo/f/f2/?style=paper">starstar/webdir/notrepo/f/f2</a></td>
<td>unknown</td>
<td>Foo Bar <foo.bar@example.com></td>
<td class="age">*</td> (glob)
@@ -489,6 +619,8 @@
/coll/a/.hg/patches/
/coll/b/
/coll/c/
+ /coll/notrepo/e/
+ /coll/notrepo/f/
$ "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/coll/a/file/tip/a?style=raw'
200 Script output follows
@@ -506,11 +638,63 @@
/rcoll/b/
/rcoll/b/d/
/rcoll/c/
+ /rcoll/notrepo/e/
+ /rcoll/notrepo/e/e2/
+ /rcoll/notrepo/f/
+ /rcoll/notrepo/f/f2/
$ "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/rcoll/b/d/file/tip/d?style=raw'
200 Script output follows
d
+
+Test descend = False
+
+ $ "$TESTDIR/killdaemons.py"
+ $ cat >> paths.conf <<EOF
+ > [web]
+ > descend=false
+ > EOF
+ $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
+ > -A access-paths.log -E error-paths-3.log
+ $ cat hg.pid >> $DAEMON_PIDS
+ $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/rcoll/?style=raw'
+ 200 Script output follows
+
+
+ /rcoll/a/
+ /rcoll/a/.hg/patches/
+ /rcoll/b/
+ /rcoll/b/d/
+ /rcoll/c/
+ /rcoll/notrepo/
+
+
+Test intermediate directories
+
+ $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/rcoll/notrepo/?style=raw'
+ 200 Script output follows
+
+
+ /rcoll/notrepo/e/
+ /rcoll/notrepo/e/e2/
+ /rcoll/notrepo/f/
+ /rcoll/notrepo/f/f2/
+
+
+Test repositories inside intermediate directories
+
+ $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/rcoll/notrepo/e/file/tip/e?style=raw'
+ 200 Script output follows
+
+ e
+
+Test subrepositories inside intermediate directories
+
+ $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/rcoll/notrepo/f/f2/file/tip/f2?style=raw'
+ 200 Script output follows
+
+ f2
Test [paths] '*' in a repo root
@@ -536,6 +720,7 @@
200 Script output follows
+ /t/
/c/
$ "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/t/?style=raw'
@@ -617,6 +802,8 @@
/a/.hg/patches/
/b/
/c/
+ /notrepo/e/
+ /notrepo/f/
$ "$TESTDIR/get-with-headers.py" localhost:$HGPORT2 '/a/file/tip/a?style=raw'
200 Script output follows
More information about the Mercurial-devel
mailing list