##// END OF EJS Templates
caches: invalidate store caches when lock is taken...
caches: invalidate store caches when lock is taken The fncache was not being properly invalidated each time the lock was taken, so in theory it could contain old data from prior to the caller having the lock. This changes it to be invalidated as soon as the lock is taken (same as all our other caches).

File last commit:

r20761:46f93b76 default
r20884:2efdd186 default
Show More
webcommands.py
1113 lines | 37.5 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
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
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
Julian Cowley
hgweb: specify a charset when sending raw text files...
r11332 from mercurial import error, encoding, archival, templater, templatefilters
wujek srujek
hgweb: fixes traceback for invalid files by removing top-level template...
r17302 from mercurial.node import short, hex, nullid
Alexander Plavin
hgweb: import the whole util module in webcommands instead of just one function...
r19657 from mercurial import util
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
Patrick Mezard
annotate: support diff whitespace filtering flags (issue3030)...
r15528 from mercurial import graphmod, patch
Augie Fackler
web: add a help view for getting hg help output
r12666 from mercurial import help as helpmod
Jordi Gutiérrez Hermoso
webcommands: allow hgweb's archive to recurse into subrepos...
r17933 from mercurial import scmutil
Augie Fackler
web: add a help view for getting hg help output
r12666 from mercurial.i18n import _
Alexander Plavin
hgweb: add revset syntax support to search...
r19722 from mercurial.error import ParseError, RepoLookupError, Abort
from mercurial import revset
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',
Alexander Solovyov
hgweb: add separate page with bookmarks listing
r13597 'manifest', 'tags', 'bookmarks', 'branches', 'summary', 'filediff', 'diff',
wujek srujek
hgweb: side-by-side comparison functionality...
r17202 'comparison', 'annotate', 'filelog', 'archive', 'static', 'graph', 'help',
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):
Matt Mackall
hgweb: raw file mimetype guessing configurable, off by default (BC) (issue2923)...
r15004 guessmime = web.configbool('web', 'guessmime', False)
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()
Matt Mackall
hgweb: raw file mimetype guessing configurable, off by default (BC) (issue2923)...
r15004 mt = 'application/binary'
if guessmime:
mt = mimetypes.guess_type(path)[0]
if mt is None:
Alexander Plavin
hgweb: import the whole util module in webcommands instead of just one function...
r19657 mt = util.binary(text) and 'application/binary' or 'text/plain'
Julian Cowley
hgweb: specify a charset when sending raw text files...
r11332 if mt.startswith('text/'):
mt += '; charset="%s"' % encoding.encoding
Dirkjan Ochtman
hgweb: fast path for sending raw files
r5890
Mads Kiilerich
hgweb: pass the actual response body to request.response, not just the length...
r18352 req.respond(HTTP_OK, mt, path, body=text)
return []
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)
Alexander Plavin
hgweb: import the whole util module in webcommands instead of just one function...
r19657 if util.binary(text):
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 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(),
Alexander Solovyov
drop {short,hex}(ctx.node()) calls in favor of ctx methods
r14055 node=fctx.hex(),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 author=fctx.user(),
date=fctx.date(),
desc=fctx.description(),
Benoit Boissinot
templates: export extra as a dict to templates...
r18581 extra=fctx.extra(),
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),
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):
Alexander Plavin
hgweb: add string constants for search mode names...
r19656 MODE_REVISION = 'rev'
MODE_KEYWORD = 'keyword'
Alexander Plavin
hgweb: add revset syntax support to search...
r19722 MODE_REVSET = 'revset'
Dirkjan Ochtman
hgweb: add less/more links for search logs (issue1972)
r10247
Alexander Plavin
hgweb: search() function supports direct pointing to revision...
r19633 def revsearch(ctx):
yield ctx
Alexander Plavin
hgweb: pass arguments which a function depends on explicitly in search...
r19632 def keywordsearch(query):
FUJIWARA Katsunori
i18n: use "encoding.lower()" to normalize string in hgweb search query...
r15727 lower = encoding.lower
qw = lower(query).split()
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
def revgen():
Pierre-Yves David
hgweb: prevent traceback during search when filtered (issue3783)...
r18497 cl = web.repo.changelog
Patrick Mezard
webcommands: remove unncessary access to repo.changelog...
r12059 for i in xrange(len(web.repo) - 1, 0, -100):
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 l = []
Alexander Plavin
hgweb: fix duplication for some search queries...
r19491 for j in cl.revs(max(0, i - 99), i):
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:
FUJIWARA Katsunori
i18n: use "encoding.lower()" to normalize string in hgweb search query...
r15727 if not (q in lower(ctx.user()) or
q in lower(ctx.description()) or
q in lower(" ".join(ctx.files()))):
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 miss = 1
break
if miss:
continue
Alexander Plavin
hgweb: separate search itself and template generation...
r19533 yield ctx
Alexander Plavin
hgweb: add revset syntax support to search...
r19722 def revsetsearch(revs):
for r in revs:
yield web.repo[r]
Alexander Plavin
hgweb: add dynamic search function selection, depending on the query...
r19631 searchfuncs = {
Wagner Bruna
hgweb, i18n: do not translate search mode description...
r20004 MODE_REVISION: (revsearch, 'exact revision search'),
MODE_KEYWORD: (keywordsearch, 'literal keyword search'),
MODE_REVSET: (revsetsearch, 'revset expression search'),
Alexander Plavin
hgweb: add dynamic search function selection, depending on the query...
r19631 }
Alexander Plavin
hgweb: pass arguments which a function depends on explicitly in search...
r19632 def getsearchmode(query):
Alexander Plavin
hgweb: search() function supports direct pointing to revision...
r19633 try:
ctx = web.repo[query]
except (error.RepoError, error.LookupError):
Alexander Plavin
hgweb: add revset syntax support to search...
r19722 # query is not an exact revision pointer, need to
Mads Kiilerich
spelling: random spell checker fixes
r19951 # decide if it's a revset expression or keywords
Alexander Plavin
hgweb: add revset syntax support to search...
r19722 pass
Alexander Plavin
hgweb: search() function supports direct pointing to revision...
r19633 else:
Alexander Plavin
hgweb: add string constants for search mode names...
r19656 return MODE_REVISION, ctx
Alexander Plavin
hgweb: add dynamic search function selection, depending on the query...
r19631
Alexander Plavin
hgweb: add revset syntax support to search...
r19722 revdef = 'reverse(%s)' % query
try:
tree, pos = revset.parse(revdef)
except ParseError:
# can't parse to a revset tree
return MODE_KEYWORD, query
if revset.depth(tree) <= 2:
# no revset syntax used
return MODE_KEYWORD, query
if util.any((token, (value or '')[:3]) == ('string', 're:')
for token, value, pos in revset.tokenize(revdef)):
return MODE_KEYWORD, query
funcsused = revset.funcsused(tree)
if not funcsused.issubset(revset.safesymbols):
return MODE_KEYWORD, query
mfunc = revset.match(web.repo.ui, revdef)
try:
Lucas Moscovicz
revset: added baseset class (still empty) to improve revset performance...
r20364 revs = mfunc(web.repo, revset.baseset(web.repo))
Alexander Plavin
hgweb: add revset syntax support to search...
r19722 return MODE_REVSET, revs
# ParseError: wrongly placed tokens, wrongs arguments, etc
# RepoLookupError: no such revision, e.g. in 'revision:'
# Abort: bookmark/tag not exists
# LookupError: ambiguous identifier, e.g. in '(bc)' on a large repo
except (ParseError, RepoLookupError, Abort, LookupError):
return MODE_KEYWORD, query
Alexander Plavin
hgweb: separate search itself and template generation...
r19533 def changelist(**map):
count = 0
Alexander Plavin
hgweb: pass variable with current search mode name to the search template
r19765 for ctx in searchfunc[0](funcarg):
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(),
Benoit Boissinot
templates: export extra as a dict to templates...
r18581 extra=ctx.extra(),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 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),
Yuya Nishihara
hgweb: add bookmark labels to monoblue theme (based on 270f57d35525)
r13794 bookmarks=webutil.nodebookmarksdict(web.repo, n),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 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
Alexander Plavin
hgweb: move local changelist function to the beginning of the parent one
r19418 query = req.form['rev'][0]
revcount = web.maxchanges
if 'revcount' in req.form:
Isaac Jurado
hgweb: ignore non numeric "revcount" parameter values (issue4091)
r20092 try:
revcount = int(req.form.get('revcount', [revcount])[0])
revcount = max(revcount, 1)
tmpl.defaults['sessionvars']['revcount'] = revcount
except ValueError:
pass
Alexander Plavin
hgweb: move local changelist function to the beginning of the parent one
r19418
lessvars = copy.copy(tmpl.defaults['sessionvars'])
lessvars['revcount'] = max(revcount / 2, 1)
lessvars['rev'] = query
morevars = copy.copy(tmpl.defaults['sessionvars'])
morevars['revcount'] = revcount * 2
morevars['rev'] = query
Alexander Plavin
hgweb: pass arguments which a function depends on explicitly in search...
r19632 mode, funcarg = getsearchmode(query)
Alexander Plavin
hgweb: add link to force literal keyword search...
r19768
if 'forcekw' in req.form:
showforcekw = ''
showunforcekw = searchfuncs[mode][1]
mode = MODE_KEYWORD
funcarg = query
else:
if mode != MODE_KEYWORD:
showforcekw = searchfuncs[MODE_KEYWORD][1]
else:
showforcekw = ''
showunforcekw = ''
Alexander Plavin
hgweb: add dynamic search function selection, depending on the query...
r19631 searchfunc = searchfuncs[mode]
Patrick Mezard
webcommands: remove unncessary access to repo.changelog...
r12059 tip = web.repo['tip']
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 parity = paritygen(web.stripecount)
Patrick Mezard
webcommands: remove unncessary access to repo.changelog...
r12059 return tmpl('search', query=query, node=tip.hex(),
Dirkjan Ochtman
hgweb: add less/more links for search logs (issue1972)
r10247 entries=changelist, archives=web.archivelist("tip"),
Alexander Plavin
hgweb: pass variable with current search mode name to the search template
r19765 morevars=morevars, lessvars=lessvars,
Alexander Plavin
hgweb: add link to force literal keyword search...
r19768 modedesc=searchfunc[1],
showforcekw=showforcekw, showunforcekw=showunforcekw)
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):
Alexander Plavin
hgweb: show current search query in the input field
r19396 query = ''
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)
Alexander Plavin
hgweb: cleaner if conditions in changelog() function...
r19534 elif 'rev' in req.form:
Alexander Plavin
hgweb: always run search when a query is entered (bc)...
r19634 return _search(web, req, tmpl)
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591 else:
Alexander Plavin
hgweb: cleaner if conditions in changelog() function...
r19534 ctx = web.repo['tip']
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Alexander Plavin
hgweb: always compute all entries and latestentry in changelog...
r19737 def changelist():
Pierre-Yves David
hgweb: use changelog for iteration...
r18427 revs = []
Alexander Plavin
hgweb: fix incorrect way to count revisions in log (issue3977)...
r19486 if pos != -1:
revs = web.repo.changelog.revs(pos, 0)
curcount = 0
Pierre-Yves David
hgweb: `limit` argument is actually `latestonly` renames and enforce...
r18402 for i in revs:
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
Alexander Plavin
hgweb: fix incorrect way to count revisions in log (issue3977)...
r19486 curcount += 1
Alexander Plavin
hgweb: add nextentry variable for easy pagination in changelog...
r19738 if curcount > revcount + 1:
Alexander Plavin
hgweb: fix incorrect way to count revisions in log (issue3977)...
r19486 break
yield {"parity": parity.next(),
"author": ctx.user(),
"parent": webutil.parents(ctx, i - 1),
"child": webutil.children(ctx, i + 1),
"changelogtag": showtags,
"desc": ctx.description(),
"extra": ctx.extra(),
"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)
}
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
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:
Isaac Jurado
hgweb: ignore non numeric "revcount" parameter values (issue4091)
r20092 try:
revcount = int(req.form.get('revcount', [revcount])[0])
revcount = max(revcount, 1)
tmpl.defaults['sessionvars']['revcount'] = revcount
except ValueError:
pass
Dirkjan Ochtman
hgweb: add less/more links to shortlog/filelog nav
r10246
lessvars = copy.copy(tmpl.defaults['sessionvars'])
Md. O. Shayan
hgweb: set minimum number of revision to display to 1 when revcount is 0...
r13931 lessvars['revcount'] = max(revcount / 2, 1)
Dirkjan Ochtman
hgweb: add less/more links to shortlog/filelog nav
r10246 morevars = copy.copy(tmpl.defaults['sessionvars'])
morevars['revcount'] = revcount * 2
Patrick Mezard
webcommands: remove unncessary access to repo.changelog...
r12059 count = len(web.repo)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 pos = ctx.rev()
Alexander Plavin
hgweb: fix incorrect way to count revisions in log (issue3977)...
r19486 parity = paritygen(web.stripecount)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Pierre-Yves David
hgweb: pass repo object to revnav construction...
r18409 changenav = webutil.revnav(web.repo).gen(pos, revcount, count)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Alexander Plavin
hgweb: always compute all entries and latestentry in changelog...
r19737 entries = list(changelist())
latestentry = entries[:1]
Alexander Plavin
hgweb: add nextentry variable for easy pagination in changelog...
r19738 if len(entries) > revcount:
nextentry = entries[-1:]
entries = entries[:-1]
else:
nextentry = []
Alexander Plavin
hgweb: always compute all entries and latestentry in changelog...
r19737
Dirkjan Ochtman
hgweb: add less/more links to shortlog/filelog nav
r10246 return tmpl(shortlog and 'shortlog' or 'changelog', changenav=changenav,
Alexander Solovyov
drop {short,hex}(ctx.node()) calls in favor of ctx methods
r14055 node=ctx.hex(), rev=pos, changesets=count,
Alexander Plavin
hgweb: always compute all entries and latestentry in changelog...
r19737 entries=entries,
Alexander Plavin
hgweb: add nextentry variable for easy pagination in changelog...
r19738 latestentry=latestentry, nextentry=nextentry,
Dirkjan Ochtman
hgweb: add less/more links to shortlog/filelog nav
r10246 archives=web.archivelist("tip"), revcount=revcount,
Alexander Plavin
hgweb: show current search query in the input field
r19396 morevars=morevars, lessvars=lessvars, query=query)
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):
Mads Kiilerich
check-code: check for spaces around = for named parameters
r19872 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)
Weiwen
hgweb: display diff for a changeset against any parents (issue2810)...
r17991 basectx = webutil.basechangectx(web.repo, req)
if basectx is None:
basectx = ctx.p1()
Dirkjan Ochtman
hgweb: move the diffs() generator into webutil
r7310 showtags = webutil.showtag(web.repo, tmpl, 'changesettag', ctx.node())
Alexander Solovyov
hgweb: add display of bookmarks for changelog and changeset
r13596 showbookmarks = webutil.showbookmark(web.repo, tmpl, 'changesetbookmark',
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)
Paul Boddie
hgweb: add block numbers to diff regions and related links...
r16308 for blockno, f in enumerate(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,
Paul Boddie
hgweb: add block numbers to diff regions and related links...
r16308 node=ctx.hex(), file=f, blockno=blockno + 1,
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 parity=parity.next()))
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]
Steven Brown
web: provide diffstat to the changeset page...
r14490 parity = paritygen(web.stripecount)
Weiwen
hgweb: display diff for a changeset against any parents (issue2810)...
r17991 diffs = webutil.diffs(web.repo, tmpl, ctx, basectx, None, parity, style)
Steven Brown
web: provide diffstat to the changeset page...
r14490
parity = paritygen(web.stripecount)
Weiwen
hgweb: display diff for a changeset against any parents (issue2810)...
r17991 diffstatgen = webutil.diffstatgen(ctx, basectx)
Steven Brown
web: provide diff summary to the changeset page...
r14570 diffstat = webutil.diffstat(tmpl, ctx, diffstatgen, parity)
Steven Brown
web: provide diffstat to the changeset page...
r14490
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),
Kevin Bullock
hgweb: rename 'currentbaseline' template keyword to 'basenode'...
r18524 basenode=basectx.hex(),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 changesettag=showtags,
Alexander Solovyov
hgweb: add display of bookmarks for changelog and changeset
r13596 changesetbookmark=showbookmarks,
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(),
Benoit Boissinot
templates: export extra as a dict to templates...
r18581 extra=ctx.extra(),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 date=ctx.date(),
files=files,
Steven Brown
web: provide diff summary to the changeset page...
r14570 diffsummary=lambda **x: webutil.diffsummary(diffstatgen),
Steven Brown
web: provide diffstat to the changeset page...
r14490 diffstat=diffstat,
Dirkjan Ochtman
hgweb: move the diffs() generator into webutil
r7310 archives=web.archivelist(ctx.hex()),
tags=webutil.nodetagsdict(web.repo, ctx.node()),
Alexander Solovyov
hgweb: add display of bookmarks for changelog and changeset
r13596 bookmarks=webutil.nodebookmarksdict(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
Martin Geisler
hgweb: add hook for remapping repository path into virtual paths...
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
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
Martin Geisler
hgweb: add hook for remapping repository path into virtual paths...
r16448 for full, n in mf.iteritems():
# the virtual path (working copy path) used for the full
# (repository) path
f = decodepath(full)
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:
Martin Geisler
hgweb: add hook for remapping repository path into virtual paths...
r16448 files[remain] = full
Ry4an Brase
hgweb: descend empty directories in web view...
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
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:
Matt Mackall
many, many trivial check-code fixups
r10282 k, v = h.items()[0]
Ry4an Brase
hgweb: descend empty directories in web view...
r7305 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),
Yuya Nishihara
hgweb: add bookmark labels to monoblue theme (based on 270f57d35525)
r13794 bookmarks=webutil.nodebookmarksdict(web.repo, node),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 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):
Matt Mackall
hgweb: fix iterator reuse in atom feed generation
r18029 i = list(reversed(web.repo.tagslist()))
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 parity = paritygen(web.stripecount)
Pierre-Yves David
hgweb: `limit` argument is actually `latestonly` renames and enforce...
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
hgweb: refactor hgweb code
r6393 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()),
Pierre-Yves David
hgweb: `limit` argument is actually `latestonly` renames and enforce...
r18402 entries=lambda **x: entries(False, False, **x),
entriesnotip=lambda **x: entries(True, False, **x),
latestentry=lambda **x: entries(True, True, **x))
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Alexander Solovyov
hgweb: add separate page with bookmarks listing
r13597 def bookmarks(web, req, tmpl):
Kevin Bullock
hgweb: don't attempt to show hidden bookmarks (issue3774)...
r18478 i = [b for b in web.repo._bookmarks.items() if b[1] in web.repo]
Alexander Solovyov
hgweb: add separate page with bookmarks listing
r13597 parity = paritygen(web.stripecount)
Pierre-Yves David
hgweb: `limit` argument is actually `latestonly` renames and enforce...
r18402 def entries(latestonly, **map):
if latestonly:
t = [min(i)]
else:
t = sorted(i)
for k, n in t:
Alexander Solovyov
hgweb: add separate page with bookmarks listing
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
hgweb: `limit` argument is actually `latestonly` renames and enforce...
r18402 entries=lambda **x: entries(latestonly=False, **x),
latestentry=lambda **x: entries(latestonly=True, **x))
Alexander Solovyov
hgweb: add separate page with bookmarks listing
r13597
Sune Foldager
webcommands: add 'branches' command, similar to 'tags'
r8352 def branches(web, req, tmpl):
Matt Mackall
hgweb: avoid generator exhaustion with branches
r18030 tips = []
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)
Brodie Rao
hgweb: simplify branches with repo.branchmap().iterbranches()
r20194 sortkey = lambda item: (not item[1], item[0].rev())
Sune Foldager
webcommands: add 'branches' command, similar to 'tags'
r8352
def entries(limit, **map):
count = 0
Matt Mackall
hgweb: avoid generator exhaustion with branches
r18030 if not tips:
Brodie Rao
hgweb: simplify branches with repo.branchmap().iterbranches()
r20194 for tag, hs, tip, closed in web.repo.branchmap().iterbranches():
tips.append((web.repo[tip], closed))
for ctx, closed 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
Brodie Rao
hgweb: simplify branches with repo.branchmap().iterbranches()
r20194 if closed:
Jesse Long
hgweb: treat branch attribute `closed' as more important than `inactive'...
r14771 status = 'closed'
elif ctx.node() not in heads:
John Mulligan
localrepo: remove 'closed' argument to heads(...) function...
r8796 status = 'inactive'
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):
Patrick Mezard
webcommands: do not modify repo.tagslist()...
r17261 i = reversed(web.repo.tagslist())
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
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
Yuya Nishihara
hgweb: add bookmarks listing to summary page of gitweb/monoblue styles
r13924 def bookmarks(**map):
parity = paritygen(web.stripecount)
Kevin Bullock
hgweb: make 'summary' work with hidden changesets (issue3810)...
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
hgweb: add bookmarks listing to summary page of gitweb/monoblue styles
r13924 yield {'parity': parity.next(),
'bookmark': k,
'date': web.repo[n].date(),
'node': hex(n)}
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 def branches(**map):
parity = paritygen(web.stripecount)
Brodie Rao
hgweb: simplify summary with repo.branchmap().iterbranches()
r20193 b = web.repo.branchmap()
l = [(-web.repo.changelog.rev(tip), tip, tag)
for tag, heads, tip, closed in b.iterbranches()]
Matt Mackall
many, many trivial check-code fixups
r10282 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):
Matt Mackall
many, many trivial check-code fixups
r10282 parity = paritygen(web.stripecount, offset=start - end)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 l = [] # build a list in forward order for efficiency
Kevin Bullock
hgweb: make 'summary' work with hidden changesets (issue3810)...
r18563 revs = []
if start < end:
revs = web.repo.changelog.revs(start, end - 1)
for i in revs:
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)
Pierre-Yves David
hgweb: no do not use listinsert(0, ...)...
r18319 l.append(tmpl(
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 'shortlogentry',
parity=parity.next(),
author=ctx.user(),
desc=ctx.description(),
Benoit Boissinot
templates: export extra as a dict to templates...
r18581 extra=ctx.extra(),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 date=ctx.date(),
rev=i,
node=hn,
tags=webutil.nodetagsdict(web.repo, n),
Yuya Nishihara
hgweb: add bookmark labels to monoblue theme (based on 270f57d35525)
r13794 bookmarks=webutil.nodebookmarksdict(web.repo, n),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 inbranch=webutil.nodeinbranch(web.repo, ctx),
branches=webutil.nodebranchdict(web.repo, ctx)))
Pierre-Yves David
hgweb: no do not use listinsert(0, ...)...
r18319 l.reverse()
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 yield l
Patrick Mezard
webcommands: remove unncessary access to repo.changelog...
r12059 tip = web.repo['tip']
count = len(web.repo)
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",
Patrick Mezard
webcommands: remove unncessary access to repo.changelog...
r12059 lastchange=tip.date(),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 tags=tagentries,
Yuya Nishihara
hgweb: add bookmarks listing to summary page of gitweb/monoblue styles
r13924 bookmarks=bookmarks,
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 branches=branches,
shortlog=changelist,
Patrick Mezard
webcommands: remove unncessary access to repo.changelog...
r12059 node=tip.hex(),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 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()
Matt Mackall
hgweb: fix filediff base calculation...
r16722 ctx = fctx.changectx()
Dirkjan Ochtman
hgweb: working diff for removed files
r7183 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]
Weiwen
hgweb: display diff for a changeset against any parents (issue2810)...
r17991 diffs = webutil.diffs(web.repo, tmpl, ctx, None, [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(),
Benoit Boissinot
templates: export extra as a dict to templates...
r18581 extra=ctx.extra(),
Dirkjan Ochtman
hgweb: working diff for removed files
r7183 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
wujek srujek
hgweb: side-by-side comparison functionality...
r17202 def comparison(web, req, tmpl):
ctx = webutil.changectx(web.repo, req)
Ross Lagerwall
hgweb: avoid traceback when file or node parameters are missing...
r17289 if 'file' not in req.form:
raise ErrorResponse(HTTP_NOT_FOUND, 'file not given')
wujek srujek
hgweb: side-by-side comparison functionality...
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
hgweb: fixes traceback for invalid files by removing top-level template...
r17302 def filelines(f):
Alexander Plavin
hgweb: import the whole util module in webcommands instead of just one function...
r19657 if util.binary(f.data()):
wujek srujek
hgweb: fixes traceback for invalid files by removing top-level template...
r17302 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
hgweb: side-by-side comparison functionality...
r17202 return tmpl('filecomparison',
file=path,
node=hex(ctx.node()),
rev=ctx.rev(),
date=ctx.date(),
desc=ctx.description(),
Benoit Boissinot
templates: export extra as a dict to templates...
r18581 extra=ctx.extra(),
wujek srujek
hgweb: side-by-side comparison functionality...
r17202 author=ctx.user(),
rename=rename,
branch=webutil.nodebranchnodefault(ctx),
wujek srujek
hgweb: fixes invalid parents / children in comparison...
r17303 parent=webutil.parents(fctx),
child=webutil.children(fctx),
wujek srujek
hgweb: fixes traceback for invalid files by removing top-level template...
r17302 leftrev=leftrev,
leftnode=hex(leftnode),
rightrev=rightrev,
rightnode=hex(rightnode),
wujek srujek
hgweb: side-by-side comparison functionality...
r17202 comparison=comparison)
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)
Patrick Mezard
annotate: support diff whitespace filtering flags (issue3030)...
r15528 diffopts = patch.diffopts(web.repo.ui, untrusted=True, section='annotate')
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
def annotate(**map):
last = None
Alexander Plavin
hgweb: import the whole util module in webcommands instead of just one function...
r19657 if util.binary(fctx.data()):
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 mt = (mimetypes.guess_type(fctx.path())[0]
or 'application/octet-stream')
lines = enumerate([((fctx.filectx(fctx.filerev()), 1),
'(binary:%s)' % mt)])
else:
Patrick Mezard
annotate: support diff whitespace filtering flags (issue3030)...
r15528 lines = enumerate(fctx.annotate(follow=True, linenumber=True,
diffopts=diffopts))
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 for lineno, ((f, targetline), l) in lines:
fnode = f.filenode()
if last != fnode:
last = fnode
yield {"parity": parity.next(),
Alexander Solovyov
drop {short,hex}(ctx.node()) calls in favor of ctx methods
r14055 "node": f.hex(),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 "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(),
Benoit Boissinot
templates: export extra as a dict to templates...
r18581 "extra": f.extra(),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 "file": f.path(),
"targetline": targetline,
"line": l,
"lineid": "l%d" % (lineno + 1),
Oli Thissen
hgweb: added revision date to annotate line data...
r13199 "linenumber": "% 6d" % (lineno + 1),
"revdate": f.date()}
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
return tmpl("fileannotate",
file=f,
annotate=annotate,
path=webutil.up(f),
rev=fctx.rev(),
Alexander Solovyov
drop {short,hex}(ctx.node()) calls in favor of ctx methods
r14055 node=fctx.hex(),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 author=fctx.user(),
date=fctx.date(),
desc=fctx.description(),
Benoit Boissinot
templates: export extra as a dict to templates...
r18581 extra=fctx.extra(),
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:
Isaac Jurado
hgweb: ignore non numeric "revcount" parameter values (issue4091)
r20092 try:
revcount = int(req.form.get('revcount', [revcount])[0])
revcount = max(revcount, 1)
tmpl.defaults['sessionvars']['revcount'] = revcount
except ValueError:
pass
Dirkjan Ochtman
hgweb: add less/more links to shortlog/filelog nav
r10246
lessvars = copy.copy(tmpl.defaults['sessionvars'])
Md. O. Shayan
hgweb: set minimum number of revision to display to 1 when revcount is 0...
r13931 lessvars['revcount'] = max(revcount / 2, 1)
Dirkjan Ochtman
hgweb: add less/more links to shortlog/filelog nav
r10246 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
Matt Mackall
many, many trivial check-code fixups
r10282 parity = paritygen(web.stripecount, offset=start - end)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Alexander Plavin
hgweb: always compute all entries and latestentry in filelog...
r20022 def entries():
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 l = []
Benoit Boissinot
web: use the correct filectx in filelog
r7612 repo = web.repo
Alexander Plavin
hgweb: use semantically suitable filelog.revs in filelog...
r20023 revs = fctx.filelog().revs(start, end - 1)
Pierre-Yves David
hgweb: `limit` argument is actually `latestonly` renames and enforce...
r18402 for i in revs:
Benoit Boissinot
web: use the correct filectx in filelog
r7612 iterfctx = fctx.filectx(i)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Pierre-Yves David
hgweb: no do not use listinsert(0, ...)...
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
templates: export extra as a dict to templates...
r18581 "extra": iterfctx.extra(),
Pierre-Yves David
hgweb: no do not use listinsert(0, ...)...
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
hgweb: refactor hgweb code
r6393 yield e
Alexander Plavin
hgweb: always compute all entries and latestentry in filelog...
r20022 entries = list(entries())
latestentry = entries[:1]
Pierre-Yves David
hgweb: pass repo object to revnav construction...
r18409 revnav = webutil.filerevnav(web.repo, fctx.path())
nav = revnav.gen(end - 1, revcount, count)
Alexander Solovyov
drop {short,hex}(ctx.node()) calls in favor of ctx methods
r14055 return tmpl("filelog", file=f, node=fctx.hex(), nav=nav,
Alexander Plavin
hgweb: always compute all entries and latestentry in filelog...
r20022 entries=entries,
latestentry=latestentry,
Dirkjan Ochtman
hgweb: add less/more links to shortlog/filelog nav
r10246 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)
Angel Ezquerra
hgweb: teach archive how to download a specific directory or file...
r18771
ctx = webutil.changectx(web.repo, req)
pats = []
Angel Ezquerra
hgweb: respond HTTP_NOT_FOUND when an archive request does not match any files
r18968 matchfn = None
Angel Ezquerra
hgweb: teach archive how to download a specific directory or file...
r18771 file = req.form.get('file', None)
if file:
Angel Ezquerra
hgweb: respond HTTP_NOT_FOUND when an archive request does not match any files
r18968 pats = ['path:' + file[0]]
matchfn = scmutil.match(ctx, pats, default='path')
if pats:
files = [f for f in ctx.manifest().keys() if matchfn(f)]
if not files:
raise ErrorResponse(HTTP_NOT_FOUND,
'file(s) not found: %s' % file[0])
Angel Ezquerra
hgweb: teach archive how to download a specific directory or file...
r18771
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 mimetype, artype, extension, encoding = web.archive_specs[type_]
headers = [
('Content-Disposition', 'attachment; filename=%s%s' % (name, extension))
Mads Kiilerich
hgweb: make type a mandatory parameter to request.respond...
r18347 ]
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 if encoding:
headers.append(('Content-Encoding', encoding))
Mads Kiilerich
hgweb: simplify wsgirequest header handling...
r18348 req.headers.extend(headers)
Mads Kiilerich
hgweb: make type a mandatory parameter to request.respond...
r18347 req.respond(HTTP_OK, mimetype)
Jordi Gutiérrez Hermoso
webcommands: allow hgweb's archive to recurse into subrepos...
r17933
archival.archive(web.repo, req, cnode, artype, prefix=name,
Angel Ezquerra
hgweb: teach archive how to download a specific directory or file...
r18771 matchfn=matchfn,
Jordi Gutiérrez Hermoso
webcommands: allow hgweb's archive to recurse into subrepos...
r17933 subrepos=web.configbool("web", "archivesubrepos"))
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 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]
Mads Kiilerich
hgweb: simplify internal staticfile return codes
r18645 staticfile(static, fname, req)
return []
Dirkjan Ochtman
add graph page to hgweb
r6691
def graph(web, req, tmpl):
Dirkjan Ochtman
hgweb: make graph page size equal to shortlog
r10245
Patrick Mezard
hgweb: fix graph view paging...
r17318 ctx = webutil.changectx(web.repo, req)
rev = ctx.rev()
Dirkjan Ochtman
add graph page to hgweb
r6691 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:
Isaac Jurado
hgweb: ignore non numeric "revcount" parameter values (issue4091)
r20092 try:
revcount = int(req.form.get('revcount', [revcount])[0])
revcount = max(revcount, 1)
tmpl.defaults['sessionvars']['revcount'] = revcount
except ValueError:
pass
Dirkjan Ochtman
hgweb: fix up the less/more links on the graph page...
r7345
lessvars = copy.copy(tmpl.defaults['sessionvars'])
Md. O. Shayan
hgweb: set minimum number of revision to display to 1 when revcount is 0...
r13931 lessvars['revcount'] = max(revcount / 2, 1)
Dirkjan Ochtman
hgweb: fix up the less/more links on the graph page...
r7345 morevars = copy.copy(tmpl.defaults['sessionvars'])
morevars['revcount'] = revcount * 2
Patrick Mezard
hgweb: fix graph view paging...
r17318 count = len(web.repo)
pos = rev
uprev = min(max(0, count - 1), rev + revcount)
Dirkjan Ochtman
add graph page to hgweb
r6691 downrev = max(0, rev - revcount)
Pierre-Yves David
hgweb: pass repo object to revnav construction...
r18409 changenav = webutil.revnav(web.repo).gen(pos, revcount, count)
Dirkjan Ochtman
add graph page to hgweb
r6691
Pierre-Yves David
hgweb: walk the graph through the changelog...
r18428 tree = []
Alexander Plavin
hgweb: fix incorrect revisions count in graph (issue3977)...
r19487 if pos != -1:
allrevs = web.repo.changelog.revs(pos, 0)
revs = []
for i in allrevs:
revs.append(i)
if len(revs) >= revcount:
break
Lucas Moscovicz
webcommands: changed code to use lazy classes when calling dagwalker...
r20761 # We have to feed a baseset to dagwalker as it is expecting smartset
# object. This does not have a big impact on hgweb performance itself
# since hgweb graphing code is not itself lazy yet.
dag = graphmod.dagwalker(web.repo, revset.baseset(revs))
# As we said one line above... not lazy.
Pierre-Yves David
hgweb: walk the graph through the changelog...
r18428 tree = list(graphmod.colored(dag, web.repo))
Paul Boddie
hgweb: make graph data suitable for template usage...
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()))
Matt Mackall
hgweb: escape branch names in graph view
r19879 branch = cgi.escape(ctx.branch())
Paul Boddie
hgweb: make graph data suitable for template usage...
r16773 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,
Matt Mackall
hgweb: add escaping of tags and bookmarks in graph view
r19883 [cgi.escape(x) for x in ctx.tags()],
[cgi.escape(x) for x in ctx.bookmarks()]))
Paul Boddie
hgweb: make graph data suitable for template usage...
r16773 else:
Augie Fackler
webcommands: move from dict() construction to {} literals...
r20678 edgedata = [{'col': edge[0], 'nextcol': edge[1],
'color': (edge[2] - 1) % 6 + 1,
'width': edge[3], 'bcolor': edge[4]}
Paul Boddie
hgweb: make graph data suitable for template usage...
r16773 for edge in edges]
data.append(
Augie Fackler
webcommands: move from dict() construction to {} literals...
r20678 {'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())})
Paul Boddie
hgweb: make graph data suitable for template usage...
r16773
row += 1
return data
cols = getcolumns(tree)
rows = len(tree)
canvasheight = (rows + 1) * bg_height - 27
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,
Paul Boddie
hgweb: make graph data suitable for template usage...
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
hgweb: fix graph view paging...
r17318 node=ctx.hex(), changenav=changenav)
Augie Fackler
web: add a help view for getting hg help output
r12666
def _getdoc(e):
doc = e[0].__doc__
if doc:
FUJIWARA Katsunori
i18n: show localized messages for commands/extensions in hgweb help top (issue3383)...
r16469 doc = _(doc).split('\n')[0]
Augie Fackler
web: add a help view for getting hg help output
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
help: use the first topic name from helptable, not the longest alias...
r17322 yield {'topic': entries[0], 'summary': summary}
Augie Fackler
web: add a help view for getting hg help output
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
hgweb: another fix for the help termwidth bug
r12696 u = webutil.wsgiui()
Adrian Buehlmann
hgweb: show help with verbose sections included...
r17146 u.verbose = True
Augie Fackler
web: add a help view for getting hg help output
r12666 try:
Dan Villiom Podlaski Christiansen
hgweb: generate HTML documentation...
r18747 doc = helpmod.help_(u, topicname)
Augie Fackler
web: add a help view for getting hg help output
r12666 except error.UnknownCommand:
raise ErrorResponse(HTTP_NOT_FOUND)
return tmpl('help', topic=topicname, doc=doc)