diff mercurial/hgweb/webcommands.py @ 7305:c21d236ca897

hgweb: descend empty directories in web view 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, descending down empty directories is very common in Java web tools.
author Ry4an Brase <ry4an-hg@ry4an.org>
date Mon, 03 Nov 2008 10:20:28 +0100
parents 591767e6ea7a
children bd522d09d5e3
line wrap: on
line diff
--- a/mercurial/hgweb/webcommands.py	Sun Nov 02 22:44:42 2008 +0100
+++ b/mercurial/hgweb/webcommands.py	Mon Nov 03 10:20:28 2008 +0100
@@ -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,21 @@
                    "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": "/".join(emptydirs),
+                   "basename": d}
 
     return tmpl("manifest",
                 rev=ctx.rev(),