##// END OF EJS Templates
tests: use killdaemons.py in test-pull-http
tests: use killdaemons.py in test-pull-http

File last commit:

r7565:5f162f61 default
r7574:4afc3208 default
Show More
webcommands.py
663 lines | 22.3 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>
#
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
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
add graph page to hgweb
r6691 from mercurial import revlog, archival, templatefilters
Benoit Boissinot
fix bug introduced by 894875eae49b (short not defined)
r6410 from mercurial.node import short, hex, nullid
Dirkjan Ochtman
add graph page to hgweb
r6691 from mercurial.util import binary, datestr
Joel Rosdahl
Avoid importing mercurial.node/mercurial.repo stuff from mercurial.hg
r6217 from mercurial.repo import RepoError
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
Matt Mackall
util: add sort helper
r6762 from mercurial import graphmod, util
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',
'manifest', 'tags', 'summary', 'filediff', 'diff', 'annotate', 'filelog',
Dirkjan Ochtman
add graph page to hgweb
r6691 '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)
Dirkjan Ochtman
hgweb: better error messages
r6368 except revlog.LookupError, inst:
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():
for lineno, t in enumerate(text.splitlines(1)):
yield {"line": t,
"lineid": "l%d" % (lineno + 1),
"linenumber": "% 6d" % (lineno + 1),
"parity": parity.next()}
return tmpl("filerevision",
file=f,
path=webutil.up(f),
text=lines(),
rev=fctx.rev(),
node=hex(fctx.node()),
author=fctx.user(),
date=fctx.date(),
desc=fctx.description(),
branch=webutil.nodebranchnodefault(fctx),
parent=webutil.siblings(fctx.parents()),
child=webutil.siblings(fctx.children()),
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))
Benoit Boissinot
hgweb: do not use unassigned variables in exception handling
r6853 except revlog.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: refactor hgweb code
r6393 def _search(web, tmpl, query):
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(),
parent=webutil.siblings(ctx.parents()),
child=webutil.siblings(ctx.children()),
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))
if count >= web.maxchanges:
break
cl = web.repo.changelog
parity = paritygen(web.stripecount)
return tmpl('search',
query=query,
node=hex(cl.tip()),
entries=changelist,
archives=web.archivelist("tip"))
Dirkjan Ochtman
hgweb: explicitly pass around the templater
r5600 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]
Joel Rosdahl
Avoid importing mercurial.node/mercurial.repo stuff from mercurial.hg
r6217 except RepoError:
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 return _search(web, tmpl, hi) # XXX redirect to 404 page?
def changelist(limit=0, **map):
cl = web.repo.changelog
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(),
"parent": webutil.siblings(ctx.parents(), i - 1),
"child": webutil.siblings(ctx.children(), i + 1),
"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
maxchanges = shortlog and web.maxshortchanges or web.maxchanges
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()
start = max(0, pos - maxchanges + 1)
end = min(count, start + maxchanges)
pos = end - 1
parity = paritygen(web.stripecount, offset=start-end)
changenav = webutil.revnavgen(pos, maxchanges, count, web.repo.changectx)
return tmpl(shortlog and 'shortlog' or 'changelog',
changenav=changenav,
Matt Mackall
hgweb: minor improvements for new web style...
r6434 node=hex(ctx.node()),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 rev=pos, changesets=count,
entries=lambda **x: changelist(limit=0,**x),
latestentry=lambda **x: changelist(limit=1,**x),
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 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 parents = ctx.parents()
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)
diffs = webutil.diffs(web.repo, tmpl, ctx, None, parity)
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: refactor hgweb code
r6393 parent=webutil.siblings(parents),
child=webutil.siblings(ctx.children()),
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
for f, n in mf.items():
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
Ry4an Brase
hgweb: descend empty directories in web view...
r7305 if 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
util: add sort helper
r6762 for f in util.sort(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):
Ry4an Brase
hgweb: descend empty directories in web view...
r7305 for d in util.sort(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)
def entries(notip=False,limit=0, **map):
count = 0
for k, n in i:
if notip and k == "tip":
continue
if limit > 0 and count >= limit:
continue
count = count + 1
yield {"parity": parity.next(),
"tag": k,
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
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()
l = [(-web.repo.changelog.rev(n), n, t) for t, n in b.items()]
Matt Mackall
util: add sort helper
r6762 for r,n,t in util.sort(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()
parents = fctx.parents()
p1 = parents and parents[0].node() or nullid
else:
n = ctx.node()
# path already defined in except clause
parents = ctx.parents()
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Dirkjan Ochtman
hgweb: move the diffs() generator into webutil
r7310 parity = paritygen(web.stripecount)
diffs = webutil.diffs(web.repo, tmpl, fctx or ctx, [path], parity)
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: refactor hgweb code
r6393 parent=webutil.siblings(parents),
Dirkjan Ochtman
hgweb: working diff for removed files
r7183 child=webutil.siblings(ctx.children()),
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),
parent=webutil.siblings(fctx.parents()),
child=webutil.siblings(fctx.children()),
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()
except revlog.LookupError:
f = webutil.cleanpath(web.repo, req.form['file'][0])
fl = web.repo.file(f)
numrevs = len(fl)
if not numrevs: # file doesn't exist at all
raise
rev = webutil.changectx(web.repo, req).rev()
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
count = fctx.filerev() + 1
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 pagelen = web.maxshortchanges
Dirkjan Ochtman
hgweb: conditionally show file logs for deleted files
r7300 start = max(0, fctx.filerev() - pagelen + 1) # first rev on this page
end = min(count, start + pagelen) # 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 = []
for i in xrange(start, end):
ctx = fctx.filectx(i)
l.insert(0, {"parity": parity.next(),
"filerev": i,
"file": f,
"node": hex(ctx.node()),
"author": ctx.user(),
"date": ctx.date(),
Matt Mackall
hgweb: minor improvements for new web style...
r6434 "rename": webutil.renamelink(fctx),
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 "parent": webutil.siblings(fctx.parents()),
"child": webutil.siblings(fctx.children()),
Benoit Allard
coal/paper: display tags and branch in filelog page
r7409 "desc": ctx.description(),
"tags": webutil.nodetagsdict(web.repo, ctx.node()),
"branch": webutil.nodebranchnodefault(ctx),
"inbranch": webutil.nodeinbranch(web.repo, ctx),
"branches": webutil.nodebranchdict(web.repo, ctx)})
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: conditionally show file logs for deleted files
r7300 nav = webutil.revnavgen(end - 1, pagelen, 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),
latestentry=lambda **x: entries(limit=1, **x))
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:
tp = web.templatepath
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):
rev = webutil.changectx(web.repo, req).rev()
bg_height = 39
Dirkjan Ochtman
hgweb: fix up the less/more links on the graph page...
r7345 revcount = 25
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
Dirkjan Ochtman
hgweb: let the web graph cope with low revisions/new repositories (issue1293)
r7030 tree = list(graphmod.graph(web.repo, rev, downrev))
Dirkjan Ochtman
add graph page to hgweb
r6691 canvasheight = (len(tree) + 1) * bg_height - 27;
data = []
for i, (ctx, vtx, edges) in enumerate(tree):
node = short(ctx.node())
age = templatefilters.age(ctx.date())
desc = templatefilters.firstline(ctx.description())
desc = cgi.escape(desc)
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)