##// END OF EJS Templates
hgweb: add a test for search logs
hgweb: add a test for search logs

File last commit:

r10247:e8c74103 default
r10248:4441e8d7 default
Show More
webcommands.py
727 lines | 24.7 KiB | text/x-python | PythonLexer
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591 #
# Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
# Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
#
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
# GNU General Public License version 2, incorporated herein by reference.
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Dirkjan Ochtman
hgweb: fix up the less/more links on the graph page...
r7345 import os, mimetypes, re, cgi, copy
Dirkjan Ochtman
hgweb: separate out utility functions
r6392 import webutil
Dirkjan Ochtman
templater: move stylemap function from hgweb to templater
r7966 from mercurial import error, archival, templater, templatefilters
Peter Arrenbrecht
cleanup: drop unused imports
r7873 from mercurial.node import short, hex
from mercurial.util import binary
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 from common import paritygen, staticfile, get_contact, ErrorResponse
Rocco Rutte
hgweb: Respond with HTTP 403 for disabled archive types instead of 404...
r7029 from common import HTTP_OK, HTTP_FORBIDDEN, HTTP_NOT_FOUND
Peter Arrenbrecht
drop unused imports
r8390 from mercurial import graphmod
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Dirkjan Ochtman
hgweb: explicitly check if requested command exists
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',
Sune Foldager
webcommands: add 'branches' command, similar to 'tags'
r8352 'manifest', 'tags', 'branches', 'summary', 'filediff', 'diff', 'annotate',
'filelog', 'archive', 'static', 'graph',
Dirkjan Ochtman
hgweb: explicitly check if requested command exists
r5963 ]
Dirkjan Ochtman
hgweb: explicitly pass around the templater
r5600 def log(web, req, tmpl):
Christian Ebert
Prefer i in d over d.has_key(i)
r5915 if 'file' in req.form and req.form['file'][0]:
Dirkjan Ochtman
hgweb: centralize req.write() calls
r5964 return filelog(web, req, tmpl)
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591 else:
Dirkjan Ochtman
hgweb: centralize req.write() calls
r5964 return changelog(web, req, tmpl)
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Dirkjan Ochtman
hgweb: fast path for sending raw files
r5890 def rawfile(web, req, tmpl):
Dirkjan Ochtman
hgweb: separate out utility functions
r6392 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
Dirkjan Ochtman
hgweb: fast path for sending raw files
r5890 if not path:
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 content = manifest(web, req, tmpl)
Dirkjan Ochtman
hgweb: explicit response status
r5993 req.respond(HTTP_OK, web.ctype)
return content
Dirkjan Ochtman
hgweb: fast path for sending raw files
r5890
try:
Dirkjan Ochtman
hgweb: separate out utility functions
r6392 fctx = webutil.filectx(web.repo, req)
Matt Mackall
errors: move revlog errors...
r7633 except error.LookupError, inst:
Dirkjan Ochtman
hgweb: better error messages
r6368 try:
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 content = manifest(web, req, tmpl)
Dirkjan Ochtman
hgweb: better error messages
r6368 req.respond(HTTP_OK, web.ctype)
return content
except ErrorResponse:
raise inst
Dirkjan Ochtman
hgweb: fast path for sending raw files
r5890
path = fctx.path()
text = fctx.data()
mt = mimetypes.guess_type(path)[0]
Rocco Rutte
hgweb: Serve raw non-binary files as text/plain...
r6981 if mt is None:
mt = binary(text) and 'application/octet-stream' or 'text/plain'
Dirkjan Ochtman
hgweb: fast path for sending raw files
r5890
Dirkjan Ochtman
hgweb: explicit response status
r5993 req.respond(HTTP_OK, mt, path, len(text))
Dirkjan Ochtman
hgweb: centralize req.write() calls
r5964 return [text]
Dirkjan Ochtman
hgweb: fast path for sending raw files
r5890
Dirkjan Ochtman
hgweb: refactor hgweb code
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
for calls expecting bool args, pass bool instead of int...
r9136 for lineno, t in enumerate(text.splitlines(True)):
Dirkjan Ochtman
hgweb: refactor hgweb code
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(),
node=hex(fctx.node()),
author=fctx.user(),
date=fctx.date(),
desc=fctx.description(),
branch=webutil.nodebranchnodefault(fctx),
Dirkjan Ochtman
hgweb: simplify parents/children generation code
r7671 parent=webutil.parents(fctx),
child=webutil.children(fctx),
Matt Mackall
hgweb: minor improvements for new web style...
r6434 rename=webutil.renamelink(fctx),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 permissions=fctx.manifest().flags(f))
Dirkjan Ochtman
hgweb: explicitly pass around the templater
r5600 def file(web, req, tmpl):
Dirkjan Ochtman
hgweb: separate out utility functions
r6392 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
Benoit Boissinot
hgweb: do not use unassigned variables in exception handling
r6853 if not path:
Patrick Mezard
Merge with crew-stable
r6857 return manifest(web, req, tmpl)
Benoit Boissinot
hgweb: do not use unassigned variables in exception handling
r6853 try:
Patrick Mezard
Merge with crew-stable
r6857 return _filerevision(web, tmpl, webutil.filectx(web.repo, req))
Matt Mackall
errors: move revlog errors...
r7633 except error.LookupError, inst:
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591 try:
Patrick Mezard
Merge with crew-stable
r6857 return manifest(web, req, tmpl)
Benoit Boissinot
hgweb: do not use unassigned variables in exception handling
r6853 except ErrorResponse:
raise inst
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Dirkjan Ochtman
hgweb: add less/more links for search logs (issue1972)
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])
tmpl.defaults['sessionvars']['revcount'] = revcount
lessvars = copy.copy(tmpl.defaults['sessionvars'])
lessvars['revcount'] = revcount / 2
lessvars['rev'] = query
morevars = copy.copy(tmpl.defaults['sessionvars'])
morevars['revcount'] = revcount * 2
morevars['rev'] = query
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
def changelist(**map):
cl = web.repo.changelog
count = 0
qw = query.lower().split()
def revgen():
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 for i in xrange(len(cl) - 1, 0, -100):
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 l = []
for j in xrange(max(0, i - 100), i + 1):
Matt Mackall
use repo[changeid] to get a changectx
r6747 ctx = web.repo[j]
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 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
Andrew Beekhof
webcommands: fix increments lost by 894875eae49b
r6659 count += 1
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 n = ctx.node()
showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n)
Dirkjan Ochtman
hgweb: move another utility function into the webutil module
r7311 files = webutil.listfilediffs(tmpl, ctx.files(), n, web.maxfiles)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
yield tmpl('searchentry',
parity=parity.next(),
author=ctx.user(),
Dirkjan Ochtman
hgweb: simplify parents/children generation code
r7671 parent=webutil.parents(ctx),
child=webutil.children(ctx),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 changelogtag=showtags,
desc=ctx.description(),
date=ctx.date(),
Dirkjan Ochtman
hgweb: move another utility function into the webutil module
r7311 files=files,
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 rev=ctx.rev(),
node=hex(n),
tags=webutil.nodetagsdict(web.repo, n),
inbranch=webutil.nodeinbranch(web.repo, ctx),
branches=webutil.nodebranchdict(web.repo, ctx))
Dirkjan Ochtman
hgweb: add less/more links for search logs (issue1972)
r10247 if count >= revcount:
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 break
cl = web.repo.changelog
parity = paritygen(web.stripecount)
Dirkjan Ochtman
hgweb: add less/more links for search logs (issue1972)
r10247 return tmpl('search', query=query, node=hex(cl.tip()),
entries=changelist, archives=web.archivelist("tip"),
morevars=morevars, lessvars=lessvars)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Dirkjan Ochtman
hgweb: add less/more links for search logs (issue1972)
r10247 def changelog(web, req, tmpl, shortlog=False):
Christian Ebert
Prefer i in d over d.has_key(i)
r5915 if 'node' in req.form:
Dirkjan Ochtman
hgweb: separate out utility functions
r6392 ctx = webutil.changectx(web.repo, req)
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591 else:
Christian Ebert
Prefer i in d over d.has_key(i)
r5915 if 'rev' in req.form:
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591 hi = req.form['rev'][0]
else:
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 hi = len(web.repo) - 1
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591 try:
Matt Mackall
use repo[changeid] to get a changectx
r6747 ctx = web.repo[hi]
Matt Mackall
error: move repo errors...
r7637 except error.RepoError:
Dirkjan Ochtman
hgweb: add less/more links for search logs (issue1972)
r10247 return _search(web, req, tmpl) # XXX redirect to 404 page?
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
def changelist(limit=0, **map):
l = [] # build a list in forward order for efficiency
for i in xrange(start, end):
Matt Mackall
use repo[changeid] to get a changectx
r6747 ctx = web.repo[i]
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 n = ctx.node()
showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n)
Dirkjan Ochtman
hgweb: move another utility function into the webutil module
r7311 files = webutil.listfilediffs(tmpl, ctx.files(), n, web.maxfiles)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
l.insert(0, {"parity": parity.next(),
"author": ctx.user(),
Dirkjan Ochtman
hgweb: simplify parents/children generation code
r7671 "parent": webutil.parents(ctx, i - 1),
"child": webutil.children(ctx, i + 1),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 "changelogtag": showtags,
"desc": ctx.description(),
"date": ctx.date(),
Dirkjan Ochtman
hgweb: move another utility function into the webutil module
r7311 "files": files,
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 "rev": i,
"node": hex(n),
"tags": webutil.nodetagsdict(web.repo, n),
"inbranch": webutil.nodeinbranch(web.repo, ctx),
"branches": webutil.nodebranchdict(web.repo, ctx)
})
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 if limit > 0:
l = l[:limit]
for e in l:
yield e
Dirkjan Ochtman
hgweb: add less/more links to shortlog/filelog nav
r10246 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
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 cl = web.repo.changelog
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 count = len(cl)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 pos = ctx.rev()
Dirkjan Ochtman
hgweb: add less/more links to shortlog/filelog nav
r10246 start = max(0, pos - revcount + 1)
end = min(count, start + revcount)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 pos = end - 1
parity = paritygen(web.stripecount, offset=start-end)
Dirkjan Ochtman
hgweb: add less/more links to shortlog/filelog nav
r10246 changenav = webutil.revnavgen(pos, revcount, count, web.repo.changectx)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Dirkjan Ochtman
hgweb: add less/more links to shortlog/filelog nav
r10246 return tmpl(shortlog and 'shortlog' or 'changelog', changenav=changenav,
node=hex(ctx.node()), rev=pos, changesets=count,
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 entries=lambda **x: changelist(limit=0,**x),
latestentry=lambda **x: changelist(limit=1,**x),
Dirkjan Ochtman
hgweb: add less/more links to shortlog/filelog nav
r10246 archives=web.archivelist("tip"), revcount=revcount,
morevars=morevars, lessvars=lessvars)
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Dirkjan Ochtman
hgweb: explicitly pass around the templater
r5600 def shortlog(web, req, tmpl):
Dirkjan Ochtman
hgweb: centralize req.write() calls
r5964 return changelog(web, req, tmpl, shortlog = True)
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Dirkjan Ochtman
hgweb: explicitly pass around the templater
r5600 def changeset(web, req, tmpl):
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 ctx = webutil.changectx(web.repo, req)
Dirkjan Ochtman
hgweb: move the diffs() generator into webutil
r7310 showtags = webutil.showtag(web.repo, tmpl, 'changesettag', ctx.node())
Dirkjan Ochtman
coal/paper: show branch name in changeset view
r7410 showbranch = webutil.nodebranchnodefault(ctx)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
files = []
parity = paritygen(web.stripecount)
for f in ctx.files():
Dirkjan Ochtman
hgweb: remove links to non-existent file versions
r7182 template = f in ctx and 'filenodelink' or 'filenolink'
files.append(tmpl(template,
Dirkjan Ochtman
hgweb: move the diffs() generator into webutil
r7310 node=ctx.hex(), file=f,
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 parity=parity.next()))
Dirkjan Ochtman
hgweb: move the diffs() generator into webutil
r7310 parity = paritygen(web.stripecount)
Dirkjan Ochtman
hgweb: show diff header line in raw diffs
r9402 style = web.config('web', 'style', 'paper')
if 'style' in req.form:
style = req.form['style'][0]
diffs = webutil.diffs(web.repo, tmpl, ctx, None, parity, style)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 return tmpl('changeset',
diff=diffs,
rev=ctx.rev(),
Dirkjan Ochtman
hgweb: move the diffs() generator into webutil
r7310 node=ctx.hex(),
Dirkjan Ochtman
hgweb: simplify parents/children generation code
r7671 parent=webutil.parents(ctx),
child=webutil.children(ctx),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 changesettag=showtags,
Dirkjan Ochtman
coal/paper: show branch name in changeset view
r7410 changesetbranch=showbranch,
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 author=ctx.user(),
desc=ctx.description(),
date=ctx.date(),
files=files,
Dirkjan Ochtman
hgweb: move the diffs() generator into webutil
r7310 archives=web.archivelist(ctx.hex()),
tags=webutil.nodetagsdict(web.repo, ctx.node()),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 branch=webutil.nodebranchnodefault(ctx),
inbranch=webutil.nodeinbranch(web.repo, ctx),
branches=webutil.nodebranchdict(web.repo, ctx))
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
rev = changeset
Dirkjan Ochtman
hgweb: explicitly pass around the templater
r5600 def manifest(web, req, tmpl):
Dirkjan Ochtman
hgweb: refactor hgweb code
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
hgweb: descend empty directories in web view...
r7305 dirs = {}
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 parity = paritygen(web.stripecount)
if path and path[-1] != "/":
path += "/"
l = len(path)
abspath = "/" + path
Dirkjan Ochtman
use dict.iteritems() rather than dict.items()...
r7622 for f, n in mf.iteritems():
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 if f[:l] != path:
continue
remain = f[l:]
Ry4an Brase
hgweb: descend empty directories in web view...
r7305 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
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Dirkjan Ochtman
hgweb: fix problems with empty repositories
r7565 if mf and not files and not dirs:
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 raise ErrorResponse(HTTP_NOT_FOUND, 'path not found: ' + path)
def filelist(**map):
Matt Mackall
replace util.sort with sorted built-in...
r8209 for f in sorted(files):
Ry4an Brase
hgweb: descend empty directories in web view...
r7305 full = files[f]
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
fctx = ctx.filectx(full)
yield {"file": full,
"parity": parity.next(),
"basename": f,
Matt Mackall
use repo[changeid] to get a changectx
r6747 "date": fctx.date(),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 "size": fctx.size(),
"permissions": mf.flags(full)}
def dirlist(**map):
Matt Mackall
replace util.sort with sorted built-in...
r8209 for d in sorted(dirs):
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Ry4an Brase
hgweb: descend empty directories in web view...
r7305 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)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 yield {"parity": parity.next(),
Ry4an Brase
hgweb: descend empty directories in web view...
r7305 "path": path,
"emptydirs": "/".join(emptydirs),
"basename": d}
Dirkjan Ochtman
hgweb: refactor hgweb code
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),
inbranch=webutil.nodeinbranch(web.repo, ctx),
branches=webutil.nodebranchdict(web.repo, ctx))
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Dirkjan Ochtman
hgweb: explicitly pass around the templater
r5600 def tags(web, req, tmpl):
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 i = web.repo.tagslist()
i.reverse()
parity = paritygen(web.stripecount)
Martin Geisler
coding style: use a space after comma...
r9198 def entries(notip=False, limit=0, **map):
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 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,
Matt Mackall
use repo[changeid] to get a changectx
r6747 "date": web.repo[n].date(),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 "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))
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Sune Foldager
webcommands: add 'branches' command, similar to 'tags'
r8352 def branches(web, req, tmpl):
b = web.repo.branchtags()
Dirkjan Ochtman
hgweb: use context api in branches webcommand
r8354 tips = (web.repo[n] for t, n in web.repo.branchtags().iteritems())
John Mulligan
localrepo: remove 'closed' argument to heads(...) function...
r8796 heads = web.repo.heads()
Sune Foldager
webcommands: add 'branches' command, similar to 'tags'
r8352 parity = paritygen(web.stripecount)
Dirkjan Ochtman
hgweb: allow distinction between open/closed branches on branches page
r8713 sortkey = lambda ctx: ('close' not in ctx.extra(), ctx.rev())
Sune Foldager
webcommands: add 'branches' command, similar to 'tags'
r8352
def entries(limit, **map):
count = 0
Dirkjan Ochtman
hgweb: allow distinction between open/closed branches on branches page
r8713 for ctx in sorted(tips, key=sortkey, reverse=True):
Sune Foldager
webcommands: add 'branches' command, similar to 'tags'
r8352 if limit > 0 and count >= limit:
return
count += 1
John Mulligan
localrepo: remove 'closed' argument to heads(...) function...
r8796 if ctx.node() not in heads:
status = 'inactive'
elif not web.repo.branchheads(ctx.branch()):
status = 'closed'
else:
status = 'open'
Sune Foldager
webcommands: add 'branches' command, similar to 'tags'
r8352 yield {'parity': parity.next(),
Dirkjan Ochtman
hgweb: use context api in branches webcommand
r8354 'branch': ctx.branch(),
Dirkjan Ochtman
hgweb: allow distinction between open/closed branches on branches page
r8713 'status': status,
Dirkjan Ochtman
hgweb: use context api in branches webcommand
r8354 'node': ctx.hex(),
'date': ctx.date()}
Sune Foldager
webcommands: add 'branches' command, similar to 'tags'
r8352
return tmpl('branches', node=hex(web.repo.changelog.tip()),
entries=lambda **x: entries(0, **x),
latestentry=lambda **x: entries(1, **x))
Dirkjan Ochtman
hgweb: explicitly pass around the templater
r5600 def summary(web, req, tmpl):
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 i = web.repo.tagslist()
i.reverse()
def tagentries(**map):
parity = paritygen(web.stripecount)
count = 0
for k, n in i:
if k == "tip": # skip tip
continue
Andrew Beekhof
webcommands: fix increments lost by 894875eae49b
r6659 count += 1
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 if count > 10: # limit to 10 tags
break
yield tmpl("tagentry",
parity=parity.next(),
tag=k,
node=hex(n),
Matt Mackall
use repo[changeid] to get a changectx
r6747 date=web.repo[n].date())
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
def branches(**map):
parity = paritygen(web.stripecount)
b = web.repo.branchtags()
Dirkjan Ochtman
use dict.iteritems() rather than dict.items()...
r7622 l = [(-web.repo.changelog.rev(n), n, t) for t, n in b.iteritems()]
Matt Mackall
replace util.sort with sorted built-in...
r8209 for r,n,t in sorted(l):
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 yield {'parity': parity.next(),
'branch': t,
'node': hex(n),
Matt Mackall
use repo[changeid] to get a changectx
r6747 'date': web.repo[n].date()}
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
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):
Matt Mackall
use repo[changeid] to get a changectx
r6747 ctx = web.repo[i]
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 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
cl = web.repo.changelog
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 count = len(cl)
Dirkjan Ochtman
hgweb: refactor hgweb code
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",
lastchange=cl.read(cl.tip())[2],
tags=tagentries,
branches=branches,
shortlog=changelist,
node=hex(cl.tip()),
archives=web.archivelist("tip"))
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Dirkjan Ochtman
hgweb: explicitly pass around the templater
r5600 def filediff(web, req, tmpl):
Dirkjan Ochtman
hgweb: working diff for removed files
r7183 fctx, ctx = None, None
try:
fctx = webutil.filectx(web.repo, req)
Benoit Boissinot
remove unused variables
r7280 except LookupError:
Dirkjan Ochtman
hgweb: working diff for removed files
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()
else:
n = ctx.node()
# path already defined in except clause
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Dirkjan Ochtman
hgweb: move the diffs() generator into webutil
r7310 parity = paritygen(web.stripecount)
Dirkjan Ochtman
hgweb: show diff header line in raw diffs
r9402 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)
Dirkjan Ochtman
hgweb: working diff for removed files
r7183 rename = fctx and webutil.renamelink(fctx) or []
ctx = fctx and fctx or ctx
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 return tmpl("filediff",
file=path,
node=hex(n),
Dirkjan Ochtman
hgweb: working diff for removed files
r7183 rev=ctx.rev(),
date=ctx.date(),
desc=ctx.description(),
author=ctx.user(),
rename=rename,
branch=webutil.nodebranchnodefault(ctx),
Dirkjan Ochtman
hgweb: simplify parents/children generation code
r7671 parent=webutil.parents(ctx),
child=webutil.children(ctx),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 diff=diffs)
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
diff = filediff
Dirkjan Ochtman
hgweb: explicitly pass around the templater
r5600 def annotate(web, req, tmpl):
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 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(),
Patrick Mezard
webcommands: pass full author to annotate, fix templates (issue 1054)
r6564 "author": f.user(),
Dirkjan Ochtman
hgweb: show cset node and description when hovering over annotate prefix
r6657 "desc": f.description(),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 "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(),
Matt Mackall
hgweb: minor improvements for new web style...
r6434 rename=webutil.renamelink(fctx),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 branch=webutil.nodebranchnodefault(fctx),
Dirkjan Ochtman
hgweb: simplify parents/children generation code
r7671 parent=webutil.parents(fctx),
child=webutil.children(fctx),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 permissions=fctx.manifest().flags(f))
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Dirkjan Ochtman
hgweb: explicitly pass around the templater
r5600 def filelog(web, req, tmpl):
Dirkjan Ochtman
hgweb: conditionally show file logs for deleted files
r7300
try:
fctx = webutil.filectx(web.repo, req)
f = fctx.path()
fl = fctx.filelog()
Matt Mackall
errors: move revlog errors...
r7633 except error.LookupError:
Dirkjan Ochtman
hgweb: conditionally show file logs for deleted files
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
linkrev: take a revision number rather than a hash
r7361 first = fl.linkrev(0)
Dirkjan Ochtman
hgweb: conditionally show file logs for deleted files
r7300 if rev < first: # current rev is from before file existed
raise
frev = numrevs - 1
Matt Mackall
linkrev: take a revision number rather than a hash
r7361 while fl.linkrev(frev) > rev:
Dirkjan Ochtman
hgweb: conditionally show file logs for deleted files
r7300 frev -= 1
Matt Mackall
linkrev: take a revision number rather than a hash
r7361 fctx = web.repo.filectx(f, fl.linkrev(frev))
Dirkjan Ochtman
hgweb: conditionally show file logs for deleted files
r7300
Dirkjan Ochtman
hgweb: add less/more links to shortlog/filelog nav
r10246 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
Dirkjan Ochtman
hgweb: conditionally show file logs for deleted files
r7300 count = fctx.filerev() + 1
Dirkjan Ochtman
hgweb: add less/more links to shortlog/filelog nav
r10246 start = max(0, fctx.filerev() - revcount + 1) # first rev on this page
end = min(count, start + revcount) # last rev on this page
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 parity = paritygen(web.stripecount, offset=start-end)
def entries(limit=0, **map):
l = []
Benoit Boissinot
web: use the correct filectx in filelog
r7612 repo = web.repo
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 for i in xrange(start, end):
Benoit Boissinot
web: use the correct filectx in filelog
r7612 iterfctx = fctx.filectx(i)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
l.insert(0, {"parity": parity.next(),
"filerev": i,
"file": f,
Benoit Boissinot
web: use the correct filectx in filelog
r7612 "node": hex(iterfctx.node()),
"author": iterfctx.user(),
"date": iterfctx.date(),
"rename": webutil.renamelink(iterfctx),
Dirkjan Ochtman
hgweb: simplify parents/children generation code
r7671 "parent": webutil.parents(iterfctx),
"child": webutil.children(iterfctx),
Benoit Boissinot
web: use the correct filectx in filelog
r7612 "desc": iterfctx.description(),
"tags": webutil.nodetagsdict(repo, iterfctx.node()),
"branch": webutil.nodebranchnodefault(iterfctx),
"inbranch": webutil.nodeinbranch(repo, iterfctx),
"branches": webutil.nodebranchdict(repo, iterfctx)})
Dirkjan Ochtman
kill some trailing spaces
r7434
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 if limit > 0:
l = l[:limit]
for e in l:
yield e
nodefunc = lambda x: fctx.filectx(fileid=x)
Dirkjan Ochtman
hgweb: add less/more links to shortlog/filelog nav
r10246 nav = webutil.revnavgen(end - 1, revcount, count, nodefunc)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 return tmpl("filelog", file=f, node=hex(fctx.node()), nav=nav,
entries=lambda **x: entries(limit=0, **x),
Dirkjan Ochtman
hgweb: add less/more links to shortlog/filelog nav
r10246 latestentry=lambda **x: entries(limit=1, **x),
revcount=revcount, morevars=morevars, lessvars=lessvars)
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Dirkjan Ochtman
hgweb: explicitly pass around the templater
r5600 def archive(web, req, tmpl):
Ali Saidi
fix traceback in hgweb when URL doesn't end in one of the archive specs...
r6669 type_ = req.form.get('type', [None])[0]
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591 allowed = web.configlist("web", "allow_archive")
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 key = req.form['node'][0]
Rocco Rutte
hgweb: Respond with HTTP 403 for disabled archive types instead of 404...
r7029 if type_ not in web.archives:
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 msg = 'Unsupported archive type: %s' % type_
raise ErrorResponse(HTTP_NOT_FOUND, msg)
Rocco Rutte
hgweb: Respond with HTTP 403 for disabled archive types instead of 404...
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
hgweb: refactor hgweb code
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)
mimetype, artype, extension, encoding = web.archive_specs[type_]
headers = [
('Content-Type', mimetype),
('Content-Disposition', 'attachment; filename=%s%s' % (name, extension))
]
if encoding:
headers.append(('Content-Encoding', encoding))
req.header(headers)
req.respond(HTTP_OK)
archival.archive(web.repo, req, cnode, artype, prefix=name)
return []
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Dirkjan Ochtman
hgweb: explicitly pass around the templater
r5600 def static(web, req, tmpl):
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
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
Allow hgweb to search for templates in more than one path....
r7107 static = web.config("web", "static", None, untrusted=False)
if not static:
Dirkjan Ochtman
templater: move stylemap function from hgweb to templater
r7966 tp = web.templatepath or templater.templatepath()
Brendan Cully
Allow hgweb to search for templates in more than one path....
r7107 if isinstance(tp, str):
tp = [tp]
Brendan Cully
Allow per-file shadowing of static directory in templatepath
r7288 static = [os.path.join(p, 'static') for p in tp]
Dirkjan Ochtman
hgweb: centralize req.write() calls
r5964 return [staticfile(static, fname, req)]
Dirkjan Ochtman
add graph page to hgweb
r6691
def graph(web, req, tmpl):
Dirkjan Ochtman
hgweb: make graph page size equal to shortlog
r10245
Dirkjan Ochtman
add graph page to hgweb
r6691 rev = webutil.changectx(web.repo, req).rev()
bg_height = 39
Dirkjan Ochtman
hgweb: make graph page size equal to shortlog
r10245 revcount = web.maxshortchanges
Dirkjan Ochtman
hgweb: fix up the less/more links on the graph page...
r7345 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
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 max_rev = len(web.repo) - 1
Dirkjan Ochtman
hgweb: fix up the less/more links on the graph page...
r7345 revcount = min(max_rev, revcount)
Dirkjan Ochtman
add graph page to hgweb
r6691 revnode = web.repo.changelog.node(rev)
revnode_hex = hex(revnode)
uprev = min(max_rev, rev + revcount)
downrev = max(0, rev - revcount)
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 count = len(web.repo)
Dirkjan Ochtman
hgweb: fix pagination for graph
r7332 changenav = webutil.revnavgen(rev, revcount, count, web.repo.changectx)
Dirkjan Ochtman
add graph page to hgweb
r6691
Peter Arrenbrecht
graphmod/webcommands: use generic DAG walks...
r8842 dag = graphmod.revisions(web.repo, rev, downrev)
tree = list(graphmod.colored(dag))
Dirkjan Ochtman
add graph page to hgweb
r6691 canvasheight = (len(tree) + 1) * bg_height - 27;
data = []
Peter Arrenbrecht
graphmod/webcommands: use generic DAG walks...
r8842 for (id, type, ctx, vtx, edges) in tree:
if type != graphmod.CHANGESET:
continue
Dirkjan Ochtman
add graph page to hgweb
r6691 node = short(ctx.node())
age = templatefilters.age(ctx.date())
desc = templatefilters.firstline(ctx.description())
Martin Geisler
webcommands: move nonempty logic from JavaScript to Python...
r8236 desc = cgi.escape(templatefilters.nonempty(desc))
Dirkjan Ochtman
add graph page to hgweb
r6691 user = cgi.escape(templatefilters.person(ctx.user()))
Dirkjan Ochtman
graph: display branch name alongside tags
r6720 branch = ctx.branch()
branch = branch, web.repo.branchtags().get(branch) == ctx.node()
data.append((node, vtx, edges, desc, user, age, branch, ctx.tags()))
Dirkjan Ochtman
add graph page to hgweb
r6691
return tmpl('graph', rev=rev, revcount=revcount, uprev=uprev,
Dirkjan Ochtman
hgweb: fix up the less/more links on the graph page...
r7345 lessvars=lessvars, morevars=morevars, downrev=downrev,
canvasheight=canvasheight, jsdata=data, bg_height=bg_height,
node=revnode_hex, changenav=changenav)