##// END OF EJS Templates
revlog: do revlog node->rev mapping by scanning...
revlog: do revlog node->rev mapping by scanning Now that the nodemap is lazily created, we use linear scanning back from tip for typical node to rev mapping. Given that nodemap creation is O(n log n) and revisions searched for are usually very close to tip, this is often a significant performance win for a small number of searches. When we do end up building a nodemap for bulk lookups, the scanning function is replaced with a hash lookup.

File last commit:

r12691:1b1a9038 default
r13259:3b616dfa default
Show More
webutil.py
226 lines | 6.4 KiB | text/x-python | PythonLexer
Dirkjan Ochtman
hgweb: separate out utility functions
r6392 # hgweb/webutil.py - utility library for the web interface.
#
# 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
hgweb: separate out utility functions
r6392
Dirkjan Ochtman
hgweb: fix up the less/more links on the graph page...
r7345 import os, copy
Augie Fackler
hgweb: fix hgweb_mod as well as hgwebdir_mod
r12691 from mercurial import match, patch, util, error, ui
Dirkjan Ochtman
hgweb: separate out utility functions
r6392 from mercurial.node import hex, nullid
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 def up(p):
if p[0] != "/":
p = "/" + p
if p[-1] == "/":
p = p[:-1]
up = os.path.dirname(p)
if up == "/":
return "/"
return up + "/"
def revnavgen(pos, pagelen, limit, nodefunc):
def seq(factor, limit=None):
if limit:
yield limit
if limit >= 20 and limit <= 40:
yield 50
else:
yield 1 * factor
yield 3 * factor
for f in seq(factor * 10):
yield f
Nicolas Dumazet
hgweb: changenav: separate pages before and after the current position...
r10254 navbefore = []
navafter = []
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Nicolas Dumazet
hgweb: changenav: separate pages before and after the current position...
r10254 last = 0
for f in seq(1, pagelen):
if f < pagelen or f <= last:
continue
if f > limit:
break
last = f
if pos + f < limit:
navafter.append(("+%d" % f, hex(nodefunc(pos + f).node())))
if pos - f >= 0:
navbefore.insert(0, ("-%d" % f, hex(nodefunc(pos - f).node())))
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Nicolas Dumazet
hgweb: changenav: separate pages before and after the current position...
r10254 navafter.append(("tip", "tip"))
try:
navbefore.insert(0, ("(0)", hex(nodefunc('0').node())))
except error.RepoError:
pass
def gen(l):
def f(**map):
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 for label, node in l:
yield {"label": label, "node": node}
Nicolas Dumazet
hgweb: changenav: separate pages before and after the current position...
r10254 return f
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Matt Mackall
many, many trivial check-code fixups
r10282 return (dict(before=gen(navbefore), after=gen(navafter)),)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Dirkjan Ochtman
hgweb: simplify parents/children generation code
r7671 def _siblings(siblings=[], hiderev=None):
Dirkjan Ochtman
hgweb: separate out utility functions
r6392 siblings = [s for s in siblings if s.node() != nullid]
if len(siblings) == 1 and siblings[0].rev() == hiderev:
return
for s in siblings:
d = {'node': hex(s.node()), 'rev': s.rev()}
Dirkjan Ochtman
hgweb: pass more information about parent/child csets to templates
r7294 d['user'] = s.user()
d['date'] = s.date()
d['description'] = s.description()
Dirkjan Ochtman
hgweb: expose sibling branches to templater
r7717 d['branch'] = s.branch()
Dirkjan Ochtman
hgweb: separate out utility functions
r6392 if hasattr(s, 'path'):
d['file'] = s.path()
yield d
Dirkjan Ochtman
hgweb: simplify parents/children generation code
r7671 def parents(ctx, hide=None):
return _siblings(ctx.parents(), hide)
def children(ctx, hide=None):
return _siblings(ctx.children(), hide)
Matt Mackall
hgweb: minor improvements for new web style...
r6434 def renamelink(fctx):
Matt Mackall
hgweb: fix merge breakage
r6437 r = fctx.renamed()
Dirkjan Ochtman
hgweb: separate out utility functions
r6392 if r:
return [dict(file=r[0], node=hex(r[1]))]
return []
def nodetagsdict(repo, node):
return [{"name": i} for i in repo.nodetags(node)]
def nodebranchdict(repo, ctx):
branches = []
branch = ctx.branch()
# If this is an empty repo, ctx.node() == nullid,
# ctx.branch() == 'default', but branchtags() is
# an empty dict. Using dict.get avoids a traceback.
if repo.branchtags().get(branch) == ctx.node():
branches.append({"name": branch})
return branches
def nodeinbranch(repo, ctx):
branches = []
branch = ctx.branch()
if branch != 'default' and repo.branchtags().get(branch) != ctx.node():
branches.append({"name": branch})
return branches
def nodebranchnodefault(ctx):
branches = []
branch = ctx.branch()
if branch != 'default':
branches.append({"name": branch})
return branches
def showtag(repo, tmpl, t1, node=nullid, **args):
for t in repo.nodetags(node):
yield tmpl(t1, tag=t, **args)
def cleanpath(repo, path):
path = path.lstrip('/')
return util.canonpath(repo.root, '', path)
def changectx(repo, req):
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 changeid = "tip"
Dirkjan Ochtman
hgweb: separate out utility functions
r6392 if 'node' in req.form:
changeid = req.form['node'][0]
elif 'manifest' in req.form:
changeid = req.form['manifest'][0]
try:
Matt Mackall
use repo[changeid] to get a changectx
r6747 ctx = repo[changeid]
Matt Mackall
error: move repo errors...
r7637 except error.RepoError:
Dirkjan Ochtman
hgweb: separate out utility functions
r6392 man = repo.manifest
Matt Mackall
linkrev: take a revision number rather than a hash
r7361 ctx = repo[man.linkrev(man.rev(man.lookup(changeid)))]
Dirkjan Ochtman
hgweb: separate out utility functions
r6392
return ctx
def filectx(repo, req):
path = cleanpath(repo, req.form['file'][0])
if 'node' in req.form:
changeid = req.form['node'][0]
else:
changeid = req.form['filenode'][0]
try:
Matt Mackall
use repo[changeid] to get a changectx
r6747 fctx = repo[changeid][path]
Matt Mackall
error: move repo errors...
r7637 except error.RepoError:
Dirkjan Ochtman
hgweb: separate out utility functions
r6392 fctx = repo.filectx(path, fileid=changeid)
return fctx
Dirkjan Ochtman
hgweb: move the diffs() generator into webutil
r7310
Dirkjan Ochtman
hgweb: move another utility function into the webutil module
r7311 def listfilediffs(tmpl, files, node, max):
for f in files[:max]:
yield tmpl('filedifflink', node=hex(node), file=f)
if len(files) > max:
yield tmpl('fileellipses')
Dirkjan Ochtman
hgweb: show diff header line in raw diffs
r9402 def diffs(repo, tmpl, ctx, files, parity, style):
Dirkjan Ochtman
hgweb: move the diffs() generator into webutil
r7310
def countgen():
start = 1
while True:
yield start
start += 1
blockcount = countgen()
def prettyprintlines(diff):
blockno = blockcount.next()
for lineno, l in enumerate(diff.splitlines(True)):
lineno = "%d.%d" % (blockno, lineno + 1)
if l.startswith('+'):
ltype = "difflineplus"
elif l.startswith('-'):
ltype = "difflineminus"
elif l.startswith('@'):
ltype = "difflineat"
else:
ltype = "diffline"
yield tmpl(ltype,
line=l,
lineid="l%s" % lineno,
linenumber="% 8s" % lineno)
if files:
m = match.exact(repo.root, repo.getcwd(), files)
else:
m = match.always(repo.root, repo.getcwd())
diffopts = patch.diffopts(repo.ui, untrusted=True)
parents = ctx.parents()
node1 = parents and parents[0].node() or nullid
node2 = ctx.node()
block = []
for chunk in patch.diff(repo, node1, node2, m, opts=diffopts):
if chunk.startswith('diff') and block:
yield tmpl('diffblock', parity=parity.next(),
lines=prettyprintlines(''.join(block)))
block = []
Dirkjan Ochtman
hgweb: show diff header line in raw diffs
r9402 if chunk.startswith('diff') and style != 'raw':
Dirkjan Ochtman
hgweb: move the diffs() generator into webutil
r7310 chunk = ''.join(chunk.splitlines(True)[1:])
block.append(chunk)
yield tmpl('diffblock', parity=parity.next(),
lines=prettyprintlines(''.join(block)))
Dirkjan Ochtman
hgweb: fix up the less/more links on the graph page...
r7345
class sessionvars(object):
def __init__(self, vars, start='?'):
self.start = start
self.vars = vars
def __getitem__(self, key):
return self.vars[key]
def __setitem__(self, key, value):
self.vars[key] = value
def __copy__(self):
return sessionvars(copy.copy(self.vars), self.start)
def __iter__(self):
separator = self.start
for key, value in self.vars.iteritems():
yield {'name': key, 'value': str(value), 'separator': separator}
separator = '&'
Augie Fackler
hgweb: fix hgweb_mod as well as hgwebdir_mod
r12691
class wsgiui(ui.ui):
# default termwidth breaks under mod_wsgi
def termwidth(self):
return 80