--- a/mercurial/hgweb/hgweb_mod.py Fri Mar 28 19:37:28 2008 +0100
+++ b/mercurial/hgweb/hgweb_mod.py Fri Mar 28 19:40:44 2008 +0100
@@ -6,13 +6,12 @@
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
-import os, mimetypes, re
-from mercurial.node import hex, nullid, short
+import os, mimetypes
+from mercurial.node import hex, nullid
from mercurial.repo import RepoError
-from mercurial import mdiff, ui, hg, util, archival, patch, hook
+from mercurial import mdiff, ui, hg, util, patch, hook
from mercurial import revlog, templater, templatefilters, changegroup
-from common import get_mtime, style_map, paritygen, countgen, get_contact
-from common import ErrorResponse
+from common import get_mtime, style_map, paritygen, countgen, ErrorResponse
from common import HTTP_OK, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, HTTP_SERVER_ERROR
from request import wsgirequest
import webcommands, protocol, webutil
@@ -32,54 +31,6 @@
'static': [('cmd', ['static']), ('file', None)]
}
-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
-
- def nav(**map):
- l = []
- 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:
- l.append(("+%d" % f, hex(nodefunc(pos + f).node())))
- if pos - f >= 0:
- l.insert(0, ("-%d" % f, hex(nodefunc(pos - f).node())))
-
- try:
- yield {"label": "(0)", "node": hex(nodefunc('0').node())}
-
- for label, node in l:
- yield {"label": label, "node": node}
-
- yield {"label": "tip", "node": "tip"}
- except RepoError:
- pass
-
- return nav
-
class hgweb(object):
def __init__(self, repo, name=None):
if isinstance(repo, str):
@@ -407,476 +358,12 @@
yield diffblock(mdiff.unidiff(to, date1, tn, date2, f, f,
opts=diffopts), f, tn)
- def changelog(self, tmpl, ctx, shortlog=False):
- def changelist(limit=0,**map):
- cl = self.repo.changelog
- l = [] # build a list in forward order for efficiency
- for i in xrange(start, end):
- ctx = self.repo.changectx(i)
- n = ctx.node()
- showtags = webutil.showtag(self.repo, tmpl, 'changelogtag', n)
-
- 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(),
- "files": self.listfilediffs(tmpl, ctx.files(), n),
- "rev": i,
- "node": hex(n),
- "tags": webutil.nodetagsdict(self.repo, n),
- "inbranch": webutil.nodeinbranch(self.repo, ctx),
- "branches": webutil.nodebranchdict(self.repo, ctx)
- })
-
- if limit > 0:
- l = l[:limit]
-
- for e in l:
- yield e
-
- maxchanges = shortlog and self.maxshortchanges or self.maxchanges
- cl = self.repo.changelog
- count = cl.count()
- pos = ctx.rev()
- start = max(0, pos - maxchanges + 1)
- end = min(count, start + maxchanges)
- pos = end - 1
- parity = paritygen(self.stripecount, offset=start-end)
-
- changenav = revnavgen(pos, maxchanges, count, self.repo.changectx)
-
- return tmpl(shortlog and 'shortlog' or 'changelog',
- changenav=changenav,
- node=hex(cl.tip()),
- rev=pos, changesets=count,
- entries=lambda **x: changelist(limit=0,**x),
- latestentry=lambda **x: changelist(limit=1,**x),
- archives=self.archivelist("tip"))
-
- def search(self, tmpl, query):
-
- def changelist(**map):
- cl = self.repo.changelog
- count = 0
- qw = query.lower().split()
-
- def revgen():
- for i in xrange(cl.count() - 1, 0, -100):
- l = []
- for j in xrange(max(0, i - 100), i + 1):
- ctx = self.repo.changectx(j)
- 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
-
- count += 1
- n = ctx.node()
- showtags = webutil.showtag(self.repo, tmpl, 'changelogtag', n)
-
- 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(),
- files=self.listfilediffs(tmpl, ctx.files(), n),
- rev=ctx.rev(),
- node=hex(n),
- tags=webutil.nodetagsdict(self.repo, n),
- inbranch=webutil.nodeinbranch(self.repo, ctx),
- branches=webutil.nodebranchdict(self.repo, ctx))
-
- if count >= self.maxchanges:
- break
-
- cl = self.repo.changelog
- parity = paritygen(self.stripecount)
-
- return tmpl('search',
- query=query,
- node=hex(cl.tip()),
- entries=changelist,
- archives=self.archivelist("tip"))
-
- def changeset(self, tmpl, ctx):
- n = ctx.node()
- showtags = webutil.showtag(self.repo, tmpl, 'changesettag', n)
- parents = ctx.parents()
- p1 = parents[0].node()
-
- files = []
- parity = paritygen(self.stripecount)
- for f in ctx.files():
- files.append(tmpl("filenodelink",
- node=hex(n), file=f,
- parity=parity.next()))
-
- def diff(**map):
- yield self.diff(tmpl, p1, n, None)
-
- return tmpl('changeset',
- diff=diff,
- rev=ctx.rev(),
- node=hex(n),
- parent=webutil.siblings(parents),
- child=webutil.siblings(ctx.children()),
- changesettag=showtags,
- author=ctx.user(),
- desc=ctx.description(),
- date=ctx.date(),
- files=files,
- archives=self.archivelist(hex(n)),
- tags=webutil.nodetagsdict(self.repo, n),
- branch=webutil.nodebranchnodefault(ctx),
- inbranch=webutil.nodeinbranch(self.repo, ctx),
- branches=webutil.nodebranchdict(self.repo, ctx))
-
- def filelog(self, tmpl, fctx):
- f = fctx.path()
- fl = fctx.filelog()
- count = fl.count()
- pagelen = self.maxshortchanges
- pos = fctx.filerev()
- start = max(0, pos - pagelen + 1)
- end = min(count, start + pagelen)
- pos = end - 1
- parity = paritygen(self.stripecount, offset=start-end)
-
- def entries(limit=0, **map):
- l = []
-
- for i in xrange(start, end):
- ctx = fctx.filectx(i)
- n = fl.node(i)
-
- l.insert(0, {"parity": parity.next(),
- "filerev": i,
- "file": f,
- "node": hex(ctx.node()),
- "author": ctx.user(),
- "date": ctx.date(),
- "rename": webutil.renamelink(fl, n),
- "parent": webutil.siblings(fctx.parents()),
- "child": webutil.siblings(fctx.children()),
- "desc": ctx.description()})
-
- if limit > 0:
- l = l[:limit]
-
- for e in l:
- yield e
-
- nodefunc = lambda x: fctx.filectx(fileid=x)
- nav = revnavgen(pos, pagelen, count, nodefunc)
- 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))
-
- def filerevision(self, tmpl, fctx):
- f = fctx.path()
- text = fctx.data()
- fl = fctx.filelog()
- n = fctx.filenode()
- parity = paritygen(self.stripecount)
-
- if util.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=_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()),
- rename=webutil.renamelink(fl, n),
- permissions=fctx.manifest().flags(f))
-
- def fileannotate(self, tmpl, fctx):
- f = fctx.path()
- n = fctx.filenode()
- fl = fctx.filelog()
- parity = paritygen(self.stripecount)
-
- def annotate(**map):
- last = None
- if util.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()
- name = self.repo.ui.shortuser(f.user())
-
- if last != fnode:
- last = fnode
-
- yield {"parity": parity.next(),
- "node": hex(f.node()),
- "rev": f.rev(),
- "author": name,
- "file": f.path(),
- "targetline": targetline,
- "line": l,
- "lineid": "l%d" % (lineno + 1),
- "linenumber": "% 6d" % (lineno + 1)}
-
- return tmpl("fileannotate",
- file=f,
- annotate=annotate,
- path=_up(f),
- rev=fctx.rev(),
- node=hex(fctx.node()),
- author=fctx.user(),
- date=fctx.date(),
- desc=fctx.description(),
- rename=webutil.renamelink(fl, n),
- branch=webutil.nodebranchnodefault(fctx),
- parent=webutil.siblings(fctx.parents()),
- child=webutil.siblings(fctx.children()),
- permissions=fctx.manifest().flags(f))
-
- def manifest(self, tmpl, ctx, path):
- mf = ctx.manifest()
- node = ctx.node()
-
- files = {}
- parity = paritygen(self.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:]
- if "/" in remain:
- short = remain[:remain.index("/") + 1] # bleah
- files[short] = (f, None)
- else:
- short = os.path.basename(remain)
- files[short] = (f, n)
-
- if not files:
- raise ErrorResponse(HTTP_NOT_FOUND, 'path not found: ' + path)
-
- def filelist(**map):
- fl = files.keys()
- fl.sort()
- for f in fl:
- full, fnode = files[f]
- if not fnode:
- continue
-
- fctx = ctx.filectx(full)
- yield {"file": full,
- "parity": parity.next(),
- "basename": f,
- "date": fctx.changectx().date(),
- "size": fctx.size(),
- "permissions": mf.flags(full)}
-
- def dirlist(**map):
- fl = files.keys()
- fl.sort()
- for f in fl:
- full, fnode = files[f]
- if fnode:
- continue
-
- yield {"parity": parity.next(),
- "path": "%s%s" % (abspath, f),
- "basename": f[:-1]}
-
- return tmpl("manifest",
- rev=ctx.rev(),
- node=hex(node),
- path=abspath,
- up=_up(abspath),
- upparity=parity.next(),
- fentries=filelist,
- dentries=dirlist,
- archives=self.archivelist(hex(node)),
- tags=webutil.nodetagsdict(self.repo, node),
- inbranch=webutil.nodeinbranch(self.repo, ctx),
- branches=webutil.nodebranchdict(self.repo, ctx))
-
- def tags(self, tmpl):
- i = self.repo.tagslist()
- i.reverse()
- parity = paritygen(self.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,
- "date": self.repo.changectx(n).date(),
- "node": hex(n)}
-
- return tmpl("tags",
- node=hex(self.repo.changelog.tip()),
- entries=lambda **x: entries(False,0, **x),
- entriesnotip=lambda **x: entries(True,0, **x),
- latestentry=lambda **x: entries(True,1, **x))
-
- def summary(self, tmpl):
- i = self.repo.tagslist()
- i.reverse()
-
- def tagentries(**map):
- parity = paritygen(self.stripecount)
- count = 0
- for k, n in i:
- if k == "tip": # skip tip
- continue;
-
- count += 1
- if count > 10: # limit to 10 tags
- break;
-
- yield tmpl("tagentry",
- parity=parity.next(),
- tag=k,
- node=hex(n),
- date=self.repo.changectx(n).date())
-
-
- def branches(**map):
- parity = paritygen(self.stripecount)
-
- b = self.repo.branchtags()
- l = [(-self.repo.changelog.rev(n), n, t) for t, n in b.items()]
- l.sort()
-
- for r,n,t in l:
- ctx = self.repo.changectx(n)
-
- yield {'parity': parity.next(),
- 'branch': t,
- 'node': hex(n),
- 'date': ctx.date()}
-
- def changelist(**map):
- parity = paritygen(self.stripecount, offset=start-end)
- l = [] # build a list in forward order for efficiency
- for i in xrange(start, end):
- ctx = self.repo.changectx(i)
- 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(self.repo, n),
- inbranch=webutil.nodeinbranch(self.repo, ctx),
- branches=webutil.nodebranchdict(self.repo, ctx)))
-
- yield l
-
- cl = self.repo.changelog
- count = cl.count()
- start = max(0, count - self.maxchanges)
- end = min(count, start + self.maxchanges)
-
- return tmpl("summary",
- desc=self.config("web", "description", "unknown"),
- owner=get_contact(self.config) or "unknown",
- lastchange=cl.read(cl.tip())[2],
- tags=tagentries,
- branches=branches,
- shortlog=changelist,
- node=hex(cl.tip()),
- archives=self.archivelist("tip"))
-
- def filediff(self, tmpl, fctx):
- n = fctx.node()
- path = fctx.path()
- parents = fctx.parents()
- p1 = parents and parents[0].node() or nullid
-
- def diff(**map):
- yield self.diff(tmpl, p1, n, [path])
-
- return tmpl("filediff",
- file=path,
- node=hex(n),
- rev=fctx.rev(),
- branch=webutil.nodebranchnodefault(fctx),
- parent=webutil.siblings(parents),
- child=webutil.siblings(fctx.children()),
- diff=diff)
-
archive_specs = {
'bz2': ('application/x-tar', 'tbz2', '.tar.bz2', None),
'gz': ('application/x-tar', 'tgz', '.tar.gz', None),
'zip': ('application/zip', 'zip', '.zip', None),
}
- def archive(self, tmpl, req, key, type_):
- reponame = re.sub(r"\W+", "-", os.path.basename(self.reponame))
- cnode = self.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 = self.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(self.repo, req, cnode, artype, prefix=name)
-
def check_perm(self, req, op, default):
'''check permission for operation based on user auth.
return true if op allowed, else false.