##// END OF EJS Templates
copies: split the combination of the copies mapping in its own function...
copies: split the combination of the copies mapping in its own function In some case, this part take up to 95% of the copy tracing that take about a hundred second. This poor performance comes from the fact we keep duplciating and merging dictionary that are mostly similar. I want to experiment with smarter native code to do this, so I need to isolate the function first.

File last commit:

r43387:8ff1ecfa default
r44178:0cc91600 default
Show More
webcommands.py
1599 lines | 46.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
Yuya Nishihara
hgweb: use absolute_import
r27046 from __future__ import absolute_import
import copy
import mimetypes
import os
import re
from ..i18n import _
av6
hgweb: reuse graph node-related functions from templates...
r37928 from ..node import hex, short
Gregory Szorc
py3: manually import getattr where it is needed...
r43359 from ..pycompat import getattr
Yuya Nishihara
hgweb: use absolute_import
r27046
from .common import (
ErrorResponse,
HTTP_FORBIDDEN,
HTTP_NOT_FOUND,
get_contact,
paritygen,
staticfile,
)
from .. import (
archival,
Yuya Nishihara
dagop: move blockancestors() and blockdescendants() from context...
r32904 dagop,
Yuya Nishihara
hgweb: use absolute_import
r27046 encoding,
error,
graphmod,
Augie Fackler
webcommands: replace str(ctx) etc with pycompat.bytestr(ctx) etc...
r34810 pycompat,
Yuya Nishihara
hgweb: use absolute_import
r27046 revset,
Yuya Nishihara
revset: split language services to revsetlang module (API)...
r31024 revsetlang,
Yuya Nishihara
hgweb: use absolute_import
r27046 scmutil,
Yuya Nishihara
revset: import set classes directly from smartset module...
r31023 smartset,
Yuya Nishihara
hgweb: use absolute_import
r27046 templater,
Yuya Nishihara
hgweb: fix search {entries} to not return results of template expansion...
r37418 templateutil,
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 )
Augie Fackler
formatting: blacken the codebase...
r43346 from ..utils import stringutil
Yuya Nishihara
hgweb: use absolute_import
r27046
Augie Fackler
formatting: blacken the codebase...
r43346 from . import webutil
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Gregory Szorc
webcommands: define web commands using a decorator...
r24076 __all__ = []
Gregory Szorc
webcommands: define a dict of available commands...
r24077 commands = {}
Gregory Szorc
webcommands: define web commands using a decorator...
r24076
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
webcommands: define web commands using a decorator...
r24076 class webcommand(object):
"""Decorator used to register a web command handler.
The decorator takes as its positional arguments the name/path the
command should be accessible under.
Gregory Szorc
hgweb: support using new response object for web commands...
r36886 When called, functions receive as arguments a ``requestcontext``,
``wsgirequest``, and a templater instance for generatoring output.
The functions should populate the ``rctx.res`` object with details
about the HTTP response.
Gregory Szorc
hgweb: always return iterable from @webcommand functions (API)...
r36896 The function returns a generator to be consumed by the WSGI application.
For most commands, this should be the result from
Gregory Szorc
hgweb: add a sendtemplate() helper function...
r36899 ``web.res.sendresponse()``. Many commands will call ``web.sendtemplate()``
to render a template.
Gregory Szorc
hgweb: support using new response object for web commands...
r36886
Gregory Szorc
webcommands: define web commands using a decorator...
r24076 Usage:
Dirkjan Ochtman
hgweb: explicitly check if requested command exists
r5963
Gregory Szorc
webcommands: define web commands using a decorator...
r24076 @webcommand('mycommand')
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 def mycommand(web):
Gregory Szorc
webcommands: define web commands using a decorator...
r24076 pass
"""
Dirkjan Ochtman
hgweb: explicitly check if requested command exists
r5963
Gregory Szorc
webcommands: define web commands using a decorator...
r24076 def __init__(self, name):
self.name = name
def __call__(self, func):
__all__.append(self.name)
Gregory Szorc
webcommands: define a dict of available commands...
r24077 commands[self.name] = func
Gregory Szorc
webcommands: define web commands using a decorator...
r24076 return func
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @webcommand(b'log')
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 def log(web):
Gregory Szorc
webcommands: document "log" web command
r24087 """
/log[/{revision}[/{path}]]
--------------------------
Show repository or file history.
For URLs of the form ``/log/{revision}``, a list of changesets starting at
the specified changeset identifier is shown. If ``{revision}`` is not
defined, the default is ``tip``. This form is equivalent to the
``changelog`` handler.
For URLs of the form ``/log/{revision}/{file}``, the history for a specific
file will be shown. This form is equivalent to the ``filelog`` handler.
"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if web.req.qsparams.get(b'file'):
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 return filelog(web)
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591 else:
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 return changelog(web)
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @webcommand(b'rawfile')
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 def rawfile(web):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 guessmime = web.configbool(b'web', b'guessmime')
Matt Mackall
hgweb: raw file mimetype guessing configurable, off by default (BC) (issue2923)...
r15004
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 path = webutil.cleanpath(web.repo, web.req.qsparams.get(b'file', b''))
Dirkjan Ochtman
hgweb: fast path for sending raw files
r5890 if not path:
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 return manifest(web)
Dirkjan Ochtman
hgweb: fast path for sending raw files
r5890
try:
Gregory Szorc
hgweb: pass modern request type into various webutil functions (API)...
r36902 fctx = webutil.filectx(web.repo, web.req)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.LookupError as inst:
Dirkjan Ochtman
hgweb: better error messages
r6368 try:
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 return manifest(web)
Dirkjan Ochtman
hgweb: better error messages
r6368 except ErrorResponse:
raise inst
Dirkjan Ochtman
hgweb: fast path for sending raw files
r5890
path = fctx.path()
text = fctx.data()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 mt = b'application/binary'
Matt Mackall
hgweb: raw file mimetype guessing configurable, off by default (BC) (issue2923)...
r15004 if guessmime:
Gregory Szorc
py3: pass str and return bytes from mimetypes.guess_type()...
r40194 mt = mimetypes.guess_type(pycompat.fsdecode(path))[0]
Matt Mackall
hgweb: raw file mimetype guessing configurable, off by default (BC) (issue2923)...
r15004 if mt is None:
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 if stringutil.binary(text):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 mt = b'application/binary'
Jordi Gutiérrez Hermoso
style: kill ersatz if-else ternary operators...
r24306 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 mt = b'text/plain'
Gregory Szorc
py3: pass str and return bytes from mimetypes.guess_type()...
r40194 else:
mt = pycompat.sysbytes(mt)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if mt.startswith(b'text/'):
mt += b'; charset="%s"' % encoding.encoding
Dirkjan Ochtman
hgweb: fast path for sending raw files
r5890
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 web.res.headers[b'Content-Type'] = mt
Augie Fackler
formatting: blacken the codebase...
r43346 filename = (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 path.rpartition(b'/')[-1].replace(b'\\', b'\\\\').replace(b'"', b'\\"')
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 web.res.headers[b'Content-Disposition'] = (
b'inline; filename="%s"' % filename
)
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 web.res.setbodybytes(text)
Gregory Szorc
hgweb: always return iterable from @webcommand functions (API)...
r36896 return web.res.sendresponse()
Dirkjan Ochtman
hgweb: fast path for sending raw files
r5890
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 def _filerevision(web, fctx):
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 f = fctx.path()
text = fctx.data()
parity = paritygen(web.stripecount)
Gregory Szorc
hgweb: use heads() instead of headrevs()...
r39820 ishead = fctx.filenode() in fctx.filelog().heads()
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 if stringutil.binary(text):
Gregory Szorc
py3: pass str and return bytes from mimetypes.guess_type()...
r40194 mt = pycompat.sysbytes(
mimetypes.guess_type(pycompat.fsdecode(f))[0]
Augie Fackler
formatting: blacken the codebase...
r43346 or r'application/octet-stream'
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 text = b'(binary:%s)' % mt
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Yuya Nishihara
hgweb: wrap {lines} of filerevision with mappinggenerator...
r38071 def lines(context):
Nicolas Dumazet
for calls expecting bool args, pass bool instead of int...
r9136 for lineno, t in enumerate(text.splitlines(True)):
Augie Fackler
formatting: blacken the codebase...
r43346 yield {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"line": t,
b"lineid": b"l%d" % (lineno + 1),
b"linenumber": b"% 6d" % (lineno + 1),
b"parity": next(parity),
Augie Fackler
formatting: blacken the codebase...
r43346 }
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Gregory Szorc
hgweb: add a sendtemplate() helper function...
r36899 return web.sendtemplate(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'filerevision',
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 file=f,
path=webutil.up(f),
Yuya Nishihara
hgweb: wrap {lines} of filerevision with mappinggenerator...
r38071 text=templateutil.mappinggenerator(lines),
Gregory Szorc
hgweb: pass modern request type into various webutil functions (API)...
r36902 symrev=webutil.symrevorshortnode(web.req, fctx),
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 rename=webutil.renamelink(fctx),
permissions=fctx.manifest().flags(f),
ishead=int(ishead),
Augie Fackler
formatting: blacken the codebase...
r43346 **pycompat.strkwargs(webutil.commonentry(web.repo, fctx))
)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @webcommand(b'file')
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 def file(web):
Gregory Szorc
webcommands: document "file" web command
r24088 """
/file/{revision}[/{path}]
-------------------------
Show information about a directory or file in the repository.
Info about the ``path`` given as a URL parameter will be rendered.
If ``path`` is a directory, information about the entries in that
directory will be rendered. This form is equivalent to the ``manifest``
handler.
If ``path`` is a file, information about that file will be shown via
the ``filerevision`` template.
If ``path`` is not defined, information about the root directory will
be rendered.
"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if web.req.qsparams.get(b'style') == b'raw':
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 return rawfile(web)
Gregory Szorc
hgweb: remove one-off routing for file?style=raw...
r36888
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 path = webutil.cleanpath(web.repo, web.req.qsparams.get(b'file', b''))
Benoit Boissinot
hgweb: do not use unassigned variables in exception handling
r6853 if not path:
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 return manifest(web)
Benoit Boissinot
hgweb: do not use unassigned variables in exception handling
r6853 try:
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 return _filerevision(web, webutil.filectx(web.repo, web.req))
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.LookupError as inst:
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591 try:
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 return manifest(web)
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
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
hgweb: use templater on requestcontext instance...
r36900 def _search(web):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 MODE_REVISION = b'rev'
MODE_KEYWORD = b'keyword'
MODE_REVSET = b'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
Gregory Szorc
global: use pycompat.xrange()...
r38806 for i in pycompat.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:
Augie Fackler
formatting: blacken the codebase...
r43346 if not (
q in lower(ctx.user())
or q in lower(ctx.description())
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 or q in lower(b" ".join(ctx.files()))
Augie Fackler
formatting: blacken the codebase...
r43346 ):
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 = {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 MODE_REVISION: (revsearch, b'exact revision search'),
MODE_KEYWORD: (keywordsearch, b'literal keyword search'),
MODE_REVSET: (revsetsearch, b'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:
Martin von Zweigbergk
hgweb: use revsymbol() to determine if query is a revision...
r37405 ctx = scmutil.revsymbol(web.repo, query)
Alexander Plavin
hgweb: search() function supports direct pointing to revision...
r19633 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
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 revdef = b'reverse(%s)' % query
Alexander Plavin
hgweb: add revset syntax support to search...
r19722 try:
Yuya Nishihara
revset: split language services to revsetlang module (API)...
r31024 tree = revsetlang.parse(revdef)
Yuya Nishihara
hgweb: unify import style of error classes...
r27009 except error.ParseError:
Alexander Plavin
hgweb: add revset syntax support to search...
r19722 # can't parse to a revset tree
return MODE_KEYWORD, query
Yuya Nishihara
revset: split language services to revsetlang module (API)...
r31024 if revsetlang.depth(tree) <= 2:
Alexander Plavin
hgweb: add revset syntax support to search...
r19722 # no revset syntax used
return MODE_KEYWORD, query
Augie Fackler
formatting: blacken the codebase...
r43346 if any(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 (token, (value or b'')[:3]) == (b'string', b're:')
Augie Fackler
formatting: blacken the codebase...
r43346 for token, value, pos in revsetlang.tokenize(revdef)
):
Alexander Plavin
hgweb: add revset syntax support to search...
r19722 return MODE_KEYWORD, query
Yuya Nishihara
revset: split language services to revsetlang module (API)...
r31024 funcsused = revsetlang.funcsused(tree)
Alexander Plavin
hgweb: add revset syntax support to search...
r19722 if not funcsused.issubset(revset.safesymbols):
return MODE_KEYWORD, query
try:
Augie Fackler
formatting: blacken the codebase...
r43346 mfunc = revset.match(
web.repo.ui, revdef, lookup=revset.lookupfn(web.repo)
)
Yuya Nishihara
revset: make match function initiate query from full set by default...
r24114 revs = mfunc(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
Augie Fackler
formatting: blacken the codebase...
r43346 except (
error.ParseError,
error.RepoLookupError,
error.Abort,
LookupError,
):
Alexander Plavin
hgweb: add revset syntax support to search...
r19722 return MODE_KEYWORD, query
Yuya Nishihara
hgweb: fix search {entries} to not return results of template expansion...
r37418 def changelist(context):
Alexander Plavin
hgweb: separate search itself and template generation...
r19533 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
Yuya Nishihara
hgweb: use scmutil.binnode() to translate None to wdir hash (issue5988)...
r39830 n = scmutil.binnode(ctx)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 showtags = webutil.showtag(web.repo, b'changelogtag', n)
Yuya Nishihara
hgweb: remove unused argument 'tmpl' from listfilediffs()
r37973 files = webutil.listfilediffs(ctx.files(), n, web.maxfiles)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Yuya Nishihara
templater: use named function to expand template against mapping dict (API)...
r37037 lm = webutil.commonentry(web.repo, ctx)
Augie Fackler
formatting: blacken the codebase...
r43346 lm.update(
{
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'parity': next(parity),
b'changelogtag': showtags,
b'files': files,
Augie Fackler
formatting: blacken the codebase...
r43346 }
)
Yuya Nishihara
hgweb: fix search {entries} to not return results of template expansion...
r37418 yield lm
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Dirkjan Ochtman
hgweb: add less/more links for search logs (issue1972)
r10247 if count >= revcount:
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 break
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 query = web.req.qsparams[b'rev']
Alexander Plavin
hgweb: move local changelist function to the beginning of the parent one
r19418 revcount = web.maxchanges
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'revcount' in web.req.qsparams:
Isaac Jurado
hgweb: ignore non numeric "revcount" parameter values (issue4091)
r20092 try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 revcount = int(web.req.qsparams.get(b'revcount', revcount))
Isaac Jurado
hgweb: ignore non numeric "revcount" parameter values (issue4091)
r20092 revcount = max(revcount, 1)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 web.tmpl.defaults[b'sessionvars'][b'revcount'] = revcount
Isaac Jurado
hgweb: ignore non numeric "revcount" parameter values (issue4091)
r20092 except ValueError:
pass
Alexander Plavin
hgweb: move local changelist function to the beginning of the parent one
r19418
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 lessvars = copy.copy(web.tmpl.defaults[b'sessionvars'])
lessvars[b'revcount'] = max(revcount // 2, 1)
lessvars[b'rev'] = query
morevars = copy.copy(web.tmpl.defaults[b'sessionvars'])
morevars[b'revcount'] = revcount * 2
morevars[b'rev'] = query
Alexander Plavin
hgweb: move local changelist function to the beginning of the parent one
r19418
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
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'forcekw' in web.req.qsparams:
showforcekw = b''
Alexander Plavin
hgweb: add link to force literal keyword search...
r19768 showunforcekw = searchfuncs[mode][1]
mode = MODE_KEYWORD
funcarg = query
else:
if mode != MODE_KEYWORD:
showforcekw = searchfuncs[MODE_KEYWORD][1]
else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 showforcekw = b''
showunforcekw = b''
Alexander Plavin
hgweb: add link to force literal keyword search...
r19768
Alexander Plavin
hgweb: add dynamic search function selection, depending on the query...
r19631 searchfunc = searchfuncs[mode]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 tip = web.repo[b'tip']
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 parity = paritygen(web.stripecount)
Gregory Szorc
hgweb: add a sendtemplate() helper function...
r36899 return web.sendtemplate(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'search',
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 query=query,
node=tip.hex(),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 symrev=b'tip',
entries=templateutil.mappinggenerator(changelist, name=b'searchentry'),
archives=web.archivelist(b'tip'),
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 morevars=morevars,
lessvars=lessvars,
modedesc=searchfunc[1],
showforcekw=showforcekw,
Augie Fackler
formatting: blacken the codebase...
r43346 showunforcekw=showunforcekw,
)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @webcommand(b'changelog')
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 def changelog(web, shortlog=False):
Gregory Szorc
webcommands: document "changelog" web command
r24089 """
/changelog[/{revision}]
-----------------------
Show information about multiple changesets.
If the optional ``revision`` URL argument is absent, information about
all changesets starting at ``tip`` will be rendered. If the ``revision``
argument is present, changesets will be shown starting from the specified
revision.
If ``revision`` is absent, the ``rev`` query string argument may be
defined. This will perform a search for changesets.
The argument for ``rev`` can be a single revision, a revision set,
or a literal keyword to search for in changeset data (equivalent to
Wagner Bruna
webcommands: fix typo in changelog documentation
r24867 :hg:`log -k`).
Gregory Szorc
webcommands: document "changelog" web command
r24089
The ``revcount`` query string argument defines the maximum numbers of
changesets to render.
For non-searches, the ``changelog`` template will be rendered.
"""
Dirkjan Ochtman
hgweb: add less/more links for search logs (issue1972)
r10247
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 query = b''
if b'node' in web.req.qsparams:
Gregory Szorc
hgweb: pass modern request type into various webutil functions (API)...
r36902 ctx = webutil.changectx(web.repo, web.req)
symrev = webutil.symrevorshortnode(web.req, ctx)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif b'rev' in web.req.qsparams:
Gregory Szorc
hgweb: use templater on requestcontext instance...
r36900 return _search(web)
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ctx = web.repo[b'tip']
symrev = b'tip'
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Yuya Nishihara
hgweb: load revcount + 1 entries to fill nextentry in log page (issue5972)...
r39419 def changelist(maxcount):
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)
Gregory Szorc
hgweb: extract changelist entry generation into own function...
r23745
Yuya Nishihara
hgweb: load revcount + 1 entries to fill nextentry in log page (issue5972)...
r39419 for entry in webutil.changelistentries(web, revs, maxcount, parity):
Gregory Szorc
hgweb: extract changelist entry generation into own function...
r23745 yield entry
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Jordi Gutiérrez Hermoso
style: kill ersatz if-else ternary operators...
r24306 if shortlog:
revcount = web.maxshortchanges
else:
revcount = web.maxchanges
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'revcount' in web.req.qsparams:
Isaac Jurado
hgweb: ignore non numeric "revcount" parameter values (issue4091)
r20092 try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 revcount = int(web.req.qsparams.get(b'revcount', revcount))
Isaac Jurado
hgweb: ignore non numeric "revcount" parameter values (issue4091)
r20092 revcount = max(revcount, 1)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 web.tmpl.defaults[b'sessionvars'][b'revcount'] = revcount
Isaac Jurado
hgweb: ignore non numeric "revcount" parameter values (issue4091)
r20092 except ValueError:
pass
Dirkjan Ochtman
hgweb: add less/more links to shortlog/filelog nav
r10246
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 lessvars = copy.copy(web.tmpl.defaults[b'sessionvars'])
lessvars[b'revcount'] = max(revcount // 2, 1)
morevars = copy.copy(web.tmpl.defaults[b'sessionvars'])
morevars[b'revcount'] = revcount * 2
Dirkjan Ochtman
hgweb: add less/more links to shortlog/filelog nav
r10246
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
Yuya Nishihara
hgweb: load revcount + 1 entries to fill nextentry in log page (issue5972)...
r39419 entries = list(changelist(revcount + 1))
Alexander Plavin
hgweb: always compute all entries and latestentry in changelog...
r19737 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
Gregory Szorc
hgweb: add a sendtemplate() helper function...
r36899 return web.sendtemplate(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'shortlog' if shortlog else b'changelog',
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 changenav=changenav,
node=ctx.hex(),
rev=pos,
symrev=symrev,
changesets=count,
Yuya Nishihara
hgweb: wrap {entries}* of changelog with mappinglist...
r38072 entries=templateutil.mappinglist(entries),
latestentry=templateutil.mappinglist(latestentry),
nextentry=templateutil.mappinglist(nextentry),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 archives=web.archivelist(b'tip'),
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 revcount=revcount,
morevars=morevars,
lessvars=lessvars,
Augie Fackler
formatting: blacken the codebase...
r43346 query=query,
)
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @webcommand(b'shortlog')
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 def shortlog(web):
Gregory Szorc
webcommands: document "shortlog" web command
r24086 """
/shortlog
---------
Show basic information about a set of changesets.
This accepts the same parameters as the ``changelog`` handler. The only
difference is the ``shortlog`` template will be rendered instead of the
``changelog`` template.
"""
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 return changelog(web, shortlog=True)
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @webcommand(b'changeset')
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 def changeset(web):
Gregory Szorc
webcommands: document "changeset" web command
r24085 """
/changeset[/{revision}]
-----------------------
Show information about a single changeset.
A URL path argument is the changeset identifier to show. See ``hg help
revisions`` for possible values. If not defined, the ``tip`` changeset
will be shown.
The ``changeset`` template is rendered. Contents of the ``changesettag``,
``changesetbookmark``, ``filenodelink``, ``filenolink``, and the many
templates related to diffs may all be used to produce the output.
"""
Gregory Szorc
hgweb: pass modern request type into various webutil functions (API)...
r36902 ctx = webutil.changectx(web.repo, web.req)
Gregory Szorc
hgweb: add a sendtemplate() helper function...
r36899
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return web.sendtemplate(b'changeset', **webutil.changesetentry(web, ctx))
Augie Fackler
formatting: blacken the codebase...
r43346
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 rev = webcommand(b'rev')(changeset)
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Augie Fackler
formatting: blacken the codebase...
r43346
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
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @webcommand(b'manifest')
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 def manifest(web):
Gregory Szorc
webcommands: document "manifest" web command
r24090 """
/manifest[/{revision}[/{path}]]
-------------------------------
Show information about a directory.
Wagner Bruna
webcommands: fix description of manifest default behavior
r24868 If the URL path arguments are omitted, information about the root
Gregory Szorc
webcommands: document "manifest" web command
r24090 directory for the ``tip`` changeset will be shown.
Because this handler can only show information for directories, it
is recommended to use the ``file`` handler instead, as it can handle both
directories and files.
The ``manifest`` template will be rendered for this handler.
"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'node' in web.req.qsparams:
Gregory Szorc
hgweb: pass modern request type into various webutil functions (API)...
r36902 ctx = webutil.changectx(web.repo, web.req)
symrev = webutil.symrevorshortnode(web.req, ctx)
av6
hgweb: provide symrev (symbolic revision) property to the templates...
r25602 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ctx = web.repo[b'tip']
symrev = b'tip'
path = webutil.cleanpath(web.repo, web.req.qsparams.get(b'file', b''))
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 mf = ctx.manifest()
Yuya Nishihara
hgweb: use scmutil.binnode() to translate None to wdir hash (issue5988)...
r39830 node = scmutil.binnode(ctx)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
files = {}
Ry4an Brase
hgweb: descend empty directories in web view...
r7305 dirs = {}
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 parity = paritygen(web.stripecount)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if path and path[-1:] != b"/":
path += b"/"
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 l = len(path)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 abspath = b"/" + path
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for full, n in pycompat.iteritems(mf):
Martin Geisler
hgweb: add hook for remapping repository path into virtual paths...
r16448 # 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:]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elements = remain.split(b'/')
Ry4an Brase
hgweb: descend empty directories in web view...
r7305 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:
Augie Fackler
formatting: blacken the codebase...
r43346 h = dirs # need to retain ref to dirs (root)
Ry4an Brase
hgweb: descend empty directories in web view...
r7305 for elem in elements[0:-1]:
if elem not in h:
h[elem] = {}
h = h[elem]
if len(h) > 1:
break
Augie Fackler
formatting: blacken the codebase...
r43346 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:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise ErrorResponse(HTTP_NOT_FOUND, b'path not found: ' + path)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Yuya Nishihara
hgweb: wrap {fentries} and {dentries} of manifest with mappinggenerator...
r38073 def filelist(context):
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)
Augie Fackler
formatting: blacken the codebase...
r43346 yield {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"file": full,
b"parity": next(parity),
b"basename": f,
b"date": fctx.date(),
b"size": fctx.size(),
b"permissions": mf.flags(full),
Augie Fackler
formatting: blacken the codebase...
r43346 }
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Yuya Nishihara
hgweb: wrap {fentries} and {dentries} of manifest with mappinggenerator...
r38073 def dirlist(context):
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:
Augie Fackler
webcommands: unpack contents of length-1 dict portably...
r36288 k, v = next(iter(h.items()))
Ry4an Brase
hgweb: descend empty directories in web view...
r7305 if v:
emptydirs.append(k)
h = v
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 path = b"%s%s" % (abspath, d)
Augie Fackler
formatting: blacken the codebase...
r43346 yield {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"parity": next(parity),
b"path": path,
b"emptydirs": b"/".join(emptydirs),
b"basename": d,
Augie Fackler
formatting: blacken the codebase...
r43346 }
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Gregory Szorc
hgweb: add a sendtemplate() helper function...
r36899 return web.sendtemplate(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'manifest',
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 symrev=symrev,
path=abspath,
up=webutil.up(abspath),
upparity=next(parity),
Yuya Nishihara
hgweb: wrap {fentries} and {dentries} of manifest with mappinggenerator...
r38073 fentries=templateutil.mappinggenerator(filelist),
dentries=templateutil.mappinggenerator(dirlist),
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 archives=web.archivelist(hex(node)),
Augie Fackler
formatting: blacken the codebase...
r43346 **pycompat.strkwargs(webutil.commonentry(web.repo, ctx))
)
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @webcommand(b'tags')
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 def tags(web):
Gregory Szorc
webcommands: document "tags" web command
r24084 """
/tags
-----
Show information about tags.
No arguments are accepted.
The ``tags`` template is rendered.
"""
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)
Yuya Nishihara
hgweb: wrap {entries}* of tags with mappinggenerator...
r38074 def entries(context, notip, latestonly):
Pierre-Yves David
hgweb: `limit` argument is actually `latestonly` renames and enforce...
r18402 t = i
if notip:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 t = [(k, n) for k, n in i if k != b"tip"]
Pierre-Yves David
hgweb: `limit` argument is actually `latestonly` renames and enforce...
r18402 if latestonly:
t = t[:1]
for k, n in t:
Augie Fackler
formatting: blacken the codebase...
r43346 yield {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"parity": next(parity),
b"tag": k,
b"date": web.repo[n].date(),
b"node": hex(n),
Augie Fackler
formatting: blacken the codebase...
r43346 }
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Gregory Szorc
hgweb: add a sendtemplate() helper function...
r36899 return web.sendtemplate(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'tags',
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 node=hex(web.repo.changelog.tip()),
Yuya Nishihara
hgweb: wrap {entries}* of tags with mappinggenerator...
r38074 entries=templateutil.mappinggenerator(entries, args=(False, False)),
Augie Fackler
formatting: blacken the codebase...
r43346 entriesnotip=templateutil.mappinggenerator(entries, args=(True, False)),
latestentry=templateutil.mappinggenerator(entries, args=(True, True)),
)
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @webcommand(b'bookmarks')
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 def bookmarks(web):
Gregory Szorc
webcommands: document "bookmarks" web command
r24083 """
/bookmarks
----------
Show information about bookmarks.
No arguments are accepted.
The ``bookmarks`` template is rendered.
"""
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]
av6
hgweb: sort bookmarks in revlog order of their nodes...
r28711 sortkey = lambda b: (web.repo[b[1]].rev(), b[0])
i = sorted(i, key=sortkey, reverse=True)
Alexander Solovyov
hgweb: add separate page with bookmarks listing
r13597 parity = paritygen(web.stripecount)
Yuya Nishihara
hgweb: wrap {entries}* of bookmarks with mappinggenerator...
r38149 def entries(context, latestonly):
av6
hgweb: sort bookmarks early...
r28710 t = i
Pierre-Yves David
hgweb: `limit` argument is actually `latestonly` renames and enforce...
r18402 if latestonly:
av6
hgweb: sort bookmarks early...
r28710 t = i[:1]
Pierre-Yves David
hgweb: `limit` argument is actually `latestonly` renames and enforce...
r18402 for k, n in t:
Augie Fackler
formatting: blacken the codebase...
r43346 yield {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"parity": next(parity),
b"bookmark": k,
b"date": web.repo[n].date(),
b"node": hex(n),
Augie Fackler
formatting: blacken the codebase...
r43346 }
Alexander Solovyov
hgweb: add separate page with bookmarks listing
r13597
av6
hgweb: generate last change date for an empty atom-bookmarks feed (issue5022)...
r28712 if i:
latestrev = i[0][1]
else:
latestrev = -1
Yuya Nishihara
hgweb: wrap {lastchange} of bookmarks with mappinglist...
r38150 lastdate = web.repo[latestrev].date()
av6
hgweb: generate last change date for an empty atom-bookmarks feed (issue5022)...
r28712
Gregory Szorc
hgweb: add a sendtemplate() helper function...
r36899 return web.sendtemplate(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'bookmarks',
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 node=hex(web.repo.changelog.tip()),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 lastchange=templateutil.mappinglist([{b'date': lastdate}]),
Yuya Nishihara
hgweb: wrap {entries}* of bookmarks with mappinggenerator...
r38149 entries=templateutil.mappinggenerator(entries, args=(False,)),
Augie Fackler
formatting: blacken the codebase...
r43346 latestentry=templateutil.mappinggenerator(entries, args=(True,)),
)
Alexander Solovyov
hgweb: add separate page with bookmarks listing
r13597
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @webcommand(b'branches')
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 def branches(web):
Gregory Szorc
webcommands: document "branches" web command
r24082 """
/branches
---------
Show information about branches.
All known branches are contained in the output, even closed branches.
No arguments are accepted.
The ``branches`` template is rendered.
"""
av6
hgweb: move branchentries code from webcommands to webutil
r26129 entries = webutil.branchentries(web.repo, web.stripecount)
latestentry = webutil.branchentries(web.repo, web.stripecount, 1)
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887
Gregory Szorc
hgweb: add a sendtemplate() helper function...
r36899 return web.sendtemplate(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'branches',
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 node=hex(web.repo.changelog.tip()),
entries=entries,
Augie Fackler
formatting: blacken the codebase...
r43346 latestentry=latestentry,
)
Sune Foldager
webcommands: add 'branches' command, similar to 'tags'
r8352
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @webcommand(b'summary')
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 def summary(web):
Gregory Szorc
webcommands: document "summary" web command
r24091 """
/summary
--------
Show a summary of repository state.
Information about the latest changesets, bookmarks, tags, and branches
is captured by this handler.
The ``summary`` template is rendered.
"""
Patrick Mezard
webcommands: do not modify repo.tagslist()...
r17261 i = reversed(web.repo.tagslist())
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Yuya Nishihara
hgweb: fix summary {tags} and {shortlog} to not forcibly expand template...
r37419 def tagentries(context):
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 parity = paritygen(web.stripecount)
count = 0
for k, n in i:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if k == b"tip": # skip tip
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 continue
Andrew Beekhof
webcommands: fix increments lost by 894875eae49b
r6659 count += 1
Augie Fackler
formatting: blacken the codebase...
r43346 if count > 10: # limit to 10 tags
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 break
Yuya Nishihara
hgweb: fix summary {tags} and {shortlog} to not forcibly expand template...
r37419 yield {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'parity': next(parity),
b'tag': k,
b'node': hex(n),
b'date': web.repo[n].date(),
Yuya Nishihara
hgweb: fix summary {tags} and {shortlog} to not forcibly expand template...
r37419 }
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Yuya Nishihara
hgweb: wrap {bookmarks} of summary with mappinggenerator...
r38151 def bookmarks(context):
Yuya Nishihara
hgweb: add bookmarks listing to summary page of gitweb/monoblue styles
r13924 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]
av6
hgweb: sort bookmarks in revlog order of their nodes...
r28711 sortkey = lambda b: (web.repo[b[1]].rev(), b[0])
marks = sorted(marks, key=sortkey, reverse=True)
for k, n in marks[:10]: # limit to 10 bookmarks
Augie Fackler
formatting: blacken the codebase...
r43346 yield {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'parity': next(parity),
b'bookmark': k,
b'date': web.repo[n].date(),
b'node': hex(n),
Augie Fackler
formatting: blacken the codebase...
r43346 }
Yuya Nishihara
hgweb: add bookmarks listing to summary page of gitweb/monoblue styles
r13924
Yuya Nishihara
hgweb: fix summary {tags} and {shortlog} to not forcibly expand template...
r37419 def changelist(context):
Matt Mackall
many, many trivial check-code fixups
r10282 parity = paritygen(web.stripecount, offset=start - end)
Augie Fackler
formatting: blacken the codebase...
r43346 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]
Yuya Nishihara
templater: use named function to expand template against mapping dict (API)...
r37037 lm = webutil.commonentry(web.repo, ctx)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 lm[b'parity'] = next(parity)
Yuya Nishihara
hgweb: fix summary {tags} and {shortlog} to not forcibly expand template...
r37419 l.append(lm)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Laura Médioni
templates: add support for summary webcommand in json style...
r29382 for entry in reversed(l):
yield entry
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 tip = web.repo[b'tip']
Patrick Mezard
webcommands: remove unncessary access to repo.changelog...
r12059 count = len(web.repo)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 start = max(0, count - web.maxchanges)
end = min(count, start + web.maxchanges)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 desc = web.config(b"web", b"description")
Boris Feld
configitems: register the 'web.description' config
r34235 if not desc:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 desc = b'unknown'
labels = web.configlist(b'web', b'labels')
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887
Gregory Szorc
hgweb: add a sendtemplate() helper function...
r36899 return web.sendtemplate(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'summary',
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 desc=desc,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 owner=get_contact(web.config) or b'unknown',
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 lastchange=tip.date(),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 tags=templateutil.mappinggenerator(tagentries, name=b'tagentry'),
Yuya Nishihara
hgweb: wrap {bookmarks} of summary with mappinggenerator...
r38151 bookmarks=templateutil.mappinggenerator(bookmarks),
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 branches=webutil.branchentries(web.repo, web.stripecount, 10),
Augie Fackler
formatting: blacken the codebase...
r43346 shortlog=templateutil.mappinggenerator(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 changelist, name=b'shortlogentry'
Augie Fackler
formatting: blacken the codebase...
r43346 ),
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 node=tip.hex(),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 symrev=b'tip',
archives=web.archivelist(b'tip'),
labels=templateutil.hybridlist(labels, name=b'label'),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @webcommand(b'filediff')
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 def filediff(web):
Gregory Szorc
webcommands: document "filediff" web command
r24092 """
/diff/{revision}/{path}
-----------------------
Show how a file changed in a particular commit.
The ``filediff`` template is rendered.
Mads Kiilerich
spelling: trivial spell checking
r26781 This handler is registered under both the ``/diff`` and ``/filediff``
Gregory Szorc
webcommands: document "filediff" web command
r24092 paths. ``/diff`` is used in modern code.
"""
Dirkjan Ochtman
hgweb: working diff for removed files
r7183 fctx, ctx = None, None
try:
Gregory Szorc
hgweb: pass modern request type into various webutil functions (API)...
r36902 fctx = webutil.filectx(web.repo, web.req)
Benoit Boissinot
remove unused variables
r7280 except LookupError:
Gregory Szorc
hgweb: pass modern request type into various webutil functions (API)...
r36902 ctx = webutil.changectx(web.repo, web.req)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 path = webutil.cleanpath(web.repo, web.req.qsparams[b'file'])
Dirkjan Ochtman
hgweb: working diff for removed files
r7183 if path not in ctx.files():
raise
if fctx is not None:
path = fctx.path()
Matt Mackall
hgweb: fix filediff base calculation...
r16722 ctx = fctx.changectx()
Denis Laxalde
hgweb: explictly pass basectx in webutil.diffs...
r31082 basectx = ctx.p1()
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 style = web.config(b'web', b'style')
if b'style' in web.req.qsparams:
style = web.req.qsparams[b'style']
Dirkjan Ochtman
hgweb: show diff header line in raw diffs
r9402
Gregory Szorc
hgweb: don't redundantly pass templater with requestcontext (API)...
r36901 diffs = webutil.diffs(web, ctx, basectx, [path], style)
av6
webcommands: test that fctx is not None in filediff()...
r27160 if fctx is not None:
Jordi Gutiérrez Hermoso
style: kill ersatz if-else ternary operators...
r24306 rename = webutil.renamelink(fctx)
ctx = fctx
else:
Yuya Nishihara
hgweb: wrap {rename} with mappinglist...
r37921 rename = templateutil.mappinglist([])
Jordi Gutiérrez Hermoso
style: kill ersatz if-else ternary operators...
r24306 ctx = ctx
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887
Gregory Szorc
hgweb: add a sendtemplate() helper function...
r36899 return web.sendtemplate(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'filediff',
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 file=path,
Gregory Szorc
hgweb: pass modern request type into various webutil functions (API)...
r36902 symrev=webutil.symrevorshortnode(web.req, ctx),
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 rename=rename,
diff=diffs,
Augie Fackler
formatting: blacken the codebase...
r43346 **pycompat.strkwargs(webutil.commonentry(web.repo, ctx))
)
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 diff = webcommand(b'diff')(filediff)
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @webcommand(b'comparison')
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 def comparison(web):
Gregory Szorc
webcommands: document "comparison" web command
r24093 """
/comparison/{revision}/{path}
-----------------------------
Show a comparison between the old and new versions of a file from changes
made on a particular revision.
This is similar to the ``diff`` handler. However, this form features
a split or side-by-side diff rather than a unified diff.
The ``context`` query string argument can be used to control the lines of
context in the diff.
The ``filecomparison`` template is rendered.
"""
Gregory Szorc
hgweb: pass modern request type into various webutil functions (API)...
r36902 ctx = webutil.changectx(web.repo, web.req)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'file' not in web.req.qsparams:
raise ErrorResponse(HTTP_NOT_FOUND, b'file not given')
path = webutil.cleanpath(web.repo, web.req.qsparams[b'file'])
wujek srujek
hgweb: side-by-side comparison functionality...
r17202
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 parsecontext = lambda v: v == b'full' and -1 or int(v)
if b'context' in web.req.qsparams:
context = parsecontext(web.req.qsparams[b'context'])
wujek srujek
hgweb: side-by-side comparison functionality...
r17202 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 context = parsecontext(web.config(b'web', b'comparisoncontext'))
wujek srujek
hgweb: side-by-side comparison functionality...
r17202
wujek srujek
hgweb: fixes traceback for invalid files by removing top-level template...
r17302 def filelines(f):
Jun Wu
webcommands: use fctx.isbinary
r32136 if f.isbinary():
Gregory Szorc
py3: pass str and return bytes from mimetypes.guess_type()...
r40194 mt = pycompat.sysbytes(
mimetypes.guess_type(pycompat.fsdecode(f.path()))[0]
Augie Fackler
formatting: blacken the codebase...
r43346 or r'application/octet-stream'
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return [_(b'(binary file %s, hash: %s)') % (mt, hex(f.filenode()))]
wujek srujek
hgweb: fixes traceback for invalid files by removing top-level template...
r17302 return f.data().splitlines()
av6
webcommands: get correct parents when comparing a removed file (issue4962)...
r27158 fctx = None
FUJIWARA Katsunori
hgweb: show revisions and hashes gotten from changelog in "comparison" page...
r21123 parent = ctx.p1()
leftrev = parent.rev()
leftnode = parent.node()
rightrev = ctx.rev()
Yuya Nishihara
hgweb: use scmutil.binnode() to translate None to wdir hash (issue5988)...
r39830 rightnode = scmutil.binnode(ctx)
wujek srujek
hgweb: fixes traceback for invalid files by removing top-level template...
r17302 if path in ctx:
fctx = ctx[path]
rightlines = filelines(fctx)
FUJIWARA Katsunori
hgweb: make "comparison" get parent from not filelog but changelog...
r21121 if path not in parent:
wujek srujek
hgweb: fixes traceback for invalid files by removing top-level template...
r17302 leftlines = ()
else:
FUJIWARA Katsunori
hgweb: make "comparison" get parent from not filelog but changelog...
r21121 pfctx = parent[path]
wujek srujek
hgweb: fixes traceback for invalid files by removing top-level template...
r17302 leftlines = filelines(pfctx)
else:
rightlines = ()
Martin von Zweigbergk
cleanup: use p1() and p2() instead of parents()[0] and parents()[1]...
r41442 pfctx = ctx.p1()[path]
av6
webcommands: get correct parents when comparing a removed file (issue4962)...
r27158 leftlines = filelines(pfctx)
wujek srujek
hgweb: fixes traceback for invalid files by removing top-level template...
r17302
Yuya Nishihara
hgweb: drop unused argument 'tmpl' from webutil.compare()
r38013 comparison = webutil.compare(context, leftlines, rightlines)
av6
webcommands: get correct parents when comparing a removed file (issue4962)...
r27158 if fctx is not None:
av6
webcommands: stop using ersatz if-else ternary operator for rename variable...
r27159 rename = webutil.renamelink(fctx)
av6
webcommands: get correct parents when comparing a removed file (issue4962)...
r27158 ctx = fctx
else:
Yuya Nishihara
hgweb: wrap {rename} with mappinglist...
r37921 rename = templateutil.mappinglist([])
av6
webcommands: get correct parents when comparing a removed file (issue4962)...
r27158 ctx = ctx
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887
Gregory Szorc
hgweb: add a sendtemplate() helper function...
r36899 return web.sendtemplate(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'filecomparison',
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 file=path,
Gregory Szorc
hgweb: pass modern request type into various webutil functions (API)...
r36902 symrev=webutil.symrevorshortnode(web.req, ctx),
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 rename=rename,
leftrev=leftrev,
leftnode=hex(leftnode),
rightrev=rightrev,
rightnode=hex(rightnode),
comparison=comparison,
Augie Fackler
formatting: blacken the codebase...
r43346 **pycompat.strkwargs(webutil.commonentry(web.repo, ctx))
)
wujek srujek
hgweb: side-by-side comparison functionality...
r17202
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @webcommand(b'annotate')
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 def annotate(web):
Gregory Szorc
webcommands: document "annotate" web command
r24094 """
/annotate/{revision}/{path}
---------------------------
Show changeset information for each line in a file.
Gregory Szorc
hgweb: query string arguments to control whitespace for annotate...
r34391 The ``ignorews``, ``ignorewsamount``, ``ignorewseol``, and
``ignoreblanklines`` query string arguments have the same meaning as
Gregory Szorc
hgweb: use parsebool for parsing diff query string options...
r34404 their ``[annotate]`` config equivalents. It uses the hgrc boolean
parsing logic to interpret the value. e.g. ``0`` and ``false`` are
false and ``1`` and ``true`` are true. If not defined, the server
default settings are used.
Gregory Szorc
hgweb: query string arguments to control whitespace for annotate...
r34391
Gregory Szorc
webcommands: document "annotate" web command
r24094 The ``fileannotate`` template is rendered.
"""
Gregory Szorc
hgweb: pass modern request type into various webutil functions (API)...
r36902 fctx = webutil.filectx(web.repo, web.req)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 f = fctx.path()
parity = paritygen(web.stripecount)
Gregory Szorc
hgweb: use heads() instead of headrevs()...
r39820 ishead = fctx.filenode() in fctx.filelog().heads()
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Gregory Szorc
hgweb: cache fctx.parents() in annotate command (issue5414)...
r30298 # parents() is called once per line and several lines likely belong to
# same revision. So it is worth caching.
# TODO there are still redundant operations within basefilectx.parents()
# and from the fctx.annotate() call itself that could be cached.
parentscache = {}
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
hgweb: wrap {parents} of {annotate} with mappinggenerator...
r38153 def parents(context, f):
Gregory Szorc
hgweb: cache fctx.parents() in annotate command (issue5414)...
r30298 rev = f.rev()
if rev not in parentscache:
parentscache[rev] = []
for p in f.parents():
entry = {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'node': p.hex(),
b'rev': p.rev(),
Gregory Szorc
hgweb: cache fctx.parents() in annotate command (issue5414)...
r30298 }
parentscache[rev].append(entry)
for p in parentscache[rev]:
yield p
Denis Laxalde
hgweb: add link to parents of annotated revision in annotate view...
r29522
Yuya Nishihara
hgweb: wrap {annotate} with mappinggenerator...
r38152 def annotate(context):
Jun Wu
webcommands: use fctx.isbinary
r32136 if fctx.isbinary():
Gregory Szorc
py3: pass str and return bytes from mimetypes.guess_type()...
r40194 mt = pycompat.sysbytes(
mimetypes.guess_type(pycompat.fsdecode(fctx.path()))[0]
Augie Fackler
formatting: blacken the codebase...
r43346 or r'application/octet-stream'
)
lines = [
dagop.annotateline(
fctx=fctx.filectx(fctx.filerev()),
lineno=1,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 text=b'(binary:%s)' % mt,
Augie Fackler
formatting: blacken the codebase...
r43346 )
]
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 else:
Gregory Szorc
hgweb: pass modern request type into various webutil functions (API)...
r36902 lines = webutil.annotate(web.req, fctx, web.repo.ui)
Jun Wu
hgweb: make fctx.annotate a separated function so it could be wrapped...
r30081
Denis Laxalde
hgweb: display blamed revision once per block in annotate view...
r29388 previousrev = None
av6
paper: make different blocks of annotated lines have different colors
r29572 blockparitygen = paritygen(1)
Yuya Nishihara
annotate: pack line content into annotateline object (API)...
r37084 for lineno, aline in enumerate(lines):
Siddharth Agarwal
annotate: introduce attr for storing per-line annotate data...
r34433 f = aline.fctx
Denis Laxalde
hgweb: display blamed revision once per block in annotate view...
r29388 rev = f.rev()
av6
paper: make different blocks of annotated lines have different colors
r29572 if rev != previousrev:
blockhead = True
blockparity = next(blockparitygen)
else:
blockhead = None
Denis Laxalde
hgweb: display blamed revision once per block in annotate view...
r29388 previousrev = rev
Augie Fackler
formatting: blacken the codebase...
r43346 yield {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"parity": next(parity),
b"node": f.hex(),
b"rev": rev,
b"author": f.user(),
b"parents": templateutil.mappinggenerator(parents, args=(f,)),
b"desc": f.description(),
b"extra": f.extra(),
b"file": f.path(),
b"blockhead": blockhead,
b"blockparity": blockparity,
b"targetline": aline.lineno,
b"line": aline.text,
b"lineno": lineno + 1,
b"lineid": b"l%d" % (lineno + 1),
b"linenumber": b"% 6d" % (lineno + 1),
b"revdate": f.date(),
Augie Fackler
formatting: blacken the codebase...
r43346 }
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 diffopts = webutil.difffeatureopts(web.req, web.repo.ui, b'annotate')
Gregory Szorc
hgweb: add HTML elements to control whitespace settings for annotate...
r34392 diffopts = {k: getattr(diffopts, k) for k in diffopts.defaults}
Gregory Szorc
hgweb: add a sendtemplate() helper function...
r36899 return web.sendtemplate(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'fileannotate',
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 file=f,
Yuya Nishihara
hgweb: wrap {annotate} with mappinggenerator...
r38152 annotate=templateutil.mappinggenerator(annotate),
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 path=webutil.up(f),
Gregory Szorc
hgweb: pass modern request type into various webutil functions (API)...
r36902 symrev=webutil.symrevorshortnode(web.req, fctx),
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 rename=webutil.renamelink(fctx),
permissions=fctx.manifest().flags(f),
ishead=int(ishead),
Yuya Nishihara
hgweb: wrap {diffopts} of annotate by hybriddict()...
r38154 diffopts=templateutil.hybriddict(diffopts),
Augie Fackler
formatting: blacken the codebase...
r43346 **pycompat.strkwargs(webutil.commonentry(web.repo, fctx))
)
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @webcommand(b'filelog')
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 def filelog(web):
Gregory Szorc
webcommands: document "filelog" web command
r24095 """
/filelog/{revision}/{path}
--------------------------
Show information about the history of a file in the repository.
The ``revcount`` query string argument can be defined to control the
maximum number of entries to show.
The ``filelog`` template will be rendered.
"""
Dirkjan Ochtman
hgweb: conditionally show file logs for deleted files
r7300
try:
Gregory Szorc
hgweb: pass modern request type into various webutil functions (API)...
r36902 fctx = webutil.filectx(web.repo, web.req)
Dirkjan Ochtman
hgweb: conditionally show file logs for deleted files
r7300 f = fctx.path()
fl = fctx.filelog()
Matt Mackall
errors: move revlog errors...
r7633 except error.LookupError:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f = webutil.cleanpath(web.repo, web.req.qsparams[b'file'])
Dirkjan Ochtman
hgweb: conditionally show file logs for deleted files
r7300 fl = web.repo.file(f)
numrevs = len(fl)
Augie Fackler
formatting: blacken the codebase...
r43346 if not numrevs: # file doesn't exist at all
Dirkjan Ochtman
hgweb: conditionally show file logs for deleted files
r7300 raise
Gregory Szorc
hgweb: pass modern request type into various webutil functions (API)...
r36902 rev = webutil.changectx(web.repo, web.req).rev()
Matt Mackall
linkrev: take a revision number rather than a hash
r7361 first = fl.linkrev(0)
Augie Fackler
formatting: blacken the codebase...
r43346 if rev < first: # current rev is from before file existed
Dirkjan Ochtman
hgweb: conditionally show file logs for deleted files
r7300 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
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'revcount' in web.req.qsparams:
Isaac Jurado
hgweb: ignore non numeric "revcount" parameter values (issue4091)
r20092 try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 revcount = int(web.req.qsparams.get(b'revcount', revcount))
Isaac Jurado
hgweb: ignore non numeric "revcount" parameter values (issue4091)
r20092 revcount = max(revcount, 1)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 web.tmpl.defaults[b'sessionvars'][b'revcount'] = revcount
Isaac Jurado
hgweb: ignore non numeric "revcount" parameter values (issue4091)
r20092 except ValueError:
pass
Dirkjan Ochtman
hgweb: add less/more links to shortlog/filelog nav
r10246
Gregory Szorc
hgweb: pass modern request type into various webutil functions (API)...
r36902 lrange = webutil.linerange(web.req)
Denis Laxalde
hgweb: handle a "linerange" request parameter in filelog command...
r31665
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 lessvars = copy.copy(web.tmpl.defaults[b'sessionvars'])
lessvars[b'revcount'] = max(revcount // 2, 1)
morevars = copy.copy(web.tmpl.defaults[b'sessionvars'])
morevars[b'revcount'] = revcount * 2
Dirkjan Ochtman
hgweb: add less/more links to shortlog/filelog nav
r10246
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 patch = b'patch' in web.req.qsparams
Denis Laxalde
hgweb: add a "patch" query parameter to filelog command...
r31661 if patch:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 lessvars[b'patch'] = morevars[b'patch'] = web.req.qsparams[b'patch']
descend = b'descend' in web.req.qsparams
Denis Laxalde
hgweb: handle a "descend" query parameter in filelog command...
r31939 if descend:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 lessvars[b'descend'] = morevars[b'descend'] = web.req.qsparams[
b'descend'
]
Denis Laxalde
hgweb: add a "patch" query parameter to filelog command...
r31661
Dirkjan Ochtman
hgweb: conditionally show file logs for deleted files
r7300 count = fctx.filerev() + 1
Augie Fackler
formatting: blacken the codebase...
r43346 start = max(0, count - revcount) # first rev on this page
end = min(count, start + revcount) # last rev on this page
Denis Laxalde
hgweb: restore ascending iteration on revs in filelog web command...
r30825 parity = paritygen(web.stripecount, offset=start - end)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Denis Laxalde
hgweb: build the "entries" list directly in filelog command...
r30816 repo = web.repo
Martin von Zweigbergk
hgweb: don't include hidden revisions in /filelog/ view...
r37381 filelog = fctx.filelog()
Augie Fackler
formatting: blacken the codebase...
r43346 revs = [
filerev
for filerev in filelog.revs(start, end - 1)
if filelog.linkrev(filerev) in repo
]
Denis Laxalde
hgweb: build the "entries" list directly in filelog command...
r30816 entries = []
Denis Laxalde
hgweb: add a "patch" query parameter to filelog command...
r31661
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 diffstyle = web.config(b'web', b'style')
if b'style' in web.req.qsparams:
diffstyle = web.req.qsparams[b'style']
Denis Laxalde
hgweb: add a "patch" query parameter to filelog command...
r31661
Denis Laxalde
hgweb: filter diff hunks when 'linerange' and 'patch' are specified in filelog
r31667 def diff(fctx, linerange=None):
Denis Laxalde
hgweb: add a "patch" query parameter to filelog command...
r31661 ctx = fctx.changectx()
basectx = ctx.p1()
path = fctx.path()
Augie Fackler
formatting: blacken the codebase...
r43346 return webutil.diffs(
web,
ctx,
basectx,
[path],
diffstyle,
linerange=linerange,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 lineidprefix=b'%s-' % ctx.hex()[:12],
Augie Fackler
formatting: blacken the codebase...
r43346 )
Denis Laxalde
hgweb: add a "patch" query parameter to filelog command...
r31661
Denis Laxalde
hgweb: handle a "linerange" request parameter in filelog command...
r31665 linerange = None
if lrange is not None:
linerange = webutil.formatlinerange(*lrange)
# deactivate numeric nav links when linerange is specified as this
# would required a dedicated "revnav" class
Yuya Nishihara
hgweb: wrap {changenav} and {nav} with mappinglist
r37716 nav = templateutil.mappinglist([])
Denis Laxalde
hgweb: handle a "descend" query parameter in filelog command...
r31939 if descend:
Yuya Nishihara
dagop: move blockancestors() and blockdescendants() from context...
r32904 it = dagop.blockdescendants(fctx, *lrange)
Denis Laxalde
hgweb: handle a "descend" query parameter in filelog command...
r31939 else:
Yuya Nishihara
dagop: move blockancestors() and blockdescendants() from context...
r32904 it = dagop.blockancestors(fctx, *lrange)
Denis Laxalde
hgweb: handle a "descend" query parameter in filelog command...
r31939 for i, (c, lr) in enumerate(it, 1):
Denis Laxalde
hgweb: handle a "linerange" request parameter in filelog command...
r31665 diffs = None
if patch:
Denis Laxalde
hgweb: filter diff hunks when 'linerange' and 'patch' are specified in filelog
r31667 diffs = diff(c, linerange=lr)
Denis Laxalde
hgweb: handle a "linerange" request parameter in filelog command...
r31665 # follow renames accross filtered (not in range) revisions
path = c.path()
Yuya Nishihara
hgweb: don't use dict(key=value) to build a mapping dict in filelog...
r38155 lm = webutil.commonentry(repo, c)
Augie Fackler
formatting: blacken the codebase...
r43346 lm.update(
{
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'parity': next(parity),
b'filerev': c.rev(),
b'file': path,
b'diff': diffs,
b'linerange': webutil.formatlinerange(*lr),
b'rename': templateutil.mappinglist([]),
Augie Fackler
formatting: blacken the codebase...
r43346 }
)
Yuya Nishihara
hgweb: don't use dict(key=value) to build a mapping dict in filelog...
r38155 entries.append(lm)
Denis Laxalde
hgweb: handle a "linerange" request parameter in filelog command...
r31665 if i == revcount:
break
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 lessvars[b'linerange'] = webutil.formatlinerange(*lrange)
morevars[b'linerange'] = lessvars[b'linerange']
Denis Laxalde
hgweb: handle a "linerange" request parameter in filelog command...
r31665 else:
for i in revs:
iterfctx = fctx.filectx(i)
diffs = None
if patch:
diffs = diff(iterfctx)
Yuya Nishihara
hgweb: don't use dict(key=value) to build a mapping dict in filelog...
r38155 lm = webutil.commonentry(repo, iterfctx)
Augie Fackler
formatting: blacken the codebase...
r43346 lm.update(
{
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'parity': next(parity),
b'filerev': i,
b'file': f,
b'diff': diffs,
b'rename': webutil.renamelink(iterfctx),
Augie Fackler
formatting: blacken the codebase...
r43346 }
)
Yuya Nishihara
hgweb: don't use dict(key=value) to build a mapping dict in filelog...
r38155 entries.append(lm)
Denis Laxalde
hgweb: handle a "linerange" request parameter in filelog command...
r31665 entries.reverse()
revnav = webutil.filerevnav(web.repo, fctx.path())
nav = revnav.gen(end - 1, revcount, count)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Alexander Plavin
hgweb: always compute all entries and latestentry in filelog...
r20022 latestentry = entries[:1]
Gregory Szorc
hgweb: add a sendtemplate() helper function...
r36899 return web.sendtemplate(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'filelog',
Gregory Szorc
hgweb: support using new response object for web commands...
r36886 file=f,
nav=nav,
Gregory Szorc
hgweb: pass modern request type into various webutil functions (API)...
r36902 symrev=webutil.symrevorshortnode(web.req, fctx),
Yuya Nishihara
hgweb: wrap {entries}* of filelog with mappinglist...
r38156 entries=templateutil.mappinglist(entries),
Gregory Szorc
hgweb: support using new response object for web commands...
r36886 descend=descend,
patch=patch,
Yuya Nishihara
hgweb: wrap {entries}* of filelog with mappinglist...
r38156 latestentry=templateutil.mappinglist(latestentry),
Gregory Szorc
hgweb: support using new response object for web commands...
r36886 linerange=linerange,
revcount=revcount,
morevars=morevars,
lessvars=lessvars,
Augie Fackler
formatting: blacken the codebase...
r43346 **pycompat.strkwargs(webutil.commonentry(web.repo, fctx))
)
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @webcommand(b'archive')
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 def archive(web):
Gregory Szorc
webcommands: document "archive" web command
r24096 """
/archive/{revision}.{format}[/{path}]
-------------------------------------
Obtain an archive of repository content.
The content and type of the archive is defined by a URL path parameter.
``format`` is the file extension of the archive type to be generated. e.g.
``zip`` or ``tar.bz2``. Not all archive types may be allowed by your
server configuration.
The optional ``path`` URL parameter controls content to include in the
archive. If omitted, every file in the specified revision is present in the
archive. If included, only the specified file or contents of the specified
directory will be included in the archive.
No template is used for this handler. Raw, binary content is generated.
"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 type_ = web.req.qsparams.get(b'type')
allowed = web.configlist(b"web", b"allow-archive")
key = web.req.qsparams[b'node']
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Yuya Nishihara
hgweb: drop archivespecs from requestcontext...
r37530 if type_ not in webutil.archivespecs:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 msg = b'Unsupported archive type: %s' % stringutil.pprint(type_)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 raise ErrorResponse(HTTP_NOT_FOUND, msg)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not ((type_ in allowed or web.configbool(b"web", b"allow" + type_))):
msg = b'Archive type not allowed: %s' % type_
Rocco Rutte
hgweb: Respond with HTTP 403 for disabled archive types instead of 404...
r7029 raise ErrorResponse(HTTP_FORBIDDEN, msg)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 reponame = re.sub(br"\W+", b"-", os.path.basename(web.reponame))
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 cnode = web.repo.lookup(key)
arch_version = key
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if cnode == key or key == b'tip':
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 arch_version = short(cnode)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 name = b"%s-%s" % (reponame, arch_version)
Angel Ezquerra
hgweb: teach archive how to download a specific directory or file...
r18771
Gregory Szorc
hgweb: pass modern request type into various webutil functions (API)...
r36902 ctx = webutil.changectx(web.repo, web.req)
Angel Ezquerra
hgweb: teach archive how to download a specific directory or file...
r18771 pats = []
Martin von Zweigbergk
cleanup: rename "matchfn" to "match" where obviously a matcher...
r34085 match = scmutil.match(ctx, [])
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 file = web.req.qsparams.get(b'file')
Angel Ezquerra
hgweb: teach archive how to download a specific directory or file...
r18771 if file:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pats = [b'path:' + file]
match = scmutil.match(ctx, pats, default=b'path')
Angel Ezquerra
hgweb: respond HTTP_NOT_FOUND when an archive request does not match any files
r18968 if pats:
Martin von Zweigbergk
cleanup: rename "matchfn" to "match" where obviously a matcher...
r34085 files = [f for f in ctx.manifest().keys() if match(f)]
Angel Ezquerra
hgweb: respond HTTP_NOT_FOUND when an archive request does not match any files
r18968 if not files:
Augie Fackler
formatting: blacken the codebase...
r43346 raise ErrorResponse(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 HTTP_NOT_FOUND, b'file(s) not found: %s' % file
Augie Fackler
formatting: blacken the codebase...
r43346 )
Angel Ezquerra
hgweb: teach archive how to download a specific directory or file...
r18771
Yuya Nishihara
hgweb: drop archivespecs from requestcontext...
r37530 mimetype, artype, extension, encoding = webutil.archivespecs[type_]
Gregory Szorc
hgweb: port archive command to modern response API...
r36892
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 web.res.headers[b'Content-Type'] = mimetype
web.res.headers[b'Content-Disposition'] = b'attachment; filename=%s%s' % (
Augie Fackler
formatting: blacken the codebase...
r43346 name,
extension,
)
Gregory Szorc
hgweb: port archive command to modern response API...
r36892
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 if encoding:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 web.res.headers[b'Content-Encoding'] = encoding
Jordi Gutiérrez Hermoso
webcommands: allow hgweb's archive to recurse into subrepos...
r17933
Gregory Szorc
hgweb: port archive command to modern response API...
r36892 web.res.setbodywillwrite()
Gregory Szorc
hgweb: convert an assert to a ProgrammingError...
r36995 if list(web.res.sendresponse()):
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.ProgrammingError(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 b'sendresponse() should not emit data if writing later'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
hgweb: port archive command to modern response API...
r36892
bodyfh = web.res.getbodyfile()
Gregory Szorc
hgweb: refactor fake file object proxy for archiving...
r36891
Augie Fackler
formatting: blacken the codebase...
r43346 archival.archive(
web.repo,
bodyfh,
cnode,
artype,
prefix=name,
match=match,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 subrepos=web.configbool(b"web", b"archivesubrepos"),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Gregory Szorc
hgweb: always return iterable from @webcommand functions (API)...
r36896 return []
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @webcommand(b'static')
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 def static(web):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 fname = web.req.qsparams[b'file']
Dirkjan Ochtman
split out hgweb commands into a separate file, move some code around
r5591 # a repo owner may set web.static in .hg/hgrc to get any file
# readable by the user running the CGI script
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 static = web.config(b"web", b"static", untrusted=False)
Brendan Cully
Allow hgweb to search for templates in more than one path....
r7107 if not static:
Mads Kiilerich
templater: introduce templatepaths for getting paths searched for templates...
r22634 tp = web.templatepath or templater.templatepaths()
Brendan Cully
Allow hgweb to search for templates in more than one path....
r7107 if isinstance(tp, str):
tp = [tp]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 static = [os.path.join(p, b'static') for p in tp]
Gregory Szorc
hgweb: port static file handling to new response API...
r36889
staticfile(static, fname, web.res)
Gregory Szorc
hgweb: always return iterable from @webcommand functions (API)...
r36896 return web.res.sendresponse()
Dirkjan Ochtman
add graph page to hgweb
r6691
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @webcommand(b'graph')
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 def graph(web):
Gregory Szorc
webcommands: document "graph" web command
r24097 """
/graph[/{revision}]
-------------------
Show information about the graphical topology of the repository.
Information rendered by this handler can be used to create visual
representations of repository topology.
av6
hgweb: update graph function docstring
r35412 The ``revision`` URL parameter controls the starting changeset. If it's
absent, the default is ``tip``.
Gregory Szorc
webcommands: document "graph" web command
r24097
The ``revcount`` query string argument can define the number of changesets
to show information for.
av6
hgweb: update graph function docstring
r35412 The ``graphtop`` query string argument can specify the starting changeset
for producing ``jsdata`` variable that is used for rendering graph in
JavaScript. By default it has the same value as ``revision``.
Gregory Szorc
webcommands: document "graph" web command
r24097 This handler will render the ``graph`` template.
"""
Dirkjan Ochtman
hgweb: make graph page size equal to shortlog
r10245
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'node' in web.req.qsparams:
Gregory Szorc
hgweb: pass modern request type into various webutil functions (API)...
r36902 ctx = webutil.changectx(web.repo, web.req)
symrev = webutil.symrevorshortnode(web.req, ctx)
av6
hgweb: provide symrev (symbolic revision) property to the templates...
r25602 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ctx = web.repo[b'tip']
symrev = b'tip'
Patrick Mezard
hgweb: fix graph view paging...
r17318 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
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'revcount' in web.req.qsparams:
Isaac Jurado
hgweb: ignore non numeric "revcount" parameter values (issue4091)
r20092 try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 revcount = int(web.req.qsparams.get(b'revcount', revcount))
Isaac Jurado
hgweb: ignore non numeric "revcount" parameter values (issue4091)
r20092 revcount = max(revcount, 1)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 web.tmpl.defaults[b'sessionvars'][b'revcount'] = revcount
Isaac Jurado
hgweb: ignore non numeric "revcount" parameter values (issue4091)
r20092 except ValueError:
pass
Dirkjan Ochtman
hgweb: fix up the less/more links on the graph page...
r7345
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 lessvars = copy.copy(web.tmpl.defaults[b'sessionvars'])
lessvars[b'revcount'] = max(revcount // 2, 1)
morevars = copy.copy(web.tmpl.defaults[b'sessionvars'])
morevars[b'revcount'] = revcount * 2
Dirkjan Ochtman
hgweb: fix up the less/more links on the graph page...
r7345
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 graphtop = web.req.qsparams.get(b'graphtop', ctx.hex())
graphvars = copy.copy(web.tmpl.defaults[b'sessionvars'])
graphvars[b'graphtop'] = graphtop
av6
hgweb: render next pages on /graph incrementally...
r35410
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 = []
av6
hgweb: render next pages on /graph incrementally...
r35410 nextentry = []
lastrev = 0
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)
av6
hgweb: render next pages on /graph incrementally...
r35410 if len(revs) >= revcount + 1:
Alexander Plavin
hgweb: fix incorrect revisions count in graph (issue3977)...
r19487 break
av6
hgweb: render next pages on /graph incrementally...
r35410 if len(revs) > revcount:
nextentry = [webutil.commonentry(web.repo, web.repo[revs[-1]])]
revs = revs[:-1]
lastrev = revs[-1]
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.
Yuya Nishihara
revset: import set classes directly from smartset module...
r31023 dag = graphmod.dagwalker(web.repo, smartset.baseset(revs))
Lucas Moscovicz
webcommands: changed code to use lazy classes when calling dagwalker...
r20761 # As we said one line above... not lazy.
Augie Fackler
formatting: blacken the codebase...
r43346 tree = list(
item
for item in graphmod.colored(dag, web.repo)
if item[1] == graphmod.CHANGESET
)
Paul Boddie
hgweb: make graph data suitable for template usage...
r16773
av6
hgweb: render next pages on /graph incrementally...
r35410 def fulltree():
pos = web.repo[graphtop].rev()
tree = []
if pos != -1:
revs = web.repo.changelog.revs(pos, lastrev)
dag = graphmod.dagwalker(web.repo, smartset.baseset(revs))
Augie Fackler
formatting: blacken the codebase...
r43346 tree = list(
item
for item in graphmod.colored(dag, web.repo)
if item[1] == graphmod.CHANGESET
)
av6
hgweb: render next pages on /graph incrementally...
r35410 return tree
Yuya Nishihara
hgweb: adapt {jsdata} of graph to mappinggenerator...
r38209 def jsdata(context):
for (id, type, ctx, vtx, edges) in fulltree():
Augie Fackler
formatting: blacken the codebase...
r43346 yield {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'node': pycompat.bytestr(ctx),
b'graphnode': webutil.getgraphnode(web.repo, ctx),
b'vertex': vtx,
b'edges': edges,
Augie Fackler
formatting: blacken the codebase...
r43346 }
Paul Boddie
hgweb: make graph data suitable for template usage...
r16773
Yuya Nishihara
hgweb: wrap {nodes} of graph with mappinggenerator...
r38210 def nodes(context):
av6
monoblue: make actual changeset entries have backgrounds on /graph...
r35548 parity = paritygen(web.stripecount)
av6
hgweb: split graphdata() into jsdata() and nodes()...
r35409 for row, (id, type, ctx, vtx, edges) in enumerate(tree):
entry = webutil.commonentry(web.repo, ctx)
Augie Fackler
formatting: blacken the codebase...
r43346 edgedata = [
{
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'col': edge[0],
b'nextcol': edge[1],
b'color': (edge[2] - 1) % 6 + 1,
b'width': edge[3],
b'bcolor': edge[4],
Augie Fackler
formatting: blacken the codebase...
r43346 }
for edge in edges
]
Paul Boddie
hgweb: make graph data suitable for template usage...
r16773
Augie Fackler
formatting: blacken the codebase...
r43346 entry.update(
{
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'col': vtx[0],
b'color': (vtx[1] - 1) % 6 + 1,
b'parity': next(parity),
b'edges': templateutil.mappinglist(edgedata),
b'row': row,
b'nextrow': row + 1,
Augie Fackler
formatting: blacken the codebase...
r43346 }
)
av6
hgweb: use webutil.commonentry() for nodes (but not for jsdata yet) in /graph...
r35095
av6
hgweb: split graphdata() into jsdata() and nodes()...
r35409 yield entry
Paul Boddie
hgweb: make graph data suitable for template usage...
r16773
rows = len(tree)
Dirkjan Ochtman
add graph page to hgweb
r6691
Gregory Szorc
hgweb: add a sendtemplate() helper function...
r36899 return web.sendtemplate(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'graph',
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 rev=rev,
symrev=symrev,
revcount=revcount,
uprev=uprev,
lessvars=lessvars,
morevars=morevars,
downrev=downrev,
graphvars=graphvars,
rows=rows,
bg_height=bg_height,
changesets=count,
Yuya Nishihara
hgweb: wrap {nextentry} of graph with mappinglist...
r38208 nextentry=templateutil.mappinglist(nextentry),
Yuya Nishihara
hgweb: adapt {jsdata} of graph to mappinggenerator...
r38209 jsdata=templateutil.mappinggenerator(jsdata),
Yuya Nishihara
hgweb: wrap {nodes} of graph with mappinggenerator...
r38210 nodes=templateutil.mappinggenerator(nodes),
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 node=ctx.hex(),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 archives=web.archivelist(b'tip'),
Augie Fackler
formatting: blacken the codebase...
r43346 changenav=changenav,
)
Augie Fackler
web: add a help view for getting hg help output
r12666
def _getdoc(e):
doc = e[0].__doc__
if doc:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 doc = _(doc).partition(b'\n')[0]
Augie Fackler
web: add a help view for getting hg help output
r12666 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 doc = _(b'(no help text available)')
Augie Fackler
web: add a help view for getting hg help output
r12666 return doc
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @webcommand(b'help')
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 def help(web):
Gregory Szorc
webcommands: document "help" web command
r24081 """
/help[/{topic}]
---------------
Render help documentation.
This web command is roughly equivalent to :hg:`help`. If a ``topic``
is defined, that help topic will be rendered. If not, an index of
available help topics will be rendered.
The ``help`` template will be rendered when requesting help for a topic.
``helptopics`` will be rendered for the index of help topics.
"""
Yuya Nishihara
hgweb: use absolute_import
r27046 from .. import commands, help as helpmod # avoid cycle
Augie Fackler
web: add a help view for getting hg help output
r12666
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 topicname = web.req.qsparams.get(b'node')
Augie Fackler
web: add a help view for getting hg help output
r12666 if not topicname:
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
hgweb: wrap {topics}es of help with mappinggenerator or mappinglist...
r38212 def topics(context):
Rodrigo Damazio
help: splitting the topics by category...
r40328 for h in helpmod.helptable:
entries, summary, _doc = h[0:3]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield {b'topic': entries[0], b'summary': summary}
Augie Fackler
web: add a help view for getting hg help output
r12666
early, other = [], []
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 primary = lambda s: s.partition(b'|')[0]
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for c, e in pycompat.iteritems(commands.table):
Augie Fackler
web: add a help view for getting hg help output
r12666 doc = _getdoc(e)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'DEPRECATED' in doc or c.startswith(b'debug'):
Augie Fackler
web: add a help view for getting hg help output
r12666 continue
cmd = primary(c)
Rodrigo Damazio
help: adding a proper declaration for shortlist/basic commands (API)...
r40331 if getattr(e[0], 'helpbasic', False):
early.append((cmd, doc))
Augie Fackler
web: add a help view for getting hg help output
r12666 else:
other.append((cmd, doc))
early.sort()
other.sort()
Yuya Nishihara
hgweb: wrap {earlycommands} and {othercommands} of help with mappinggenerator...
r38213 def earlycommands(context):
Augie Fackler
web: add a help view for getting hg help output
r12666 for c, doc in early:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield {b'topic': c, b'summary': doc}
Augie Fackler
web: add a help view for getting hg help output
r12666
Yuya Nishihara
hgweb: wrap {earlycommands} and {othercommands} of help with mappinggenerator...
r38213 def othercommands(context):
Augie Fackler
web: add a help view for getting hg help output
r12666 for c, doc in other:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield {b'topic': c, b'summary': doc}
Augie Fackler
web: add a help view for getting hg help output
r12666
Gregory Szorc
hgweb: add a sendtemplate() helper function...
r36899 return web.sendtemplate(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'helptopics',
Yuya Nishihara
hgweb: wrap {topics}es of help with mappinggenerator or mappinglist...
r38212 topics=templateutil.mappinggenerator(topics),
Yuya Nishihara
hgweb: wrap {earlycommands} and {othercommands} of help with mappinggenerator...
r38213 earlycommands=templateutil.mappinggenerator(earlycommands),
othercommands=templateutil.mappinggenerator(othercommands),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 title=b'Index',
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
web: add a help view for getting hg help output
r12666
Gregory Szorc
hgweb: support rendering sub-topic indexes...
r27581 # Render an index of sub-topics.
if topicname in helpmod.subtopics:
topics = []
for entries, summary, _doc in helpmod.subtopics[topicname]:
Augie Fackler
formatting: blacken the codebase...
r43346 topics.append(
{
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'topic': b'%s.%s' % (topicname, entries[0]),
b'basename': entries[0],
b'summary': summary,
Augie Fackler
formatting: blacken the codebase...
r43346 }
)
Gregory Szorc
hgweb: support rendering sub-topic indexes...
r27581
Gregory Szorc
hgweb: add a sendtemplate() helper function...
r36899 return web.sendtemplate(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'helptopics',
Yuya Nishihara
hgweb: wrap {topics}es of help with mappinggenerator or mappinglist...
r38212 topics=templateutil.mappinglist(topics),
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887 title=topicname,
Augie Fackler
formatting: blacken the codebase...
r43346 subindex=True,
)
Gregory Szorc
hgweb: support rendering sub-topic indexes...
r27581
Yuya Nishihara
ui: factor out ui.load() to create a ui without loading configs (API)...
r30559 u = webutil.wsgiui.load()
Adrian Buehlmann
hgweb: show help with verbose sections included...
r17146 u.verbose = True
Gregory Szorc
hgweb: support rendering a sub-topic...
r27582
# Render a page from a sub-topic.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'.' in topicname:
Gregory Szorc
hgweb: support rendering a sub-topic...
r27582 # TODO implement support for rendering sections, like
# `hg help` works.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 topic, subtopic = topicname.split(b'.', 1)
Gregory Szorc
hgweb: support rendering a sub-topic...
r27582 if topic not in helpmod.subtopics:
raise ErrorResponse(HTTP_NOT_FOUND)
else:
topic = topicname
subtopic = None
Augie Fackler
web: add a help view for getting hg help output
r12666 try:
Yuya Nishihara
help: pass commands module by argument...
r32567 doc = helpmod.help_(u, commands, topic, subtopic=subtopic)
Yuya Nishihara
hgweb: translate Abort in help command to 404 error...
r36262 except error.Abort:
Augie Fackler
web: add a help view for getting hg help output
r12666 raise ErrorResponse(HTTP_NOT_FOUND)
Gregory Szorc
hgweb: port most @webcommand to use modern response type...
r36887
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return web.sendtemplate(b'help', topic=topicname, doc=doc)
Augie Fackler
formatting: blacken the codebase...
r43346
FUJIWARA Katsunori
i18n: extract doc string of each web commands as translatable one...
r24859
# tell hggettext to extract docstrings from these functions:
i18nfunctions = commands.values()