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,