def puttags(self, tags): try: parentctx = self.repo[self.tagsbranch] tagparent = parentctx.node() except error.RepoError: parentctx = None tagparent = nullid try: oldlines = sorted(parentctx['.hgtags'].data().splitlines(True)) except: oldlines = [] newlines = sorted([("%s %s\n" % (tags[tag], tag)) for tag in tags]) if newlines == oldlines: return None, None data = "".join(newlines) def getfilectx(repo, memctx, f): return context.memfilectx(f, data, False, False, None) self.ui.status(_("updating tags\n")) date = "%s 0" % int(time.mktime(time.gmtime())) extra = {'branch': self.tagsbranch} ctx = context.memctx(self.repo, (tagparent, None), "update tags", [".hgtags"], getfilectx, "convert-repo", date, extra) self.repo.commitctx(ctx) return hex(self.repo.changelog.tip()), hex(tagparent)
def changelist(limit=0, **map): l = [] # build a list in forward order for efficiency for i in xrange(start, end): ctx = web.repo[i] n = ctx.node() showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n) files = webutil.listfilediffs(tmpl, ctx.files(), n, web.maxfiles) l.insert( 0, { "parity": parity.next(), "author": ctx.user(), "parent": webutil.parents(ctx, i - 1), "child": webutil.children(ctx, i + 1), "changelogtag": showtags, "desc": ctx.description(), "date": ctx.date(), "files": files, "rev": i, "node": hex(n), "tags": webutil.nodetagsdict(web.repo, n), "inbranch": webutil.nodeinbranch(web.repo, ctx), "branches": webutil.nodebranchdict(web.repo, ctx) }) if limit > 0: l = l[:limit] for e in l: yield e
def branches(web, req, tmpl): tips = (web.repo[n] for t, n in web.repo.branchtags().iteritems()) heads = web.repo.heads() parity = paritygen(web.stripecount) sortkey = lambda ctx: ('close' not in ctx.extra(), ctx.rev()) def entries(limit, **map): count = 0 for ctx in sorted(tips, key=sortkey, reverse=True): if limit > 0 and count >= limit: return count += 1 if ctx.node() not in heads: status = 'inactive' elif not web.repo.branchheads(ctx.branch()): status = 'closed' else: status = 'open' yield { 'parity': parity.next(), 'branch': ctx.branch(), 'status': status, 'node': ctx.hex(), 'date': ctx.date() } return tmpl('branches', node=hex(web.repo.changelog.tip()), entries=lambda **x: entries(0, **x), latestentry=lambda **x: entries(1, **x))
def annotate(**map): last = None if binary(fctx.data()): mt = (mimetypes.guess_type(fctx.path())[0] or 'application/octet-stream') lines = enumerate([((fctx.filectx(fctx.filerev()), 1), '(binary:%s)' % mt)]) else: lines = enumerate(fctx.annotate(follow=True, linenumber=True)) for lineno, ((f, targetline), l) in lines: fnode = f.filenode() if last != fnode: last = fnode yield { "parity": parity.next(), "node": hex(f.node()), "rev": f.rev(), "author": f.user(), "desc": f.description(), "file": f.path(), "targetline": targetline, "line": l, "lineid": "l%d" % (lineno + 1), "linenumber": "% 6d" % (lineno + 1) }
def write(repo): '''Write bookmarks Write the given bookmark => hash dictionary to the .hg/bookmarks file in a format equal to those of localtags. We also store a backup of the previous state in undo.bookmarks that can be copied back on rollback. ''' refs = repo._bookmarks try: bms = repo.opener('bookmarks').read() except IOError: bms = '' repo.opener('undo.bookmarks', 'w').write(bms) if repo._bookmarkcurrent not in refs: setcurrent(repo, None) wlock = repo.wlock() try: file = repo.opener('bookmarks', 'w', atomictemp=True) for refspec, node in refs.iteritems(): file.write("%s %s\n" % (hex(node), refspec)) file.rename() # touch 00changelog.i so hgweb reloads bookmarks (no lock needed) try: os.utime(repo.sjoin('00changelog.i'), None) except OSError: pass finally: wlock.release()
def entries(limit=0, **map): l = [] repo = web.repo for i in xrange(start, end): iterfctx = fctx.filectx(i) l.insert( 0, { "parity": parity.next(), "filerev": i, "file": f, "node": hex(iterfctx.node()), "author": iterfctx.user(), "date": iterfctx.date(), "rename": webutil.renamelink(iterfctx), "parent": webutil.parents(iterfctx), "child": webutil.children(iterfctx), "desc": iterfctx.description(), "tags": webutil.nodetagsdict(repo, iterfctx.node()), "branch": webutil.nodebranchnodefault(iterfctx), "inbranch": webutil.nodeinbranch(repo, iterfctx), "branches": webutil.nodebranchdict(repo, iterfctx) }) if limit > 0: l = l[:limit] for e in l: yield e
def _filerevision(web, tmpl, fctx): f = fctx.path() text = fctx.data() parity = paritygen(web.stripecount) if binary(text): mt = mimetypes.guess_type(f)[0] or 'application/octet-stream' text = '(binary:%s)' % mt def lines(): for lineno, t in enumerate(text.splitlines(True)): yield { "line": t, "lineid": "l%d" % (lineno + 1), "linenumber": "% 6d" % (lineno + 1), "parity": parity.next() } return tmpl("filerevision", file=f, path=webutil.up(f), text=lines(), rev=fctx.rev(), node=hex(fctx.node()), author=fctx.user(), date=fctx.date(), desc=fctx.description(), branch=webutil.nodebranchnodefault(fctx), parent=webutil.parents(fctx), child=webutil.children(fctx), rename=webutil.renamelink(fctx), permissions=fctx.manifest().flags(f))
def tags(web, req, tmpl): i = web.repo.tagslist() i.reverse() parity = paritygen(web.stripecount) def entries(notip=False, limit=0, **map): count = 0 for k, n in i: if notip and k == "tip": continue if limit > 0 and count >= limit: continue count = count + 1 yield { "parity": parity.next(), "tag": k, "date": web.repo[n].date(), "node": hex(n) } return tmpl("tags", node=hex(web.repo.changelog.tip()), entries=lambda **x: entries(False, 0, **x), entriesnotip=lambda **x: entries(True, 0, **x), latestentry=lambda **x: entries(True, 1, **x))
def catfile(self, rev, type): if rev == hex(nullid): raise IOError() data, ret = self.gitread("git cat-file %s %s" % (type, rev)) if ret: raise util.Abort(_('cannot read %r object at %s') % (type, rev)) return data
def listbookmarks(repo): # We may try to list bookmarks on a repo type that does not # support it (e.g., statichttprepository). if not hasattr(repo, '_bookmarks'): return {} d = {} for k, v in repo._bookmarks.iteritems(): d[k] = hex(v) return d
def revnavgen(pos, pagelen, limit, nodefunc): def seq(factor, limit=None): if limit: yield limit if limit >= 20 and limit <= 40: yield 50 else: yield 1 * factor yield 3 * factor for f in seq(factor * 10): yield f navbefore = [] navafter = [] last = 0 for f in seq(1, pagelen): if f < pagelen or f <= last: continue if f > limit: break last = f if pos + f < limit: navafter.append(("+%d" % f, hex(nodefunc(pos + f).node()))) if pos - f >= 0: navbefore.insert(0, ("-%d" % f, hex(nodefunc(pos - f).node()))) navafter.append(("tip", "tip")) try: navbefore.insert(0, ("(0)", hex(nodefunc('0').node()))) except error.RepoError: pass def gen(l): def f(**map): for label, node in l: yield {"label": label, "node": node} return f return (dict(before=gen(navbefore), after=gen(navafter)), )
def putcommit(self, files, copies, parents, commit, source, revmap): files = dict(files) def getfilectx(repo, memctx, f): v = files[f] data, mode = source.getfile(f, v) if f == '.hgtags': data = self._rewritetags(source, revmap, data) return context.memfilectx(f, data, 'l' in mode, 'x' in mode, copies.get(f)) pl = [] for p in parents: if p not in pl: pl.append(p) parents = pl nparents = len(parents) if self.filemapmode and nparents == 1: m1node = self.repo.changelog.read(bin(parents[0]))[0] parent = parents[0] if len(parents) < 2: parents.append(nullid) if len(parents) < 2: parents.append(nullid) p2 = parents.pop(0) text = commit.desc extra = commit.extra.copy() if self.branchnames and commit.branch: extra['branch'] = commit.branch if commit.rev: extra['convert_revision'] = commit.rev while parents: p1 = p2 p2 = parents.pop(0) ctx = context.memctx(self.repo, (p1, p2), text, files.keys(), getfilectx, commit.author, commit.date, extra) self.repo.commitctx(ctx) text = "(octopus merge fixup)\n" p2 = hex(self.repo.changelog.tip()) if self.filemapmode and nparents == 1: man = self.repo.manifest mnode = self.repo.changelog.read(bin(p2))[0] closed = 'close' in commit.extra if not closed and not man.cmp(m1node, man.revision(mnode)): self.ui.status(_("filtering out empty revision\n")) self.repo.rollback() return parent return p2
def branches(**map): parity = paritygen(web.stripecount) b = web.repo.branchtags() l = [(-web.repo.changelog.rev(n), n, t) for t, n in b.iteritems()] for r, n, t in sorted(l): yield { 'parity': parity.next(), 'branch': t, 'node': hex(n), 'date': web.repo[n].date() }
def _siblings(siblings=[], hiderev=None): siblings = [s for s in siblings if s.node() != nullid] if len(siblings) == 1 and siblings[0].rev() == hiderev: return for s in siblings: d = {'node': hex(s.node()), 'rev': s.rev()} d['user'] = s.user() d['date'] = s.date() d['description'] = s.description() d['branch'] = s.branch() if hasattr(s, 'path'): d['file'] = s.path() yield d
def graph(web, req, tmpl): rev = webutil.changectx(web.repo, req).rev() bg_height = 39 revcount = web.maxshortchanges if 'revcount' in req.form: revcount = int(req.form.get('revcount', [revcount])[0]) tmpl.defaults['sessionvars']['revcount'] = revcount lessvars = copy.copy(tmpl.defaults['sessionvars']) lessvars['revcount'] = revcount / 2 morevars = copy.copy(tmpl.defaults['sessionvars']) morevars['revcount'] = revcount * 2 max_rev = len(web.repo) - 1 revcount = min(max_rev, revcount) revnode = web.repo.changelog.node(rev) revnode_hex = hex(revnode) uprev = min(max_rev, rev + revcount) downrev = max(0, rev - revcount) count = len(web.repo) changenav = webutil.revnavgen(rev, revcount, count, web.repo.changectx) dag = graphmod.revisions(web.repo, rev, downrev) tree = list(graphmod.colored(dag)) canvasheight = (len(tree) + 1) * bg_height - 27 data = [] for (id, type, ctx, vtx, edges) in tree: if type != graphmod.CHANGESET: continue node = short(ctx.node()) age = templatefilters.age(ctx.date()) desc = templatefilters.firstline(ctx.description()) desc = cgi.escape(templatefilters.nonempty(desc)) user = cgi.escape(templatefilters.person(ctx.user())) branch = ctx.branch() branch = branch, web.repo.branchtags().get(branch) == ctx.node() data.append((node, vtx, edges, desc, user, age, branch, ctx.tags())) return tmpl('graph', rev=rev, revcount=revcount, uprev=uprev, lessvars=lessvars, morevars=morevars, downrev=downrev, canvasheight=canvasheight, jsdata=data, bg_height=bg_height, node=revnode_hex, changenav=changenav)
def entries(notip=False, limit=0, **map): count = 0 for k, n in i: if notip and k == "tip": continue if limit > 0 and count >= limit: continue count = count + 1 yield { "parity": parity.next(), "tag": k, "date": web.repo[n].date(), "node": hex(n) }
def pushbookmark(repo, key, old, new): w = repo.wlock() try: marks = repo._bookmarks if hex(marks.get(key, '')) != old: return False if new == '': del marks[key] else: if new not in repo: return False marks[key] = repo[new].node() write(repo) return True finally: w.release()
def tagentries(**map): parity = paritygen(web.stripecount) count = 0 for k, n in i: if k == "tip": # skip tip continue count += 1 if count > 10: # limit to 10 tags break yield tmpl("tagentry", parity=parity.next(), tag=k, node=hex(n), date=web.repo[n].date())
def annotate(web, req, tmpl): fctx = webutil.filectx(web.repo, req) f = fctx.path() parity = paritygen(web.stripecount) def annotate(**map): last = None if binary(fctx.data()): mt = (mimetypes.guess_type(fctx.path())[0] or 'application/octet-stream') lines = enumerate([((fctx.filectx(fctx.filerev()), 1), '(binary:%s)' % mt)]) else: lines = enumerate(fctx.annotate(follow=True, linenumber=True)) for lineno, ((f, targetline), l) in lines: fnode = f.filenode() if last != fnode: last = fnode yield { "parity": parity.next(), "node": hex(f.node()), "rev": f.rev(), "author": f.user(), "desc": f.description(), "file": f.path(), "targetline": targetline, "line": l, "lineid": "l%d" % (lineno + 1), "linenumber": "% 6d" % (lineno + 1) } return tmpl("fileannotate", file=f, annotate=annotate, path=webutil.up(f), rev=fctx.rev(), node=hex(fctx.node()), author=fctx.user(), date=fctx.date(), desc=fctx.description(), rename=webutil.renamelink(fctx), branch=webutil.nodebranchnodefault(fctx), parent=webutil.parents(fctx), child=webutil.children(fctx), permissions=fctx.manifest().flags(f))
def changelist(**map): count = 0 qw = query.lower().split() def revgen(): for i in xrange(len(web.repo) - 1, 0, -100): l = [] for j in xrange(max(0, i - 100), i + 1): ctx = web.repo[j] l.append(ctx) l.reverse() for e in l: yield e for ctx in revgen(): miss = 0 for q in qw: if not (q in ctx.user().lower() or q in ctx.description().lower() or q in " ".join(ctx.files()).lower()): miss = 1 break if miss: continue count += 1 n = ctx.node() showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n) files = webutil.listfilediffs(tmpl, ctx.files(), n, web.maxfiles) yield tmpl('searchentry', parity=parity.next(), author=ctx.user(), parent=webutil.parents(ctx), child=webutil.children(ctx), changelogtag=showtags, desc=ctx.description(), date=ctx.date(), files=files, rev=ctx.rev(), node=hex(n), tags=webutil.nodetagsdict(web.repo, n), inbranch=webutil.nodeinbranch(web.repo, ctx), branches=webutil.nodebranchdict(web.repo, ctx)) if count >= revcount: break
def check(ui, repo, rev): """verify all the signatures there may be for a particular revision""" mygpg = newgpg(ui) rev = repo.lookup(rev) hexrev = hgnode.hex(rev) keys = [] for data, context in sigwalk(repo): node, version, sig = data if node == hexrev: k = getkeys(ui, repo, mygpg, data, context) if k: keys.extend(k) if not keys: ui.write(_("No valid signature for %s\n") % hgnode.short(rev)) return # print summary ui.write("%s is signed by:\n" % hgnode.short(rev)) for key in keys: ui.write(" %s\n" % keystr(ui, key))
def changelist(**map): parity = paritygen(web.stripecount, offset=start - end) l = [] # build a list in forward order for efficiency for i in xrange(start, end): ctx = web.repo[i] n = ctx.node() hn = hex(n) l.insert( 0, tmpl('shortlogentry', parity=parity.next(), author=ctx.user(), desc=ctx.description(), date=ctx.date(), rev=i, node=hn, tags=webutil.nodetagsdict(web.repo, n), inbranch=webutil.nodeinbranch(web.repo, ctx), branches=webutil.nodebranchdict(web.repo, ctx))) yield l
def sigs(ui, repo): """list signed changesets""" mygpg = newgpg(ui) revs = {} for data, context in sigwalk(repo): node, version, sig = data fn, ln = context try: n = repo.lookup(node) except KeyError: ui.warn(_("%s:%d node does not exist\n") % (fn, ln)) continue r = repo.changelog.rev(n) keys = getkeys(ui, repo, mygpg, data, context) if not keys: continue revs.setdefault(r, []) revs[r].extend(keys) for rev in sorted(revs, reverse=True): for k in revs[rev]: r = "%5d:%s" % (rev, hgnode.hex(repo.changelog.node(rev))) ui.write("%-30s %s\n" % (keystr(ui, k), r))
def filediff(web, req, tmpl): fctx, ctx = None, None try: fctx = webutil.filectx(web.repo, req) except LookupError: ctx = webutil.changectx(web.repo, req) path = webutil.cleanpath(web.repo, req.form['file'][0]) if path not in ctx.files(): raise if fctx is not None: n = fctx.node() path = fctx.path() else: n = ctx.node() # path already defined in except clause parity = paritygen(web.stripecount) style = web.config('web', 'style', 'paper') if 'style' in req.form: style = req.form['style'][0] diffs = webutil.diffs(web.repo, tmpl, fctx or ctx, [path], parity, style) rename = fctx and webutil.renamelink(fctx) or [] ctx = fctx and fctx or ctx return tmpl("filediff", file=path, node=hex(n), rev=ctx.rev(), date=ctx.date(), desc=ctx.description(), author=ctx.user(), rename=rename, branch=webutil.nodebranchnodefault(ctx), parent=webutil.parents(ctx), child=webutil.children(ctx), diff=diffs)
def sign(ui, repo, *revs, **opts): """add a signature for the current or given revision If no revision is given, the parent of the working directory is used, or tip if no revision is checked out. See :hg:`help dates` for a list of formats valid for -d/--date. """ mygpg = newgpg(ui, **opts) sigver = "0" sigmessage = "" date = opts.get('date') if date: opts['date'] = util.parsedate(date) if revs: nodes = [repo.lookup(n) for n in revs] else: nodes = [ node for node in repo.dirstate.parents() if node != hgnode.nullid ] if len(nodes) > 1: raise util.Abort( _('uncommitted merge - please provide a ' 'specific revision')) if not nodes: nodes = [repo.changelog.tip()] for n in nodes: hexnode = hgnode.hex(n) ui.write( _("Signing %d:%s\n") % (repo.changelog.rev(n), hgnode.short(n))) # build data data = node2txt(repo, n, sigver) sig = mygpg.sign(data) if not sig: raise util.Abort(_("error while signing")) sig = binascii.b2a_base64(sig) sig = sig.replace("\n", "") sigmessage += "%s %s %s\n" % (hexnode, sigver, sig) # write it if opts['local']: repo.opener("localsigs", "ab").write(sigmessage) return msigs = match.exact(repo.root, '', ['.hgsigs']) s = repo.status(match=msigs, unknown=True, ignored=True)[:6] if util.any(s) and not opts["force"]: raise util.Abort( _("working copy of .hgsigs is changed " "(please commit .hgsigs manually " "or use --force)")) repo.wfile(".hgsigs", "ab").write(sigmessage) if '.hgsigs' not in repo.dirstate: repo[None].add([".hgsigs"]) if opts["no_commit"]: return message = opts['message'] if not message: # we don't translate commit messages message = "\n".join([ "Added signature for changeset %s" % hgnode.short(n) for n in nodes ]) try: repo.commit(message, opts['user'], opts['date'], match=msigs) except ValueError, inst: raise util.Abort(str(inst))
def renamelink(fctx): r = fctx.renamed() if r: return [dict(file=r[0], node=hex(r[1]))] return []
def changelog(web, req, tmpl, shortlog=False): if 'node' in req.form: ctx = webutil.changectx(web.repo, req) else: if 'rev' in req.form: hi = req.form['rev'][0] else: hi = len(web.repo) - 1 try: ctx = web.repo[hi] except error.RepoError: return _search(web, req, tmpl) # XXX redirect to 404 page? def changelist(limit=0, **map): l = [] # build a list in forward order for efficiency for i in xrange(start, end): ctx = web.repo[i] n = ctx.node() showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n) files = webutil.listfilediffs(tmpl, ctx.files(), n, web.maxfiles) l.insert( 0, { "parity": parity.next(), "author": ctx.user(), "parent": webutil.parents(ctx, i - 1), "child": webutil.children(ctx, i + 1), "changelogtag": showtags, "desc": ctx.description(), "date": ctx.date(), "files": files, "rev": i, "node": hex(n), "tags": webutil.nodetagsdict(web.repo, n), "inbranch": webutil.nodeinbranch(web.repo, ctx), "branches": webutil.nodebranchdict(web.repo, ctx) }) if limit > 0: l = l[:limit] for e in l: yield e revcount = shortlog and web.maxshortchanges or web.maxchanges if 'revcount' in req.form: revcount = int(req.form.get('revcount', [revcount])[0]) tmpl.defaults['sessionvars']['revcount'] = revcount lessvars = copy.copy(tmpl.defaults['sessionvars']) lessvars['revcount'] = revcount / 2 morevars = copy.copy(tmpl.defaults['sessionvars']) morevars['revcount'] = revcount * 2 count = len(web.repo) pos = ctx.rev() start = max(0, pos - revcount + 1) end = min(count, start + revcount) pos = end - 1 parity = paritygen(web.stripecount, offset=start - end) changenav = webutil.revnavgen(pos, revcount, count, web.repo.changectx) return tmpl(shortlog and 'shortlog' or 'changelog', changenav=changenav, node=hex(ctx.node()), rev=pos, changesets=count, entries=lambda **x: changelist(limit=0, **x), latestentry=lambda **x: changelist(limit=1, **x), archives=web.archivelist("tip"), revcount=revcount, morevars=morevars, lessvars=lessvars)
def node2txt(repo, node, ver): """map a manifest into some text""" if ver == "0": return "%s\n" % hgnode.hex(node) else: raise util.Abort(_("unknown signature version"))
def filelog(web, req, tmpl): try: fctx = webutil.filectx(web.repo, req) f = fctx.path() fl = fctx.filelog() except error.LookupError: f = webutil.cleanpath(web.repo, req.form['file'][0]) fl = web.repo.file(f) numrevs = len(fl) if not numrevs: # file doesn't exist at all raise rev = webutil.changectx(web.repo, req).rev() first = fl.linkrev(0) if rev < first: # current rev is from before file existed raise frev = numrevs - 1 while fl.linkrev(frev) > rev: frev -= 1 fctx = web.repo.filectx(f, fl.linkrev(frev)) revcount = web.maxshortchanges if 'revcount' in req.form: revcount = int(req.form.get('revcount', [revcount])[0]) tmpl.defaults['sessionvars']['revcount'] = revcount lessvars = copy.copy(tmpl.defaults['sessionvars']) lessvars['revcount'] = revcount / 2 morevars = copy.copy(tmpl.defaults['sessionvars']) morevars['revcount'] = revcount * 2 count = fctx.filerev() + 1 start = max(0, fctx.filerev() - revcount + 1) # first rev on this page end = min(count, start + revcount) # last rev on this page parity = paritygen(web.stripecount, offset=start - end) def entries(limit=0, **map): l = [] repo = web.repo for i in xrange(start, end): iterfctx = fctx.filectx(i) l.insert( 0, { "parity": parity.next(), "filerev": i, "file": f, "node": hex(iterfctx.node()), "author": iterfctx.user(), "date": iterfctx.date(), "rename": webutil.renamelink(iterfctx), "parent": webutil.parents(iterfctx), "child": webutil.children(iterfctx), "desc": iterfctx.description(), "tags": webutil.nodetagsdict(repo, iterfctx.node()), "branch": webutil.nodebranchnodefault(iterfctx), "inbranch": webutil.nodeinbranch(repo, iterfctx), "branches": webutil.nodebranchdict(repo, iterfctx) }) if limit > 0: l = l[:limit] for e in l: yield e nodefunc = lambda x: fctx.filectx(fileid=x) nav = webutil.revnavgen(end - 1, revcount, count, nodefunc) return tmpl("filelog", file=f, node=hex(fctx.node()), nav=nav, entries=lambda **x: entries(limit=0, **x), latestentry=lambda **x: entries(limit=1, **x), revcount=revcount, morevars=morevars, lessvars=lessvars)
def manifest(web, req, tmpl): ctx = webutil.changectx(web.repo, req) path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0]) mf = ctx.manifest() node = ctx.node() files = {} dirs = {} parity = paritygen(web.stripecount) if path and path[-1] != "/": path += "/" l = len(path) abspath = "/" + path for f, n in mf.iteritems(): if f[:l] != path: continue remain = f[l:] 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 mf and not files and not dirs: raise ErrorResponse(HTTP_NOT_FOUND, 'path not found: ' + path) def filelist(**map): for f in sorted(files): full = files[f] fctx = ctx.filectx(full) yield { "file": full, "parity": parity.next(), "basename": f, "date": fctx.date(), "size": fctx.size(), "permissions": mf.flags(full) } def dirlist(**map): for d in sorted(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": path, "emptydirs": "/".join(emptydirs), "basename": d } return tmpl("manifest", rev=ctx.rev(), node=hex(node), path=abspath, up=webutil.up(abspath), upparity=parity.next(), fentries=filelist, dentries=dirlist, archives=web.archivelist(hex(node)), tags=webutil.nodetagsdict(web.repo, node), inbranch=webutil.nodeinbranch(web.repo, ctx), branches=webutil.nodebranchdict(web.repo, ctx))