[PATCH] Descend empty directories in web view, non-optional, optimized
Ry4an Brase
ry4an-hg at ry4an.org
Sat Nov 1 01:01:09 CDT 2008
# HG changeset patch
# User Ry4an Brase <ry4an-hg at ry4an.org>
# Date 1224788391 18000
# Node ID 5c2fa1ffb49fa0c95fa046722c8c801bbc27f4cf
# Parent bd6deb7525f46d66fe1b33b928e5c828218b7f30
Descend empty directories in web view, non-optional, optimized
When a manifest has a series of directories with nothing in them but a
single directory, displaying the entire chain of empty directories
allows for navigation down to the first non-empty directory with a
single click.
Because Java links package hierarchy to directory hierarchy, and because Java
conventions include at least three empty directories at the top of this
hierarchy, this descending of empty directories is par for the course in Java web
tools.
History:
- Mpm said to make it non-optional
- Tonfa suggested removing additional folder icons in paper and coal
- Djc said to:
- merge previously separate webcommand and template patches
- make template value a string (not a dict)
- add tests
Non-interactive sample view:
http://ry4an.org/tmp/Dime-without-folders.html
diff -r bd6deb7525f4 -r 5c2fa1ffb49f mercurial/hgweb/webcommands.py
--- a/mercurial/hgweb/webcommands.py Thu Oct 30 12:38:24 2008 -0700
+++ b/mercurial/hgweb/webcommands.py Thu Oct 23 13:59:51 2008 -0500
@@ -264,6 +264,7 @@
node = ctx.node()
files = {}
+ dirs = {}
parity = paritygen(web.stripecount)
if path and path[-1] != "/":
@@ -275,20 +276,25 @@
if f[:l] != path:
continue
remain = f[l:]
- idx = remain.find('/')
- if idx != -1:
- remain = remain[:idx+1]
- n = None
- files[remain] = (f, n)
+ elements = remain.split('/')
+ if len(elements) == 1:
+ files[remain] = f
+ else:
+ h = dirs # need to retain ref to dirs (root)
+ for elem in elements[0:-1]:
+ if elem not in h:
+ h[elem] = {}
+ h = h[elem]
+ if len(h) > 1:
+ break
+ h[None] = None # denotes files present
- if not files:
+ if not files and not dirs:
raise ErrorResponse(HTTP_NOT_FOUND, 'path not found: ' + path)
def filelist(**map):
for f in util.sort(files):
- full, fnode = files[f]
- if not fnode:
- continue
+ full = files[f]
fctx = ctx.filectx(full)
yield {"file": full,
@@ -299,14 +305,22 @@
"permissions": mf.flags(full)}
def dirlist(**map):
- for f in util.sort(files):
- full, fnode = files[f]
- if fnode:
- continue
+ for d in util.sort(dirs):
+ emptydirs = []
+ h = dirs[d]
+ while isinstance(h, dict) and len(h) == 1:
+ k,v = h.items()[0]
+ if v:
+ emptydirs.append(k)
+ h = v
+
+ path = "%s%s" % (abspath, d)
yield {"parity": parity.next(),
- "path": "%s%s" % (abspath, f),
- "basename": f[:-1]}
+ "path": path,
+ "emptydirs": (),
+ "emptydirs": "/".join(emptydirs),
+ "basename": d}
return tmpl("manifest",
rev=ctx.rev(),
diff -r bd6deb7525f4 -r 5c2fa1ffb49f templates/coal/map
--- a/templates/coal/map Thu Oct 30 12:38:24 2008 -0700
+++ b/templates/coal/map Thu Oct 23 13:59:51 2008 -0500
@@ -23,7 +23,7 @@
changeset = changeset.tmpl
manifest = manifest.tmpl
-direntry = '<tr class="fileline parity{parity}"><td class="name"><a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}"><img src="{staticurl}coal-folder.png"> {basename|escape}/</a><td class="size"></td><td class="permissions">drwxr-xr-x</td></tr>'
+direntry = '<tr class="fileline parity{parity}"><td class="name"><a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}"><img src="{staticurl}coal-folder.png"> {basename|escape}/</a> <a href="{url}file/{node|short}{path|urlescape}/{emptydirs|urlescape}{sessionvars%urlparameter}">{emptydirs|escape}</a><td class="size"></td><td class="permissions">drwxr-xr-x</td></tr>'
fileentry = '<tr class="fileline parity{parity}"><td class="filename"><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}#l1"><img src="{staticurl}coal-file.png"> {basename|escape}</a></td><td class="size">{size}</td><td class="permissions">{permissions|permissions}</td></tr>'
filerevision = filerevision.tmpl
diff -r bd6deb7525f4 -r 5c2fa1ffb49f templates/gitweb/map
--- a/templates/gitweb/map Thu Oct 30 12:38:24 2008 -0700
+++ b/templates/gitweb/map Thu Oct 23 13:59:51 2008 -0500
@@ -19,7 +19,7 @@
searchentry = changelogentry.tmpl
changeset = changeset.tmpl
manifest = manifest.tmpl
-direntry = '<tr class="parity#parity#"><td style="font-family:monospace">drwxr-xr-x</td><td style="font-family:monospace"></td><td style="font-family:monospace"></td><td><a href="#url#file/#node|short##path|urlescape#{sessionvars%urlparameter}">#basename|escape#</a></td><td class="link"><a href="#url#file/#node|short##path|urlescape#{sessionvars%urlparameter}">files</a></td></tr>'
+direntry = '<tr class="parity#parity#"><td style="font-family:monospace">drwxr-xr-x</td><td style="font-family:monospace"></td><td style="font-family:monospace"></td><td><a href="#url#file/#node|short##path|urlescape#{sessionvars%urlparameter}">#basename|escape#</a> <a href="#url#file/#node|short##path|urlescape#/#emptydirs|urlescape#{sessionvars%urlparameter}">#emptydirs|escape#</a></td><td class="link"><a href="#url#file/#node|short##path|urlescape#{sessionvars%urlparameter}">files</a></td></tr>'
fileentry = '<tr class="parity#parity#"><td style="font-family:monospace">#permissions|permissions#</td><td style="font-family:monospace" align=right>#date|isodate#</td><td style="font-family:monospace" align=right>#size#</td><td class="list"><a class="list" href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">#basename|escape#</a></td><td class="link"><a href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">file</a> | <a href="#url#log/#node|short#/#file|urlescape#{sessionvars%urlparameter}">revisions</a> | <a href="#url#annotate/#node|short#/#file|urlescape#{sessionvars%urlparameter}">annotate</a></td></tr>'
filerevision = filerevision.tmpl
fileannotate = fileannotate.tmpl
diff -r bd6deb7525f4 -r 5c2fa1ffb49f templates/map
--- a/templates/map Thu Oct 30 12:38:24 2008 -0700
+++ b/templates/map Thu Oct 23 13:59:51 2008 -0500
@@ -19,7 +19,7 @@
searchentry = changelogentry.tmpl
changeset = changeset.tmpl
manifest = manifest.tmpl
-direntry = '<tr class="parity#parity#"><td><tt>drwxr-xr-x</tt> <td> <td> <td><a href="#url#file/#node|short##path|urlescape#{sessionvars%urlparameter}">#basename|escape#/</a>'
+direntry = '<tr class="parity#parity#"><td><tt>drwxr-xr-x</tt> <td> <td> <td><a href="#url#file/#node|short##path|urlescape#{sessionvars%urlparameter}">#basename|escape#/</a> <a href="#url#file/#node|short##path|urlescape#/#emptydirs|urlescape#{sessionvars%urlparameter}">#emptydirs|urlescape#</a>'
fileentry = '<tr class="parity#parity#"><td><tt>#permissions|permissions#</tt> <td align=right><tt class="date">#date|isodate#</tt> <td align=right><tt>#size#</tt> <td><a href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">#basename|escape#</a>'
filerevision = filerevision.tmpl
fileannotate = fileannotate.tmpl
diff -r bd6deb7525f4 -r 5c2fa1ffb49f templates/paper/map
--- a/templates/paper/map Thu Oct 30 12:38:24 2008 -0700
+++ b/templates/paper/map Thu Oct 23 13:59:51 2008 -0500
@@ -23,7 +23,7 @@
changeset = ../coal/changeset.tmpl
manifest = ../coal/manifest.tmpl
-direntry = '<tr class="fileline parity{parity}"><td class="name"><a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}"><img src="{staticurl}coal-folder.png"> {basename|escape}/</a><td class="size"></td><td class="permissions">drwxr-xr-x</td></tr>'
+direntry = '<tr class="fileline parity{parity}"><td class="name"><a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}"><img src="{staticurl}coal-folder.png"> {basename|escape}/</a> <a href="{url}file/{node|short}{path|urlescape}/{emptydirs|urlescape}{sessionvars%urlparameter}">{emptydirs|escape}</a><td class="size"></td><td class="permissions">drwxr-xr-x</td></tr>'
fileentry = '<tr class="fileline parity{parity}"><td class="filename"><a href="{url}file/{node|short}/{file|urlescape}#l1{sessionvars%urlparameter}"><img src="{staticurl}coal-file.png"> {basename|escape}</a></td><td class="size">{size}</td><td class="permissions">{permissions|permissions}</td></tr>'
filerevision = ../coal/filerevision.tmpl
diff -r bd6deb7525f4 -r 5c2fa1ffb49f tests/test-hgweb-descend-empties
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-hgweb-descend-empties Thu Oct 23 13:59:51 2008 -0500
@@ -0,0 +1,27 @@
+#!/bin/sh
+# Test chains of near empty directories, terminating 3 different ways:
+# - a1: file at level 4 (deepest)
+# - b1: two dirs at level 3
+# - e1: file at level 2
+
+echo % Set up the repo
+hg init test
+cd test
+mkdir -p a1/a2/a3/a4
+mkdir -p b1/b2/b3/b4
+mkdir -p b1/b2/c3/c4
+mkdir -p d1/d2/d3/d4
+echo foo > a1/a2/a3/a4/foo
+echo foo > b1/b2/b3/b4/foo
+echo foo > b1/b2/c3/c4/foo
+echo foo > d1/d2/d3/d4/foo
+echo foo > d1/d2/foo
+hg ci -d'0 0' -Ambase
+hg serve -n test -p $HGPORT -d --pid-file=hg.pid -E errors.log
+cat hg.pid >> $DAEMON_PIDS
+
+echo % File-related
+"$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file'
+
+echo % ERRORS ENCOUNTERED
+cat errors.log
diff -r bd6deb7525f4 -r 5c2fa1ffb49f tests/test-hgweb-descend-empties.out
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-hgweb-descend-empties.out Thu Oct 23 13:59:51 2008 -0500
@@ -0,0 +1,51 @@
+% Set up the repo
+adding a1/a2/a3/a4/foo
+adding b1/b2/b3/b4/foo
+adding b1/b2/c3/c4/foo
+adding d1/d2/d3/d4/foo
+adding d1/d2/foo
+% File-related
+200 Script output follows
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<link rel="icon" href="/static/hgicon.png" type="image/png">
+<meta name="robots" content="index, nofollow" />
+<link rel="stylesheet" href="/static/style.css" type="text/css" />
+
+<title>test: files for changeset 8ec8269799d6</title>
+</head>
+<body>
+
+<div class="buttons">
+<a href="/log/0">changelog</a>
+<a href="/shortlog/0">shortlog</a>
+<a href="/graph">graph</a>
+<a href="/tags">tags</a>
+<a href="/rev/8ec8269799d6">changeset</a>
+
+</div>
+
+<h2>files for changeset 8ec8269799d6: /</h2>
+
+<table cellpadding="0" cellspacing="0">
+<tr class="parity0">
+ <td><tt>drwxr-xr-x</tt>
+ <td>
+ <td>
+ <td><a href="/file/8ec8269799d6/">[up]</a>
+</tr>
+<tr class="parity1"><td><tt>drwxr-xr-x</tt> <td> <td> <td><a href="/file/8ec8269799d6/a1">a1/</a> <a href="/file/8ec8269799d6/a1/a2/a3/a4">a2/a3/a4</a><tr class="parity0"><td><tt>drwxr-xr-x</tt> <td> <td> <td><a href="/file/8ec8269799d6/b1">b1/</a> <a href="/file/8ec8269799d6/b1/b2">b2</a><tr class="parity1"><td><tt>drwxr-xr-x</tt> <td> <td> <td><a href="/file/8ec8269799d6/d1">d1/</a> <a href="/file/8ec8269799d6/d1/d2">d2</a>
+
+</table>
+
+<div class="logo">
+<a href="http://www.selenic.com/mercurial/">
+<img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
+</div>
+
+</body>
+</html>
+
+% ERRORS ENCOUNTERED
More information about the Mercurial-devel
mailing list