Mercurial > hg
comparison 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 |
comparison
equal
deleted
inserted
replaced
7304:68374f1c8c87 | 7305:c21d236ca897 |
---|---|
262 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0]) | 262 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0]) |
263 mf = ctx.manifest() | 263 mf = ctx.manifest() |
264 node = ctx.node() | 264 node = ctx.node() |
265 | 265 |
266 files = {} | 266 files = {} |
267 dirs = {} | |
267 parity = paritygen(web.stripecount) | 268 parity = paritygen(web.stripecount) |
268 | 269 |
269 if path and path[-1] != "/": | 270 if path and path[-1] != "/": |
270 path += "/" | 271 path += "/" |
271 l = len(path) | 272 l = len(path) |
273 | 274 |
274 for f, n in mf.items(): | 275 for f, n in mf.items(): |
275 if f[:l] != path: | 276 if f[:l] != path: |
276 continue | 277 continue |
277 remain = f[l:] | 278 remain = f[l:] |
278 idx = remain.find('/') | 279 elements = remain.split('/') |
279 if idx != -1: | 280 if len(elements) == 1: |
280 remain = remain[:idx+1] | 281 files[remain] = f |
281 n = None | 282 else: |
282 files[remain] = (f, n) | 283 h = dirs # need to retain ref to dirs (root) |
283 | 284 for elem in elements[0:-1]: |
284 if not files: | 285 if elem not in h: |
286 h[elem] = {} | |
287 h = h[elem] | |
288 if len(h) > 1: | |
289 break | |
290 h[None] = None # denotes files present | |
291 | |
292 if not files and not dirs: | |
285 raise ErrorResponse(HTTP_NOT_FOUND, 'path not found: ' + path) | 293 raise ErrorResponse(HTTP_NOT_FOUND, 'path not found: ' + path) |
286 | 294 |
287 def filelist(**map): | 295 def filelist(**map): |
288 for f in util.sort(files): | 296 for f in util.sort(files): |
289 full, fnode = files[f] | 297 full = files[f] |
290 if not fnode: | |
291 continue | |
292 | 298 |
293 fctx = ctx.filectx(full) | 299 fctx = ctx.filectx(full) |
294 yield {"file": full, | 300 yield {"file": full, |
295 "parity": parity.next(), | 301 "parity": parity.next(), |
296 "basename": f, | 302 "basename": f, |
297 "date": fctx.date(), | 303 "date": fctx.date(), |
298 "size": fctx.size(), | 304 "size": fctx.size(), |
299 "permissions": mf.flags(full)} | 305 "permissions": mf.flags(full)} |
300 | 306 |
301 def dirlist(**map): | 307 def dirlist(**map): |
302 for f in util.sort(files): | 308 for d in util.sort(dirs): |
303 full, fnode = files[f] | 309 |
304 if fnode: | 310 emptydirs = [] |
305 continue | 311 h = dirs[d] |
306 | 312 while isinstance(h, dict) and len(h) == 1: |
313 k,v = h.items()[0] | |
314 if v: | |
315 emptydirs.append(k) | |
316 h = v | |
317 | |
318 path = "%s%s" % (abspath, d) | |
307 yield {"parity": parity.next(), | 319 yield {"parity": parity.next(), |
308 "path": "%s%s" % (abspath, f), | 320 "path": path, |
309 "basename": f[:-1]} | 321 "emptydirs": "/".join(emptydirs), |
322 "basename": d} | |
310 | 323 |
311 return tmpl("manifest", | 324 return tmpl("manifest", |
312 rev=ctx.rev(), | 325 rev=ctx.rev(), |
313 node=hex(node), | 326 node=hex(node), |
314 path=abspath, | 327 path=abspath, |