webcommands.py
1014 lines
| 34.7 KiB
| text/x-python
|
PythonLexer
Dirkjan Ochtman
|
r5591 | # | ||
# Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net> | ||||
# Copyright 2005-2007 Matt Mackall <mpm@selenic.com> | ||||
# | ||||
Martin Geisler
|
r8225 | # This software may be used and distributed according to the terms of the | ||
Matt Mackall
|
r10263 | # GNU General Public License version 2 or any later version. | ||
Dirkjan Ochtman
|
r5591 | |||
Dirkjan Ochtman
|
r7345 | import os, mimetypes, re, cgi, copy | ||
Dirkjan Ochtman
|
r6392 | import webutil | ||
Julian Cowley
|
r11332 | from mercurial import error, encoding, archival, templater, templatefilters | ||
wujek srujek
|
r17302 | from mercurial.node import short, hex, nullid | ||
Peter Arrenbrecht
|
r7873 | from mercurial.util import binary | ||
Dirkjan Ochtman
|
r6393 | from common import paritygen, staticfile, get_contact, ErrorResponse | ||
Rocco Rutte
|
r7029 | from common import HTTP_OK, HTTP_FORBIDDEN, HTTP_NOT_FOUND | ||
Patrick Mezard
|
r15528 | from mercurial import graphmod, patch | ||
Augie Fackler
|
r12666 | from mercurial import help as helpmod | ||
Jordi Gutiérrez Hermoso
|
r17933 | from mercurial import scmutil | ||
Augie Fackler
|
r12666 | from mercurial.i18n import _ | ||
Dirkjan Ochtman
|
r5591 | |||
Dirkjan Ochtman
|
r5963 | # __all__ is populated with the allowed commands. Be sure to add to it if | ||
# you're adding a new command, or the new command won't work. | ||||
__all__ = [ | ||||
'log', 'rawfile', 'file', 'changelog', 'shortlog', 'changeset', 'rev', | ||||
Alexander Solovyov
|
r13597 | 'manifest', 'tags', 'bookmarks', 'branches', 'summary', 'filediff', 'diff', | ||
wujek srujek
|
r17202 | 'comparison', 'annotate', 'filelog', 'archive', 'static', 'graph', 'help', | ||
Dirkjan Ochtman
|
r5963 | ] | ||
Dirkjan Ochtman
|
r5600 | def log(web, req, tmpl): | ||
Christian Ebert
|
r5915 | if 'file' in req.form and req.form['file'][0]: | ||
Dirkjan Ochtman
|
r5964 | return filelog(web, req, tmpl) | ||
Dirkjan Ochtman
|
r5591 | else: | ||
Dirkjan Ochtman
|
r5964 | return changelog(web, req, tmpl) | ||
Dirkjan Ochtman
|
r5591 | |||
Dirkjan Ochtman
|
r5890 | def rawfile(web, req, tmpl): | ||
Matt Mackall
|
r15004 | guessmime = web.configbool('web', 'guessmime', False) | ||
Dirkjan Ochtman
|
r6392 | path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0]) | ||
Dirkjan Ochtman
|
r5890 | if not path: | ||
Dirkjan Ochtman
|
r6393 | content = manifest(web, req, tmpl) | ||
Dirkjan Ochtman
|
r5993 | req.respond(HTTP_OK, web.ctype) | ||
return content | ||||
Dirkjan Ochtman
|
r5890 | |||
try: | ||||
Dirkjan Ochtman
|
r6392 | fctx = webutil.filectx(web.repo, req) | ||
Matt Mackall
|
r7633 | except error.LookupError, inst: | ||
Dirkjan Ochtman
|
r6368 | try: | ||
Dirkjan Ochtman
|
r6393 | content = manifest(web, req, tmpl) | ||
Dirkjan Ochtman
|
r6368 | req.respond(HTTP_OK, web.ctype) | ||
return content | ||||
except ErrorResponse: | ||||
raise inst | ||||
Dirkjan Ochtman
|
r5890 | |||
path = fctx.path() | ||||
text = fctx.data() | ||||
Matt Mackall
|
r15004 | mt = 'application/binary' | ||
if guessmime: | ||||
mt = mimetypes.guess_type(path)[0] | ||||
if mt is None: | ||||
mt = binary(text) and 'application/binary' or 'text/plain' | ||||
Julian Cowley
|
r11332 | if mt.startswith('text/'): | ||
mt += '; charset="%s"' % encoding.encoding | ||||
Dirkjan Ochtman
|
r5890 | |||
Mads Kiilerich
|
r18352 | req.respond(HTTP_OK, mt, path, body=text) | ||
return [] | ||||
Dirkjan Ochtman
|
r5890 | |||
Dirkjan Ochtman
|
r6393 | 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(): | ||||
Nicolas Dumazet
|
r9136 | for lineno, t in enumerate(text.splitlines(True)): | ||
Dirkjan Ochtman
|
r6393 | 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(), | ||||
Alexander Solovyov
|
r14055 | node=fctx.hex(), | ||
Dirkjan Ochtman
|
r6393 | author=fctx.user(), | ||
date=fctx.date(), | ||||
desc=fctx.description(), | ||||
Benoit Boissinot
|
r18581 | extra=fctx.extra(), | ||
Dirkjan Ochtman
|
r6393 | branch=webutil.nodebranchnodefault(fctx), | ||
Dirkjan Ochtman
|
r7671 | parent=webutil.parents(fctx), | ||
child=webutil.children(fctx), | ||||
Matt Mackall
|
r6434 | rename=webutil.renamelink(fctx), | ||
Dirkjan Ochtman
|
r6393 | permissions=fctx.manifest().flags(f)) | ||
Dirkjan Ochtman
|
r5600 | def file(web, req, tmpl): | ||
Dirkjan Ochtman
|
r6392 | path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0]) | ||
Benoit Boissinot
|
r6853 | if not path: | ||
Patrick Mezard
|
r6857 | return manifest(web, req, tmpl) | ||
Benoit Boissinot
|
r6853 | try: | ||
Patrick Mezard
|
r6857 | return _filerevision(web, tmpl, webutil.filectx(web.repo, req)) | ||
Matt Mackall
|
r7633 | except error.LookupError, inst: | ||
Dirkjan Ochtman
|
r5591 | try: | ||
Patrick Mezard
|
r6857 | return manifest(web, req, tmpl) | ||
Benoit Boissinot
|
r6853 | except ErrorResponse: | ||
raise inst | ||||
Dirkjan Ochtman
|
r5591 | |||
Dirkjan Ochtman
|
r10247 | def _search(web, req, tmpl): | ||
query = req.form['rev'][0] | ||||
revcount = web.maxchanges | ||||
if 'revcount' in req.form: | ||||
revcount = int(req.form.get('revcount', [revcount])[0]) | ||||
Md. O. Shayan
|
r13931 | revcount = max(revcount, 1) | ||
Dirkjan Ochtman
|
r10247 | tmpl.defaults['sessionvars']['revcount'] = revcount | ||
lessvars = copy.copy(tmpl.defaults['sessionvars']) | ||||
Md. O. Shayan
|
r13931 | lessvars['revcount'] = max(revcount / 2, 1) | ||
Dirkjan Ochtman
|
r10247 | lessvars['rev'] = query | ||
morevars = copy.copy(tmpl.defaults['sessionvars']) | ||||
morevars['revcount'] = revcount * 2 | ||||
morevars['rev'] = query | ||||
Dirkjan Ochtman
|
r6393 | |||
def changelist(**map): | ||||
count = 0 | ||||
FUJIWARA Katsunori
|
r15727 | lower = encoding.lower | ||
qw = lower(query).split() | ||||
Dirkjan Ochtman
|
r6393 | |||
def revgen(): | ||||
Pierre-Yves David
|
r18497 | cl = web.repo.changelog | ||
Patrick Mezard
|
r12059 | for i in xrange(len(web.repo) - 1, 0, -100): | ||
Dirkjan Ochtman
|
r6393 | l = [] | ||
Pierre-Yves David
|
r18497 | for j in cl.revs(max(0, i - 100), i + 1): | ||
Matt Mackall
|
r6747 | ctx = web.repo[j] | ||
Dirkjan Ochtman
|
r6393 | l.append(ctx) | ||
l.reverse() | ||||
for e in l: | ||||
yield e | ||||
for ctx in revgen(): | ||||
miss = 0 | ||||
for q in qw: | ||||
FUJIWARA Katsunori
|
r15727 | if not (q in lower(ctx.user()) or | ||
q in lower(ctx.description()) or | ||||
q in lower(" ".join(ctx.files()))): | ||||
Dirkjan Ochtman
|
r6393 | miss = 1 | ||
break | ||||
if miss: | ||||
continue | ||||
Andrew Beekhof
|
r6659 | count += 1 | ||
Dirkjan Ochtman
|
r6393 | n = ctx.node() | ||
showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n) | ||||
Dirkjan Ochtman
|
r7311 | files = webutil.listfilediffs(tmpl, ctx.files(), n, web.maxfiles) | ||
Dirkjan Ochtman
|
r6393 | |||
yield tmpl('searchentry', | ||||
parity=parity.next(), | ||||
author=ctx.user(), | ||||
Dirkjan Ochtman
|
r7671 | parent=webutil.parents(ctx), | ||
child=webutil.children(ctx), | ||||
Dirkjan Ochtman
|
r6393 | changelogtag=showtags, | ||
desc=ctx.description(), | ||||
Benoit Boissinot
|
r18581 | extra=ctx.extra(), | ||
Dirkjan Ochtman
|
r6393 | date=ctx.date(), | ||
Dirkjan Ochtman
|
r7311 | files=files, | ||
Dirkjan Ochtman
|
r6393 | rev=ctx.rev(), | ||
node=hex(n), | ||||
tags=webutil.nodetagsdict(web.repo, n), | ||||
Yuya Nishihara
|
r13794 | bookmarks=webutil.nodebookmarksdict(web.repo, n), | ||
Dirkjan Ochtman
|
r6393 | inbranch=webutil.nodeinbranch(web.repo, ctx), | ||
branches=webutil.nodebranchdict(web.repo, ctx)) | ||||
Dirkjan Ochtman
|
r10247 | if count >= revcount: | ||
Dirkjan Ochtman
|
r6393 | break | ||
Patrick Mezard
|
r12059 | tip = web.repo['tip'] | ||
Dirkjan Ochtman
|
r6393 | parity = paritygen(web.stripecount) | ||
Patrick Mezard
|
r12059 | return tmpl('search', query=query, node=tip.hex(), | ||
Dirkjan Ochtman
|
r10247 | entries=changelist, archives=web.archivelist("tip"), | ||
morevars=morevars, lessvars=lessvars) | ||||
Dirkjan Ochtman
|
r6393 | |||
Dirkjan Ochtman
|
r10247 | def changelog(web, req, tmpl, shortlog=False): | ||
Christian Ebert
|
r5915 | if 'node' in req.form: | ||
Dirkjan Ochtman
|
r6392 | ctx = webutil.changectx(web.repo, req) | ||
Dirkjan Ochtman
|
r5591 | else: | ||
Christian Ebert
|
r5915 | if 'rev' in req.form: | ||
Dirkjan Ochtman
|
r5591 | hi = req.form['rev'][0] | ||
else: | ||||
Kevin Bullock
|
r18477 | hi = 'tip' | ||
Dirkjan Ochtman
|
r5591 | try: | ||
Matt Mackall
|
r6747 | ctx = web.repo[hi] | ||
Matt Mackall
|
r7637 | except error.RepoError: | ||
Dirkjan Ochtman
|
r10247 | return _search(web, req, tmpl) # XXX redirect to 404 page? | ||
Dirkjan Ochtman
|
r6393 | |||
Pierre-Yves David
|
r18402 | def changelist(latestonly, **map): | ||
Dirkjan Ochtman
|
r6393 | l = [] # build a list in forward order for efficiency | ||
Pierre-Yves David
|
r18427 | revs = [] | ||
if start < end: | ||||
revs = web.repo.changelog.revs(start, end - 1) | ||||
Pierre-Yves David
|
r18402 | if latestonly: | ||
Pierre-Yves David
|
r18427 | for r in revs: | ||
pass | ||||
revs = (r,) | ||||
Pierre-Yves David
|
r18402 | for i in revs: | ||
Matt Mackall
|
r6747 | ctx = web.repo[i] | ||
Dirkjan Ochtman
|
r6393 | n = ctx.node() | ||
showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n) | ||||
Dirkjan Ochtman
|
r7311 | files = webutil.listfilediffs(tmpl, ctx.files(), n, web.maxfiles) | ||
Dirkjan Ochtman
|
r6393 | |||
Pierre-Yves David
|
r18319 | l.append({"parity": parity.next(), | ||
"author": ctx.user(), | ||||
"parent": webutil.parents(ctx, i - 1), | ||||
"child": webutil.children(ctx, i + 1), | ||||
"changelogtag": showtags, | ||||
"desc": ctx.description(), | ||||
Benoit Boissinot
|
r18581 | "extra": ctx.extra(), | ||
Pierre-Yves David
|
r18319 | "date": ctx.date(), | ||
"files": files, | ||||
"rev": i, | ||||
"node": hex(n), | ||||
"tags": webutil.nodetagsdict(web.repo, n), | ||||
"bookmarks": webutil.nodebookmarksdict(web.repo, n), | ||||
"inbranch": webutil.nodeinbranch(web.repo, ctx), | ||||
"branches": webutil.nodebranchdict(web.repo, ctx) | ||||
}) | ||||
for e in reversed(l): | ||||
Dirkjan Ochtman
|
r6393 | yield e | ||
Dirkjan Ochtman
|
r10246 | revcount = shortlog and web.maxshortchanges or web.maxchanges | ||
if 'revcount' in req.form: | ||||
revcount = int(req.form.get('revcount', [revcount])[0]) | ||||
Md. O. Shayan
|
r13931 | revcount = max(revcount, 1) | ||
Dirkjan Ochtman
|
r10246 | tmpl.defaults['sessionvars']['revcount'] = revcount | ||
lessvars = copy.copy(tmpl.defaults['sessionvars']) | ||||
Md. O. Shayan
|
r13931 | lessvars['revcount'] = max(revcount / 2, 1) | ||
Dirkjan Ochtman
|
r10246 | morevars = copy.copy(tmpl.defaults['sessionvars']) | ||
morevars['revcount'] = revcount * 2 | ||||
Patrick Mezard
|
r12059 | count = len(web.repo) | ||
Dirkjan Ochtman
|
r6393 | pos = ctx.rev() | ||
Dirkjan Ochtman
|
r10246 | start = max(0, pos - revcount + 1) | ||
end = min(count, start + revcount) | ||||
Dirkjan Ochtman
|
r6393 | pos = end - 1 | ||
Matt Mackall
|
r10282 | parity = paritygen(web.stripecount, offset=start - end) | ||
Dirkjan Ochtman
|
r6393 | |||
Pierre-Yves David
|
r18409 | changenav = webutil.revnav(web.repo).gen(pos, revcount, count) | ||
Dirkjan Ochtman
|
r6393 | |||
Dirkjan Ochtman
|
r10246 | return tmpl(shortlog and 'shortlog' or 'changelog', changenav=changenav, | ||
Alexander Solovyov
|
r14055 | node=ctx.hex(), rev=pos, changesets=count, | ||
Pierre-Yves David
|
r18402 | entries=lambda **x: changelist(latestonly=False, **x), | ||
latestentry=lambda **x: changelist(latestonly=True, **x), | ||||
Dirkjan Ochtman
|
r10246 | archives=web.archivelist("tip"), revcount=revcount, | ||
morevars=morevars, lessvars=lessvars) | ||||
Dirkjan Ochtman
|
r5591 | |||
Dirkjan Ochtman
|
r5600 | def shortlog(web, req, tmpl): | ||
Dirkjan Ochtman
|
r5964 | return changelog(web, req, tmpl, shortlog = True) | ||
Dirkjan Ochtman
|
r5591 | |||
Dirkjan Ochtman
|
r5600 | def changeset(web, req, tmpl): | ||
Dirkjan Ochtman
|
r6393 | ctx = webutil.changectx(web.repo, req) | ||
Weiwen
|
r17991 | basectx = webutil.basechangectx(web.repo, req) | ||
if basectx is None: | ||||
basectx = ctx.p1() | ||||
Dirkjan Ochtman
|
r7310 | showtags = webutil.showtag(web.repo, tmpl, 'changesettag', ctx.node()) | ||
Alexander Solovyov
|
r13596 | showbookmarks = webutil.showbookmark(web.repo, tmpl, 'changesetbookmark', | ||
ctx.node()) | ||||
Dirkjan Ochtman
|
r7410 | showbranch = webutil.nodebranchnodefault(ctx) | ||
Dirkjan Ochtman
|
r6393 | |||
files = [] | ||||
parity = paritygen(web.stripecount) | ||||
Paul Boddie
|
r16308 | for blockno, f in enumerate(ctx.files()): | ||
Dirkjan Ochtman
|
r7182 | template = f in ctx and 'filenodelink' or 'filenolink' | ||
files.append(tmpl(template, | ||||
Paul Boddie
|
r16308 | node=ctx.hex(), file=f, blockno=blockno + 1, | ||
Dirkjan Ochtman
|
r6393 | parity=parity.next())) | ||
Dirkjan Ochtman
|
r9402 | style = web.config('web', 'style', 'paper') | ||
if 'style' in req.form: | ||||
style = req.form['style'][0] | ||||
Steven Brown
|
r14490 | parity = paritygen(web.stripecount) | ||
Weiwen
|
r17991 | diffs = webutil.diffs(web.repo, tmpl, ctx, basectx, None, parity, style) | ||
Steven Brown
|
r14490 | |||
parity = paritygen(web.stripecount) | ||||
Weiwen
|
r17991 | diffstatgen = webutil.diffstatgen(ctx, basectx) | ||
Steven Brown
|
r14570 | diffstat = webutil.diffstat(tmpl, ctx, diffstatgen, parity) | ||
Steven Brown
|
r14490 | |||
Dirkjan Ochtman
|
r6393 | return tmpl('changeset', | ||
diff=diffs, | ||||
rev=ctx.rev(), | ||||
Dirkjan Ochtman
|
r7310 | node=ctx.hex(), | ||
Dirkjan Ochtman
|
r7671 | parent=webutil.parents(ctx), | ||
child=webutil.children(ctx), | ||||
Kevin Bullock
|
r18524 | basenode=basectx.hex(), | ||
Dirkjan Ochtman
|
r6393 | changesettag=showtags, | ||
Alexander Solovyov
|
r13596 | changesetbookmark=showbookmarks, | ||
Dirkjan Ochtman
|
r7410 | changesetbranch=showbranch, | ||
Dirkjan Ochtman
|
r6393 | author=ctx.user(), | ||
desc=ctx.description(), | ||||
Benoit Boissinot
|
r18581 | extra=ctx.extra(), | ||
Dirkjan Ochtman
|
r6393 | date=ctx.date(), | ||
files=files, | ||||
Steven Brown
|
r14570 | diffsummary=lambda **x: webutil.diffsummary(diffstatgen), | ||
Steven Brown
|
r14490 | diffstat=diffstat, | ||
Dirkjan Ochtman
|
r7310 | archives=web.archivelist(ctx.hex()), | ||
tags=webutil.nodetagsdict(web.repo, ctx.node()), | ||||
Alexander Solovyov
|
r13596 | bookmarks=webutil.nodebookmarksdict(web.repo, ctx.node()), | ||
Dirkjan Ochtman
|
r6393 | branch=webutil.nodebranchnodefault(ctx), | ||
inbranch=webutil.nodeinbranch(web.repo, ctx), | ||||
branches=webutil.nodebranchdict(web.repo, ctx)) | ||||
Dirkjan Ochtman
|
r5591 | |||
rev = changeset | ||||
Martin Geisler
|
r16448 | def decodepath(path): | ||
"""Hook for mapping a path in the repository to a path in the | ||||
working copy. | ||||
Extensions (e.g., largefiles) can override this to remap files in | ||||
the virtual file system presented by the manifest command below.""" | ||||
return path | ||||
Dirkjan Ochtman
|
r5600 | def manifest(web, req, tmpl): | ||
Dirkjan Ochtman
|
r6393 | ctx = webutil.changectx(web.repo, req) | ||
path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0]) | ||||
mf = ctx.manifest() | ||||
node = ctx.node() | ||||
files = {} | ||||
Ry4an Brase
|
r7305 | dirs = {} | ||
Dirkjan Ochtman
|
r6393 | parity = paritygen(web.stripecount) | ||
if path and path[-1] != "/": | ||||
path += "/" | ||||
l = len(path) | ||||
abspath = "/" + path | ||||
Martin Geisler
|
r16448 | for full, n in mf.iteritems(): | ||
# the virtual path (working copy path) used for the full | ||||
# (repository) path | ||||
f = decodepath(full) | ||||
Dirkjan Ochtman
|
r6393 | if f[:l] != path: | ||
continue | ||||
remain = f[l:] | ||||
Ry4an Brase
|
r7305 | elements = remain.split('/') | ||
if len(elements) == 1: | ||||
Martin Geisler
|
r16448 | files[remain] = full | ||
Ry4an Brase
|
r7305 | 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 | ||||
Dirkjan Ochtman
|
r6393 | |||
Dirkjan Ochtman
|
r7565 | if mf and not files and not dirs: | ||
Dirkjan Ochtman
|
r6393 | raise ErrorResponse(HTTP_NOT_FOUND, 'path not found: ' + path) | ||
def filelist(**map): | ||||
Matt Mackall
|
r8209 | for f in sorted(files): | ||
Ry4an Brase
|
r7305 | full = files[f] | ||
Dirkjan Ochtman
|
r6393 | |||
fctx = ctx.filectx(full) | ||||
yield {"file": full, | ||||
"parity": parity.next(), | ||||
"basename": f, | ||||
Matt Mackall
|
r6747 | "date": fctx.date(), | ||
Dirkjan Ochtman
|
r6393 | "size": fctx.size(), | ||
"permissions": mf.flags(full)} | ||||
def dirlist(**map): | ||||
Matt Mackall
|
r8209 | for d in sorted(dirs): | ||
Dirkjan Ochtman
|
r6393 | |||
Ry4an Brase
|
r7305 | emptydirs = [] | ||
h = dirs[d] | ||||
while isinstance(h, dict) and len(h) == 1: | ||||
Matt Mackall
|
r10282 | k, v = h.items()[0] | ||
Ry4an Brase
|
r7305 | if v: | ||
emptydirs.append(k) | ||||
h = v | ||||
path = "%s%s" % (abspath, d) | ||||
Dirkjan Ochtman
|
r6393 | yield {"parity": parity.next(), | ||
Ry4an Brase
|
r7305 | "path": path, | ||
"emptydirs": "/".join(emptydirs), | ||||
"basename": d} | ||||
Dirkjan Ochtman
|
r6393 | |||
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), | ||||
Yuya Nishihara
|
r13794 | bookmarks=webutil.nodebookmarksdict(web.repo, node), | ||
Dirkjan Ochtman
|
r6393 | inbranch=webutil.nodeinbranch(web.repo, ctx), | ||
branches=webutil.nodebranchdict(web.repo, ctx)) | ||||
Dirkjan Ochtman
|
r5591 | |||
Dirkjan Ochtman
|
r5600 | def tags(web, req, tmpl): | ||
Matt Mackall
|
r18029 | i = list(reversed(web.repo.tagslist())) | ||
Dirkjan Ochtman
|
r6393 | parity = paritygen(web.stripecount) | ||
Pierre-Yves David
|
r18402 | def entries(notip, latestonly, **map): | ||
t = i | ||||
if notip: | ||||
t = [(k, n) for k, n in i if k != "tip"] | ||||
if latestonly: | ||||
t = t[:1] | ||||
for k, n in t: | ||||
Dirkjan Ochtman
|
r6393 | yield {"parity": parity.next(), | ||
"tag": k, | ||||
Matt Mackall
|
r6747 | "date": web.repo[n].date(), | ||
Dirkjan Ochtman
|
r6393 | "node": hex(n)} | ||
return tmpl("tags", | ||||
node=hex(web.repo.changelog.tip()), | ||||
Pierre-Yves David
|
r18402 | entries=lambda **x: entries(False, False, **x), | ||
entriesnotip=lambda **x: entries(True, False, **x), | ||||
latestentry=lambda **x: entries(True, True, **x)) | ||||
Dirkjan Ochtman
|
r5591 | |||
Alexander Solovyov
|
r13597 | def bookmarks(web, req, tmpl): | ||
Kevin Bullock
|
r18478 | i = [b for b in web.repo._bookmarks.items() if b[1] in web.repo] | ||
Alexander Solovyov
|
r13597 | parity = paritygen(web.stripecount) | ||
Pierre-Yves David
|
r18402 | def entries(latestonly, **map): | ||
if latestonly: | ||||
t = [min(i)] | ||||
else: | ||||
t = sorted(i) | ||||
for k, n in t: | ||||
Alexander Solovyov
|
r13597 | yield {"parity": parity.next(), | ||
"bookmark": k, | ||||
"date": web.repo[n].date(), | ||||
"node": hex(n)} | ||||
return tmpl("bookmarks", | ||||
node=hex(web.repo.changelog.tip()), | ||||
Pierre-Yves David
|
r18402 | entries=lambda **x: entries(latestonly=False, **x), | ||
latestentry=lambda **x: entries(latestonly=True, **x)) | ||||
Alexander Solovyov
|
r13597 | |||
Sune Foldager
|
r8352 | def branches(web, req, tmpl): | ||
Matt Mackall
|
r18030 | tips = [] | ||
John Mulligan
|
r8796 | heads = web.repo.heads() | ||
Sune Foldager
|
r8352 | parity = paritygen(web.stripecount) | ||
Brodie Rao
|
r16720 | sortkey = lambda ctx: (not ctx.closesbranch(), ctx.rev()) | ||
Sune Foldager
|
r8352 | |||
def entries(limit, **map): | ||||
count = 0 | ||||
Matt Mackall
|
r18030 | if not tips: | ||
for t, n in web.repo.branchtags().iteritems(): | ||||
tips.append(web.repo[n]) | ||||
Dirkjan Ochtman
|
r8713 | for ctx in sorted(tips, key=sortkey, reverse=True): | ||
Sune Foldager
|
r8352 | if limit > 0 and count >= limit: | ||
return | ||||
count += 1 | ||||
Jesse Long
|
r14771 | if not web.repo.branchheads(ctx.branch()): | ||
status = 'closed' | ||||
elif ctx.node() not in heads: | ||||
John Mulligan
|
r8796 | status = 'inactive' | ||
else: | ||||
status = 'open' | ||||
Sune Foldager
|
r8352 | yield {'parity': parity.next(), | ||
Dirkjan Ochtman
|
r8354 | 'branch': ctx.branch(), | ||
Dirkjan Ochtman
|
r8713 | 'status': status, | ||
Dirkjan Ochtman
|
r8354 | 'node': ctx.hex(), | ||
'date': ctx.date()} | ||||
Sune Foldager
|
r8352 | |||
return tmpl('branches', node=hex(web.repo.changelog.tip()), | ||||
entries=lambda **x: entries(0, **x), | ||||
latestentry=lambda **x: entries(1, **x)) | ||||
Dirkjan Ochtman
|
r5600 | def summary(web, req, tmpl): | ||
Patrick Mezard
|
r17261 | i = reversed(web.repo.tagslist()) | ||
Dirkjan Ochtman
|
r6393 | |||
def tagentries(**map): | ||||
parity = paritygen(web.stripecount) | ||||
count = 0 | ||||
for k, n in i: | ||||
if k == "tip": # skip tip | ||||
continue | ||||
Andrew Beekhof
|
r6659 | count += 1 | ||
Dirkjan Ochtman
|
r6393 | if count > 10: # limit to 10 tags | ||
break | ||||
yield tmpl("tagentry", | ||||
parity=parity.next(), | ||||
tag=k, | ||||
node=hex(n), | ||||
Matt Mackall
|
r6747 | date=web.repo[n].date()) | ||
Dirkjan Ochtman
|
r6393 | |||
Yuya Nishihara
|
r13924 | def bookmarks(**map): | ||
parity = paritygen(web.stripecount) | ||||
Kevin Bullock
|
r18563 | marks = [b for b in web.repo._bookmarks.items() if b[1] in web.repo] | ||
for k, n in sorted(marks)[:10]: # limit to 10 bookmarks | ||||
Yuya Nishihara
|
r13924 | yield {'parity': parity.next(), | ||
'bookmark': k, | ||||
'date': web.repo[n].date(), | ||||
'node': hex(n)} | ||||
Dirkjan Ochtman
|
r6393 | def branches(**map): | ||
parity = paritygen(web.stripecount) | ||||
b = web.repo.branchtags() | ||||
Dirkjan Ochtman
|
r7622 | l = [(-web.repo.changelog.rev(n), n, t) for t, n in b.iteritems()] | ||
Matt Mackall
|
r10282 | for r, n, t in sorted(l): | ||
Dirkjan Ochtman
|
r6393 | yield {'parity': parity.next(), | ||
'branch': t, | ||||
'node': hex(n), | ||||
Matt Mackall
|
r6747 | 'date': web.repo[n].date()} | ||
Dirkjan Ochtman
|
r6393 | |||
def changelist(**map): | ||||
Matt Mackall
|
r10282 | parity = paritygen(web.stripecount, offset=start - end) | ||
Dirkjan Ochtman
|
r6393 | l = [] # build a list in forward order for efficiency | ||
Kevin Bullock
|
r18563 | revs = [] | ||
if start < end: | ||||
revs = web.repo.changelog.revs(start, end - 1) | ||||
for i in revs: | ||||
Matt Mackall
|
r6747 | ctx = web.repo[i] | ||
Dirkjan Ochtman
|
r6393 | n = ctx.node() | ||
hn = hex(n) | ||||
Pierre-Yves David
|
r18319 | l.append(tmpl( | ||
Dirkjan Ochtman
|
r6393 | 'shortlogentry', | ||
parity=parity.next(), | ||||
author=ctx.user(), | ||||
desc=ctx.description(), | ||||
Benoit Boissinot
|
r18581 | extra=ctx.extra(), | ||
Dirkjan Ochtman
|
r6393 | date=ctx.date(), | ||
rev=i, | ||||
node=hn, | ||||
tags=webutil.nodetagsdict(web.repo, n), | ||||
Yuya Nishihara
|
r13794 | bookmarks=webutil.nodebookmarksdict(web.repo, n), | ||
Dirkjan Ochtman
|
r6393 | inbranch=webutil.nodeinbranch(web.repo, ctx), | ||
branches=webutil.nodebranchdict(web.repo, ctx))) | ||||
Pierre-Yves David
|
r18319 | l.reverse() | ||
Dirkjan Ochtman
|
r6393 | yield l | ||
Patrick Mezard
|
r12059 | tip = web.repo['tip'] | ||
count = len(web.repo) | ||||
Dirkjan Ochtman
|
r6393 | start = max(0, count - web.maxchanges) | ||
end = min(count, start + web.maxchanges) | ||||
return tmpl("summary", | ||||
desc=web.config("web", "description", "unknown"), | ||||
owner=get_contact(web.config) or "unknown", | ||||
Patrick Mezard
|
r12059 | lastchange=tip.date(), | ||
Dirkjan Ochtman
|
r6393 | tags=tagentries, | ||
Yuya Nishihara
|
r13924 | bookmarks=bookmarks, | ||
Dirkjan Ochtman
|
r6393 | branches=branches, | ||
shortlog=changelist, | ||||
Patrick Mezard
|
r12059 | node=tip.hex(), | ||
Dirkjan Ochtman
|
r6393 | archives=web.archivelist("tip")) | ||
Dirkjan Ochtman
|
r5591 | |||
Dirkjan Ochtman
|
r5600 | def filediff(web, req, tmpl): | ||
Dirkjan Ochtman
|
r7183 | fctx, ctx = None, None | ||
try: | ||||
fctx = webutil.filectx(web.repo, req) | ||||
Benoit Boissinot
|
r7280 | except LookupError: | ||
Dirkjan Ochtman
|
r7183 | 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() | ||||
Matt Mackall
|
r16722 | ctx = fctx.changectx() | ||
Dirkjan Ochtman
|
r7183 | else: | ||
n = ctx.node() | ||||
# path already defined in except clause | ||||
Dirkjan Ochtman
|
r6393 | |||
Dirkjan Ochtman
|
r7310 | parity = paritygen(web.stripecount) | ||
Dirkjan Ochtman
|
r9402 | style = web.config('web', 'style', 'paper') | ||
if 'style' in req.form: | ||||
style = req.form['style'][0] | ||||
Weiwen
|
r17991 | diffs = webutil.diffs(web.repo, tmpl, ctx, None, [path], parity, style) | ||
Dirkjan Ochtman
|
r7183 | rename = fctx and webutil.renamelink(fctx) or [] | ||
ctx = fctx and fctx or ctx | ||||
Dirkjan Ochtman
|
r6393 | return tmpl("filediff", | ||
file=path, | ||||
node=hex(n), | ||||
Dirkjan Ochtman
|
r7183 | rev=ctx.rev(), | ||
date=ctx.date(), | ||||
desc=ctx.description(), | ||||
Benoit Boissinot
|
r18581 | extra=ctx.extra(), | ||
Dirkjan Ochtman
|
r7183 | author=ctx.user(), | ||
rename=rename, | ||||
branch=webutil.nodebranchnodefault(ctx), | ||||
Dirkjan Ochtman
|
r7671 | parent=webutil.parents(ctx), | ||
child=webutil.children(ctx), | ||||
Dirkjan Ochtman
|
r6393 | diff=diffs) | ||
Dirkjan Ochtman
|
r5591 | |||
diff = filediff | ||||
wujek srujek
|
r17202 | def comparison(web, req, tmpl): | ||
ctx = webutil.changectx(web.repo, req) | ||||
Ross Lagerwall
|
r17289 | if 'file' not in req.form: | ||
raise ErrorResponse(HTTP_NOT_FOUND, 'file not given') | ||||
wujek srujek
|
r17202 | path = webutil.cleanpath(web.repo, req.form['file'][0]) | ||
rename = path in ctx and webutil.renamelink(ctx[path]) or [] | ||||
parsecontext = lambda v: v == 'full' and -1 or int(v) | ||||
if 'context' in req.form: | ||||
context = parsecontext(req.form['context'][0]) | ||||
else: | ||||
context = parsecontext(web.config('web', 'comparisoncontext', '5')) | ||||
wujek srujek
|
r17302 | def filelines(f): | ||
if binary(f.data()): | ||||
mt = mimetypes.guess_type(f.path())[0] | ||||
if not mt: | ||||
mt = 'application/octet-stream' | ||||
return [_('(binary file %s, hash: %s)') % (mt, hex(f.filenode()))] | ||||
return f.data().splitlines() | ||||
if path in ctx: | ||||
fctx = ctx[path] | ||||
rightrev = fctx.filerev() | ||||
rightnode = fctx.filenode() | ||||
rightlines = filelines(fctx) | ||||
parents = fctx.parents() | ||||
if not parents: | ||||
leftrev = -1 | ||||
leftnode = nullid | ||||
leftlines = () | ||||
else: | ||||
pfctx = parents[0] | ||||
leftrev = pfctx.filerev() | ||||
leftnode = pfctx.filenode() | ||||
leftlines = filelines(pfctx) | ||||
else: | ||||
rightrev = -1 | ||||
rightnode = nullid | ||||
rightlines = () | ||||
fctx = ctx.parents()[0][path] | ||||
leftrev = fctx.filerev() | ||||
leftnode = fctx.filenode() | ||||
leftlines = filelines(fctx) | ||||
comparison = webutil.compare(tmpl, context, leftlines, rightlines) | ||||
wujek srujek
|
r17202 | return tmpl('filecomparison', | ||
file=path, | ||||
node=hex(ctx.node()), | ||||
rev=ctx.rev(), | ||||
date=ctx.date(), | ||||
desc=ctx.description(), | ||||
Benoit Boissinot
|
r18581 | extra=ctx.extra(), | ||
wujek srujek
|
r17202 | author=ctx.user(), | ||
rename=rename, | ||||
branch=webutil.nodebranchnodefault(ctx), | ||||
wujek srujek
|
r17303 | parent=webutil.parents(fctx), | ||
child=webutil.children(fctx), | ||||
wujek srujek
|
r17302 | leftrev=leftrev, | ||
leftnode=hex(leftnode), | ||||
rightrev=rightrev, | ||||
rightnode=hex(rightnode), | ||||
wujek srujek
|
r17202 | comparison=comparison) | ||
Dirkjan Ochtman
|
r5600 | def annotate(web, req, tmpl): | ||
Dirkjan Ochtman
|
r6393 | fctx = webutil.filectx(web.repo, req) | ||
f = fctx.path() | ||||
parity = paritygen(web.stripecount) | ||||
Patrick Mezard
|
r15528 | diffopts = patch.diffopts(web.repo.ui, untrusted=True, section='annotate') | ||
Dirkjan Ochtman
|
r6393 | |||
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: | ||||
Patrick Mezard
|
r15528 | lines = enumerate(fctx.annotate(follow=True, linenumber=True, | ||
diffopts=diffopts)) | ||||
Dirkjan Ochtman
|
r6393 | for lineno, ((f, targetline), l) in lines: | ||
fnode = f.filenode() | ||||
if last != fnode: | ||||
last = fnode | ||||
yield {"parity": parity.next(), | ||||
Alexander Solovyov
|
r14055 | "node": f.hex(), | ||
Dirkjan Ochtman
|
r6393 | "rev": f.rev(), | ||
Patrick Mezard
|
r6564 | "author": f.user(), | ||
Dirkjan Ochtman
|
r6657 | "desc": f.description(), | ||
Benoit Boissinot
|
r18581 | "extra": f.extra(), | ||
Dirkjan Ochtman
|
r6393 | "file": f.path(), | ||
"targetline": targetline, | ||||
"line": l, | ||||
"lineid": "l%d" % (lineno + 1), | ||||
Oli Thissen
|
r13199 | "linenumber": "% 6d" % (lineno + 1), | ||
"revdate": f.date()} | ||||
Dirkjan Ochtman
|
r6393 | |||
return tmpl("fileannotate", | ||||
file=f, | ||||
annotate=annotate, | ||||
path=webutil.up(f), | ||||
rev=fctx.rev(), | ||||
Alexander Solovyov
|
r14055 | node=fctx.hex(), | ||
Dirkjan Ochtman
|
r6393 | author=fctx.user(), | ||
date=fctx.date(), | ||||
desc=fctx.description(), | ||||
Benoit Boissinot
|
r18581 | extra=fctx.extra(), | ||
Matt Mackall
|
r6434 | rename=webutil.renamelink(fctx), | ||
Dirkjan Ochtman
|
r6393 | branch=webutil.nodebranchnodefault(fctx), | ||
Dirkjan Ochtman
|
r7671 | parent=webutil.parents(fctx), | ||
child=webutil.children(fctx), | ||||
Dirkjan Ochtman
|
r6393 | permissions=fctx.manifest().flags(f)) | ||
Dirkjan Ochtman
|
r5591 | |||
Dirkjan Ochtman
|
r5600 | def filelog(web, req, tmpl): | ||
Dirkjan Ochtman
|
r7300 | |||
try: | ||||
fctx = webutil.filectx(web.repo, req) | ||||
f = fctx.path() | ||||
fl = fctx.filelog() | ||||
Matt Mackall
|
r7633 | except error.LookupError: | ||
Dirkjan Ochtman
|
r7300 | 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() | ||||
Matt Mackall
|
r7361 | first = fl.linkrev(0) | ||
Dirkjan Ochtman
|
r7300 | if rev < first: # current rev is from before file existed | ||
raise | ||||
frev = numrevs - 1 | ||||
Matt Mackall
|
r7361 | while fl.linkrev(frev) > rev: | ||
Dirkjan Ochtman
|
r7300 | frev -= 1 | ||
Matt Mackall
|
r7361 | fctx = web.repo.filectx(f, fl.linkrev(frev)) | ||
Dirkjan Ochtman
|
r7300 | |||
Dirkjan Ochtman
|
r10246 | revcount = web.maxshortchanges | ||
if 'revcount' in req.form: | ||||
revcount = int(req.form.get('revcount', [revcount])[0]) | ||||
Md. O. Shayan
|
r13931 | revcount = max(revcount, 1) | ||
Dirkjan Ochtman
|
r10246 | tmpl.defaults['sessionvars']['revcount'] = revcount | ||
lessvars = copy.copy(tmpl.defaults['sessionvars']) | ||||
Md. O. Shayan
|
r13931 | lessvars['revcount'] = max(revcount / 2, 1) | ||
Dirkjan Ochtman
|
r10246 | morevars = copy.copy(tmpl.defaults['sessionvars']) | ||
morevars['revcount'] = revcount * 2 | ||||
Dirkjan Ochtman
|
r7300 | count = fctx.filerev() + 1 | ||
Dirkjan Ochtman
|
r10246 | start = max(0, fctx.filerev() - revcount + 1) # first rev on this page | ||
end = min(count, start + revcount) # last rev on this page | ||||
Matt Mackall
|
r10282 | parity = paritygen(web.stripecount, offset=start - end) | ||
Dirkjan Ochtman
|
r6393 | |||
Pierre-Yves David
|
r18402 | def entries(latestonly, **map): | ||
Dirkjan Ochtman
|
r6393 | l = [] | ||
Benoit Boissinot
|
r7612 | repo = web.repo | ||
Pierre-Yves David
|
r18427 | revs = repo.changelog.revs(start, end - 1) | ||
Pierre-Yves David
|
r18402 | if latestonly: | ||
Pierre-Yves David
|
r18427 | for r in revs: | ||
pass | ||||
revs = (r,) | ||||
Pierre-Yves David
|
r18402 | for i in revs: | ||
Benoit Boissinot
|
r7612 | iterfctx = fctx.filectx(i) | ||
Dirkjan Ochtman
|
r6393 | |||
Pierre-Yves David
|
r18319 | l.append({"parity": parity.next(), | ||
"filerev": i, | ||||
"file": f, | ||||
"node": iterfctx.hex(), | ||||
"author": iterfctx.user(), | ||||
"date": iterfctx.date(), | ||||
"rename": webutil.renamelink(iterfctx), | ||||
"parent": webutil.parents(iterfctx), | ||||
"child": webutil.children(iterfctx), | ||||
"desc": iterfctx.description(), | ||||
Benoit Boissinot
|
r18581 | "extra": iterfctx.extra(), | ||
Pierre-Yves David
|
r18319 | "tags": webutil.nodetagsdict(repo, iterfctx.node()), | ||
"bookmarks": webutil.nodebookmarksdict( | ||||
repo, iterfctx.node()), | ||||
"branch": webutil.nodebranchnodefault(iterfctx), | ||||
"inbranch": webutil.nodeinbranch(repo, iterfctx), | ||||
"branches": webutil.nodebranchdict(repo, iterfctx)}) | ||||
for e in reversed(l): | ||||
Dirkjan Ochtman
|
r6393 | yield e | ||
Pierre-Yves David
|
r18409 | revnav = webutil.filerevnav(web.repo, fctx.path()) | ||
nav = revnav.gen(end - 1, revcount, count) | ||||
Alexander Solovyov
|
r14055 | return tmpl("filelog", file=f, node=fctx.hex(), nav=nav, | ||
Pierre-Yves David
|
r18402 | entries=lambda **x: entries(latestonly=False, **x), | ||
latestentry=lambda **x: entries(latestonly=True, **x), | ||||
Dirkjan Ochtman
|
r10246 | revcount=revcount, morevars=morevars, lessvars=lessvars) | ||
Dirkjan Ochtman
|
r5591 | |||
Dirkjan Ochtman
|
r5600 | def archive(web, req, tmpl): | ||
Ali Saidi
|
r6669 | type_ = req.form.get('type', [None])[0] | ||
Dirkjan Ochtman
|
r5591 | allowed = web.configlist("web", "allow_archive") | ||
Dirkjan Ochtman
|
r6393 | key = req.form['node'][0] | ||
Rocco Rutte
|
r7029 | if type_ not in web.archives: | ||
Dirkjan Ochtman
|
r6393 | msg = 'Unsupported archive type: %s' % type_ | ||
raise ErrorResponse(HTTP_NOT_FOUND, msg) | ||||
Rocco Rutte
|
r7029 | if not ((type_ in allowed or | ||
web.configbool("web", "allow" + type_, False))): | ||||
msg = 'Archive type not allowed: %s' % type_ | ||||
raise ErrorResponse(HTTP_FORBIDDEN, msg) | ||||
Dirkjan Ochtman
|
r6393 | reponame = re.sub(r"\W+", "-", os.path.basename(web.reponame)) | ||
cnode = web.repo.lookup(key) | ||||
arch_version = key | ||||
if cnode == key or key == 'tip': | ||||
arch_version = short(cnode) | ||||
name = "%s-%s" % (reponame, arch_version) | ||||
Angel Ezquerra
|
r18771 | |||
ctx = webutil.changectx(web.repo, req) | ||||
pats = [] | ||||
file = req.form.get('file', None) | ||||
if file: | ||||
file = file[0] | ||||
patandfile = file.split(':') | ||||
if len(patandfile) > 1 and patandfile[0].lower() in ('glob', 'relglob', | ||||
'path', 'relpath', 're', 'relre', 'set'): | ||||
msg = 'Archive pattern not allowed: %s' % file | ||||
raise ErrorResponse(HTTP_FORBIDDEN, msg) | ||||
pats = ['path:' + file] | ||||
Dirkjan Ochtman
|
r6393 | mimetype, artype, extension, encoding = web.archive_specs[type_] | ||
headers = [ | ||||
('Content-Disposition', 'attachment; filename=%s%s' % (name, extension)) | ||||
Mads Kiilerich
|
r18347 | ] | ||
Dirkjan Ochtman
|
r6393 | if encoding: | ||
headers.append(('Content-Encoding', encoding)) | ||||
Mads Kiilerich
|
r18348 | req.headers.extend(headers) | ||
Mads Kiilerich
|
r18347 | req.respond(HTTP_OK, mimetype) | ||
Jordi Gutiérrez Hermoso
|
r17933 | |||
Angel Ezquerra
|
r18771 | matchfn = scmutil.match(ctx, pats, default='path') | ||
Jordi Gutiérrez Hermoso
|
r17933 | archival.archive(web.repo, req, cnode, artype, prefix=name, | ||
Angel Ezquerra
|
r18771 | matchfn=matchfn, | ||
Jordi Gutiérrez Hermoso
|
r17933 | subrepos=web.configbool("web", "archivesubrepos")) | ||
Dirkjan Ochtman
|
r6393 | return [] | ||
Dirkjan Ochtman
|
r5591 | |||
Dirkjan Ochtman
|
r5600 | def static(web, req, tmpl): | ||
Dirkjan Ochtman
|
r5591 | fname = req.form['file'][0] | ||
# a repo owner may set web.static in .hg/hgrc to get any file | ||||
# readable by the user running the CGI script | ||||
Brendan Cully
|
r7107 | static = web.config("web", "static", None, untrusted=False) | ||
if not static: | ||||
Dirkjan Ochtman
|
r7966 | tp = web.templatepath or templater.templatepath() | ||
Brendan Cully
|
r7107 | if isinstance(tp, str): | ||
tp = [tp] | ||||
Brendan Cully
|
r7288 | static = [os.path.join(p, 'static') for p in tp] | ||
Mads Kiilerich
|
r18645 | staticfile(static, fname, req) | ||
return [] | ||||
Dirkjan Ochtman
|
r6691 | |||
def graph(web, req, tmpl): | ||||
Dirkjan Ochtman
|
r10245 | |||
Patrick Mezard
|
r17318 | ctx = webutil.changectx(web.repo, req) | ||
rev = ctx.rev() | ||||
Dirkjan Ochtman
|
r6691 | bg_height = 39 | ||
Dirkjan Ochtman
|
r10245 | revcount = web.maxshortchanges | ||
Dirkjan Ochtman
|
r7345 | if 'revcount' in req.form: | ||
revcount = int(req.form.get('revcount', [revcount])[0]) | ||||
Md. O. Shayan
|
r13931 | revcount = max(revcount, 1) | ||
Dirkjan Ochtman
|
r7345 | tmpl.defaults['sessionvars']['revcount'] = revcount | ||
lessvars = copy.copy(tmpl.defaults['sessionvars']) | ||||
Md. O. Shayan
|
r13931 | lessvars['revcount'] = max(revcount / 2, 1) | ||
Dirkjan Ochtman
|
r7345 | morevars = copy.copy(tmpl.defaults['sessionvars']) | ||
morevars['revcount'] = revcount * 2 | ||||
Patrick Mezard
|
r17318 | count = len(web.repo) | ||
pos = rev | ||||
start = max(0, pos - revcount + 1) | ||||
end = min(count, start + revcount) | ||||
pos = end - 1 | ||||
uprev = min(max(0, count - 1), rev + revcount) | ||||
Dirkjan Ochtman
|
r6691 | downrev = max(0, rev - revcount) | ||
Pierre-Yves David
|
r18409 | changenav = webutil.revnav(web.repo).gen(pos, revcount, count) | ||
Dirkjan Ochtman
|
r6691 | |||
Pierre-Yves David
|
r18428 | tree = [] | ||
if start < end: | ||||
revs = list(web.repo.changelog.revs(end - 1, start)) | ||||
dag = graphmod.dagwalker(web.repo, revs) | ||||
tree = list(graphmod.colored(dag, web.repo)) | ||||
Paul Boddie
|
r16773 | |||
def getcolumns(tree): | ||||
cols = 0 | ||||
for (id, type, ctx, vtx, edges) in tree: | ||||
if type != graphmod.CHANGESET: | ||||
continue | ||||
cols = max(cols, max([edge[0] for edge in edges] or [0]), | ||||
max([edge[1] for edge in edges] or [0])) | ||||
return cols | ||||
def graphdata(usetuples, **map): | ||||
data = [] | ||||
row = 0 | ||||
for (id, type, ctx, vtx, edges) in tree: | ||||
if type != graphmod.CHANGESET: | ||||
continue | ||||
node = str(ctx) | ||||
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() | ||||
try: | ||||
branchnode = web.repo.branchtip(branch) | ||||
except error.RepoLookupError: | ||||
branchnode = None | ||||
branch = branch, branchnode == ctx.node() | ||||
if usetuples: | ||||
data.append((node, vtx, edges, desc, user, age, branch, | ||||
ctx.tags(), ctx.bookmarks())) | ||||
else: | ||||
edgedata = [dict(col=edge[0], nextcol=edge[1], | ||||
color=(edge[2] - 1) % 6 + 1, | ||||
width=edge[3], bcolor=edge[4]) | ||||
for edge in edges] | ||||
data.append( | ||||
dict(node=node, | ||||
col=vtx[0], | ||||
color=(vtx[1] - 1) % 6 + 1, | ||||
edges=edgedata, | ||||
row=row, | ||||
nextrow=row + 1, | ||||
desc=desc, | ||||
user=user, | ||||
age=age, | ||||
bookmarks=webutil.nodebookmarksdict( | ||||
web.repo, ctx.node()), | ||||
branches=webutil.nodebranchdict(web.repo, ctx), | ||||
inbranch=webutil.nodeinbranch(web.repo, ctx), | ||||
tags=webutil.nodetagsdict(web.repo, ctx.node()))) | ||||
row += 1 | ||||
return data | ||||
cols = getcolumns(tree) | ||||
rows = len(tree) | ||||
canvasheight = (rows + 1) * bg_height - 27 | ||||
Dirkjan Ochtman
|
r6691 | |||
return tmpl('graph', rev=rev, revcount=revcount, uprev=uprev, | ||||
Dirkjan Ochtman
|
r7345 | lessvars=lessvars, morevars=morevars, downrev=downrev, | ||
Paul Boddie
|
r16773 | cols=cols, rows=rows, | ||
canvaswidth=(cols + 1) * bg_height, | ||||
truecanvasheight=rows * bg_height, | ||||
canvasheight=canvasheight, bg_height=bg_height, | ||||
jsdata=lambda **x: graphdata(True, **x), | ||||
nodes=lambda **x: graphdata(False, **x), | ||||
Patrick Mezard
|
r17318 | node=ctx.hex(), changenav=changenav) | ||
Augie Fackler
|
r12666 | |||
def _getdoc(e): | ||||
doc = e[0].__doc__ | ||||
if doc: | ||||
FUJIWARA Katsunori
|
r16469 | doc = _(doc).split('\n')[0] | ||
Augie Fackler
|
r12666 | else: | ||
doc = _('(no help text available)') | ||||
return doc | ||||
def help(web, req, tmpl): | ||||
from mercurial import commands # avoid cycle | ||||
topicname = req.form.get('node', [None])[0] | ||||
if not topicname: | ||||
def topics(**map): | ||||
for entries, summary, _ in helpmod.helptable: | ||||
Mads Kiilerich
|
r17322 | yield {'topic': entries[0], 'summary': summary} | ||
Augie Fackler
|
r12666 | |||
early, other = [], [] | ||||
primary = lambda s: s.split('|')[0] | ||||
for c, e in commands.table.iteritems(): | ||||
doc = _getdoc(e) | ||||
if 'DEPRECATED' in doc or c.startswith('debug'): | ||||
continue | ||||
cmd = primary(c) | ||||
if cmd.startswith('^'): | ||||
early.append((cmd[1:], doc)) | ||||
else: | ||||
other.append((cmd, doc)) | ||||
early.sort() | ||||
other.sort() | ||||
def earlycommands(**map): | ||||
for c, doc in early: | ||||
yield {'topic': c, 'summary': doc} | ||||
def othercommands(**map): | ||||
for c, doc in other: | ||||
yield {'topic': c, 'summary': doc} | ||||
return tmpl('helptopics', topics=topics, earlycommands=earlycommands, | ||||
othercommands=othercommands, title='Index') | ||||
Matt Mackall
|
r12696 | u = webutil.wsgiui() | ||
Adrian Buehlmann
|
r17146 | u.verbose = True | ||
Augie Fackler
|
r12666 | try: | ||
Dan Villiom Podlaski Christiansen
|
r18747 | doc = helpmod.help_(u, topicname) | ||
Augie Fackler
|
r12666 | except error.UnknownCommand: | ||
raise ErrorResponse(HTTP_NOT_FOUND) | ||||
return tmpl('help', topic=topicname, doc=doc) | ||||