##// END OF EJS Templates
copies: do not initialize the dictionary with root in changeset copies...
copies: do not initialize the dictionary with root in changeset copies We don't strictly need the dict to be prefiled with `{}`. Not doing so will make the next changeset simpler. This part of a preparation to use native code for this part of copy tracing.

File last commit:

r44159:371765e7 stable
r44177:fb8f10c0 default
Show More
webutil.py
940 lines | 26.9 KiB | text/x-python | PythonLexer
Dirkjan Ochtman
hgweb: separate out utility functions
r6392 # hgweb/webutil.py - utility library for the web interface.
#
# Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
# Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
#
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Dirkjan Ochtman
hgweb: separate out utility functions
r6392
Yuya Nishihara
hgweb: use absolute_import
r27046 from __future__ import absolute_import
import copy
import difflib
import os
Gregory Szorc
hgweb: extract web substitutions table generation to own function...
r26162 import re
Yuya Nishihara
hgweb: use absolute_import
r27046
from ..i18n import _
from ..node import hex, nullid, short
Gregory Szorc
py3: manually import pycompat.setattr where it is needed...
r43357 from ..pycompat import setattr
Yuya Nishihara
hgweb: use absolute_import
r27046
from .common import (
ErrorResponse,
Denis Laxalde
hgweb: handle a "linerange" request parameter in filelog command...
r31665 HTTP_BAD_REQUEST,
Yuya Nishihara
hgweb: use absolute_import
r27046 HTTP_NOT_FOUND,
paritygen,
)
from .. import (
context,
Yuya Nishihara
diffutil: move the module out of utils package...
r38607 diffutil,
Yuya Nishihara
hgweb: use absolute_import
r27046 error,
match,
Denis Laxalde
mdiff: add a hunkinrange helper function...
r31808 mdiff,
av6
hgweb: explain instabilities of unstable changesets
r36973 obsutil,
Yuya Nishihara
hgweb: use absolute_import
r27046 patch,
pathutil,
Augie Fackler
webutil: use pycompat.bytestr() instead of str()...
r34808 pycompat,
Martin von Zweigbergk
hgweb: use revsymbol() for creating context from changeid...
r37351 scmutil,
Yuya Nishihara
hgweb: use absolute_import
r27046 templatefilters,
av6
hgweb: display fate of obsolete changesets...
r35501 templatekw,
Yuya Nishihara
hgweb: wrap {archives} with mappinglist...
r37533 templateutil,
Yuya Nishihara
hgweb: use absolute_import
r27046 ui as uimod,
util,
)
Dirkjan Ochtman
hgweb: separate out utility functions
r6392
Augie Fackler
formatting: blacken the codebase...
r43346 from ..utils import stringutil
archivespecs = util.sortdict(
(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 (b'zip', (b'application/zip', b'zip', b'.zip', None)),
(b'gz', (b'application/x-gzip', b'tgz', b'.tar.gz', None)),
(b'bz2', (b'application/x-bzip2', b'tbz2', b'.tar.bz2', None)),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 )
Yuya Nishihara
hgweb: move archivespecs to webutil...
r37529
Yuya Nishihara
hgweb: forward archivelist() of hgweb to webutil...
r37532 def archivelist(ui, nodeid, url=None):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 allowed = ui.configlist(b'web', b'allow-archive', untrusted=True)
Yuya Nishihara
hgweb: move archivelist() of hgwebdir to webutil
r37531 archives = []
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for typ, spec in pycompat.iteritems(archivespecs):
Augie Fackler
formatting: blacken the codebase...
r43346 if typ in allowed or ui.configbool(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'web', b'allow' + typ, untrusted=True
Augie Fackler
formatting: blacken the codebase...
r43346 ):
archives.append(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 {
b'type': typ,
b'extension': spec[2],
b'node': nodeid,
b'url': url,
}
Augie Fackler
formatting: blacken the codebase...
r43346 )
Yuya Nishihara
hgweb: move archivelist() of hgwebdir to webutil
r37531
Yuya Nishihara
hgweb: wrap {archives} with mappinglist...
r37533 return templateutil.mappinglist(archives)
Yuya Nishihara
hgweb: move archivelist() of hgwebdir to webutil
r37531
Augie Fackler
formatting: blacken the codebase...
r43346
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 def up(p):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if p[0:1] != b"/":
p = b"/" + p
if p[-1:] == b"/":
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393 p = p[:-1]
up = os.path.dirname(p)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if up == b"/":
return b"/"
return up + b"/"
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
hgweb: better names for _navseq arguments...
r18391 def _navseq(step, firststep=None):
if firststep:
yield firststep
if firststep >= 20 and firststep <= 40:
Pierre-Yves David
hgweb: ensure _navseq yield strictly increasing numbers...
r18392 firststep = 50
yield firststep
assert step > 0
assert firststep > 0
while step <= firststep:
step *= 10
Pierre-Yves David
hgweb: drop recursivity in _navseq...
r18390 while True:
Pierre-Yves David
hgweb: better names for _navseq arguments...
r18391 yield 1 * step
yield 3 * step
step *= 10
Pierre-Yves David
hgweb: move the `seq` function out of the revnavgen scope...
r18389
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
hgweb: move revnavgen into an object...
r18403 class revnav(object):
Pierre-Yves David
hgweb: pass repo object to revnav construction...
r18409 def __init__(self, repo):
Pierre-Yves David
hgweb: pass nodefunc to the revnav object...
r18404 """Navigation generation object
Pierre-Yves David
hgweb: pass repo object to revnav construction...
r18409 :repo: repo object we generate nav for
Pierre-Yves David
hgweb: pass nodefunc to the revnav object...
r18404 """
Pierre-Yves David
hgweb: pass repo object to revnav construction...
r18409 # used for hex generation
self._revlog = repo.changelog
Pierre-Yves David
hgweb: pass nodefunc to the revnav object...
r18404
Pierre-Yves David
hgweb: simplify the handling of empty repo...
r18406 def __nonzero__(self):
"""return True if any revision to navigate over"""
Pierre-Yves David
hgweb: handle filtered "0" rev in navigation...
r19094 return self._first() is not None
Gregory Szorc
py3: add __bool__ to every class defining __nonzero__...
r31476 __bool__ = __nonzero__
Pierre-Yves David
hgweb: handle filtered "0" rev in navigation...
r19094 def _first(self):
"""return the minimum non-filtered changeset or None"""
try:
timeless
py3: convert to next() function...
r29216 return next(iter(self._revlog))
Pierre-Yves David
hgweb: handle filtered "0" rev in navigation...
r19094 except StopIteration:
return None
Pierre-Yves David
hgweb: simplify the handling of empty repo...
r18406
Pierre-Yves David
hgweb: move hex creation into an object method...
r18405 def hex(self, rev):
Pierre-Yves David
hgweb: pass repo object to revnav construction...
r18409 return hex(self._revlog.node(rev))
Pierre-Yves David
hgweb: move hex creation into an object method...
r18405
Pierre-Yves David
hgweb: pass nodefunc to the revnav object...
r18404 def gen(self, pos, pagelen, limit):
Pierre-Yves David
hgweb: move revnavgen into an object...
r18403 """computes label and revision id for navigation link
Pierre-Yves David
hgweb: document the revnavgen function
r18320
Pierre-Yves David
hgweb: move revnavgen into an object...
r18403 :pos: is the revision relative to which we generate navigation.
:pagelen: the size of each navigation page
:limit: how far shall we link
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Pierre-Yves David
hgweb: move revnavgen into an object...
r18403 The return is:
Yuya Nishihara
hgweb: wrap {changenav} and {nav} with mappinglist
r37716 - a single element mappinglist
Pierre-Yves David
hgweb: move revnavgen into an object...
r18403 - containing a dictionary with a `before` and `after` key
Yuya Nishihara
hgweb: make revnav.gen() simply build a list of mappings by one pass...
r37715 - values are dictionaries with `label` and `node` keys
Pierre-Yves David
hgweb: move revnavgen into an object...
r18403 """
Pierre-Yves David
hgweb: simplify the handling of empty repo...
r18406 if not self:
# empty repo
Augie Fackler
formatting: blacken the codebase...
r43346 return templateutil.mappinglist(
[
{
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'before': templateutil.mappinglist([]),
b'after': templateutil.mappinglist([]),
Augie Fackler
formatting: blacken the codebase...
r43346 },
]
)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Pierre-Yves David
hgweb: generate revnav in two phase...
r18425 targets = []
Pierre-Yves David
hgweb: move revnavgen into an object...
r18403 for f in _navseq(1, pagelen):
if f > limit:
break
Pierre-Yves David
hgweb: generate revnav in two phase...
r18425 targets.append(pos + f)
targets.append(pos - f)
targets.sort()
Pierre-Yves David
hgweb: handle filtered "0" rev in navigation...
r19094 first = self._first()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 navbefore = [{b'label': b'(%i)' % first, b'node': self.hex(first)}]
Pierre-Yves David
hgweb: generate revnav in two phase...
r18425 navafter = []
for rev in targets:
Pierre-Yves David
hgweb: ignore filtered revision in revnav...
r18426 if rev not in self._revlog:
continue
Pierre-Yves David
hgweb: generate revnav in two phase...
r18425 if pos < rev < limit:
Augie Fackler
formatting: blacken the codebase...
r43346 navafter.append(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 {b'label': b'+%d' % abs(rev - pos), b'node': self.hex(rev)}
Augie Fackler
formatting: blacken the codebase...
r43346 )
Pierre-Yves David
hgweb: generate revnav in two phase...
r18425 if 0 < rev < pos:
Augie Fackler
formatting: blacken the codebase...
r43346 navbefore.append(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 {b'label': b'-%d' % abs(rev - pos), b'node': self.hex(rev)}
Augie Fackler
formatting: blacken the codebase...
r43346 )
Nicolas Dumazet
hgweb: changenav: separate pages before and after the current position...
r10254
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 navafter.append({b'label': b'tip', b'node': b'tip'})
Pierre-Yves David
hgweb: move revnavgen into an object...
r18403
Yuya Nishihara
hgweb: wrap {changenav} and {nav} with mappinglist
r37716 # TODO: maybe this can be a scalar object supporting tomap()
Augie Fackler
formatting: blacken the codebase...
r43346 return templateutil.mappinglist(
[
{
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'before': templateutil.mappinglist(navbefore),
b'after': templateutil.mappinglist(navafter),
Augie Fackler
formatting: blacken the codebase...
r43346 },
]
)
Dirkjan Ochtman
hgweb: refactor hgweb code
r6393
Pierre-Yves David
hgweb: introduction a filerevnav subclass...
r18408 class filerevnav(revnav):
Pierre-Yves David
hgweb: pass repo object to revnav construction...
r18409 def __init__(self, repo, path):
"""Navigation generation object
:repo: repo object we generate nav for
:path: path of the file we generate nav for
"""
# used for iteration
self._changelog = repo.unfiltered().changelog
# used for hex generation
self._revlog = repo.file(path)
def hex(self, rev):
return hex(self._changelog.node(self._revlog.linkrev(rev)))
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
hgweb: extract a generator function of _siblings class...
r37717 # TODO: maybe this can be a wrapper class for changectx/filectx list, which
# yields {'ctx': ctx}
Yuya Nishihara
hgweb: convert _siblings to a factory function of mappinggenerator...
r37718 def _ctxsgen(context, ctxs):
Yuya Nishihara
hgweb: extract a generator function of _siblings class...
r37717 for s in ctxs:
d = {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'node': s.hex(),
b'rev': s.rev(),
b'user': s.user(),
b'date': s.date(),
b'description': s.description(),
b'branch': s.branch(),
Yuya Nishihara
hgweb: extract a generator function of _siblings class...
r37717 }
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if util.safehasattr(s, b'path'):
d[b'file'] = s.path()
Yuya Nishihara
hgweb: extract a generator function of _siblings class...
r37717 yield d
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
hgweb: convert _siblings to a factory function of mappinggenerator...
r37718 def _siblings(siblings=None, hiderev=None):
if siblings is None:
siblings = []
siblings = [s for s in siblings if s.node() != nullid]
if len(siblings) == 1 and siblings[0].rev() == hiderev:
siblings = []
return templateutil.mappinggenerator(_ctxsgen, args=(siblings,))
Dirkjan Ochtman
hgweb: separate out utility functions
r6392
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
hgweb: query string arguments to control whitespace for annotate...
r34391 def difffeatureopts(req, ui, section):
Augie Fackler
formatting: blacken the codebase...
r43346 diffopts = diffutil.difffeatureopts(
ui, untrusted=True, section=section, whitespace=True
)
Gregory Szorc
hgweb: query string arguments to control whitespace for annotate...
r34391
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for k in (
b'ignorews',
b'ignorewsamount',
b'ignorewseol',
b'ignoreblanklines',
):
Gregory Szorc
hgweb: pass modern request type into various webutil functions (API)...
r36902 v = req.qsparams.get(k)
Gregory Szorc
hgweb: query string arguments to control whitespace for annotate...
r34391 if v is not None:
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 v = stringutil.parsebool(v)
Gregory Szorc
hgweb: use parsebool for parsing diff query string options...
r34404 setattr(diffopts, k, v if v is not None else True)
Gregory Szorc
hgweb: query string arguments to control whitespace for annotate...
r34391
return diffopts
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
hgweb: query string arguments to control whitespace for annotate...
r34391 def annotate(req, fctx, ui):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 diffopts = difffeatureopts(req, ui, b'annotate')
Yuya Nishihara
annotate: drop linenumber flag from fctx.annotate() (API)...
r37083 return fctx.annotate(follow=True, diffopts=diffopts)
Jun Wu
hgweb: make fctx.annotate a separated function so it could be wrapped...
r30081
Augie Fackler
formatting: blacken the codebase...
r43346
Dirkjan Ochtman
hgweb: simplify parents/children generation code
r7671 def parents(ctx, hide=None):
Anton Shestakov
hgweb: use introrev() for finding parents (issue4506)...
r24136 if isinstance(ctx, context.basefilectx):
introrev = ctx.introrev()
if ctx.changectx().rev() != introrev:
Matt Harbison
hgweb: replace 'ctx._repo' with 'ctx.repo()'
r24340 return _siblings([ctx.repo()[introrev]], hide)
Dirkjan Ochtman
hgweb: simplify parents/children generation code
r7671 return _siblings(ctx.parents(), hide)
Augie Fackler
formatting: blacken the codebase...
r43346
Dirkjan Ochtman
hgweb: simplify parents/children generation code
r7671 def children(ctx, hide=None):
return _siblings(ctx.children(), hide)
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
hgweb: minor improvements for new web style...
r6434 def renamelink(fctx):
Matt Mackall
hgweb: fix merge breakage
r6437 r = fctx.renamed()
Dirkjan Ochtman
hgweb: separate out utility functions
r6392 if r:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return templateutil.mappinglist([{b'file': r[0], b'node': hex(r[1])}])
Yuya Nishihara
hgweb: wrap {rename} with mappinglist...
r37921 return templateutil.mappinglist([])
Dirkjan Ochtman
hgweb: separate out utility functions
r6392
Augie Fackler
formatting: blacken the codebase...
r43346
Dirkjan Ochtman
hgweb: separate out utility functions
r6392 def nodetagsdict(repo, node):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return templateutil.hybridlist(repo.nodetags(node), name=b'name')
Dirkjan Ochtman
hgweb: separate out utility functions
r6392
Augie Fackler
formatting: blacken the codebase...
r43346
Alexander Solovyov
hgweb: add display of bookmarks for changelog and changeset
r13596 def nodebookmarksdict(repo, node):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return templateutil.hybridlist(repo.nodebookmarks(node), name=b'name')
Alexander Solovyov
hgweb: add display of bookmarks for changelog and changeset
r13596
Augie Fackler
formatting: blacken the codebase...
r43346
Dirkjan Ochtman
hgweb: separate out utility functions
r6392 def nodebranchdict(repo, ctx):
branches = []
branch = ctx.branch()
# If this is an empty repo, ctx.node() == nullid,
Brodie Rao
localrepo: add branchtip() method for faster single-branch lookups...
r16719 # ctx.branch() == 'default'.
try:
branchnode = repo.branchtip(branch)
except error.RepoLookupError:
branchnode = None
if branchnode == ctx.node():
Yuya Nishihara
hgweb: wrap {branches} by hybridlist()...
r37924 branches.append(branch)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return templateutil.hybridlist(branches, name=b'name')
Dirkjan Ochtman
hgweb: separate out utility functions
r6392
Augie Fackler
formatting: blacken the codebase...
r43346
Dirkjan Ochtman
hgweb: separate out utility functions
r6392 def nodeinbranch(repo, ctx):
branches = []
branch = ctx.branch()
Brodie Rao
localrepo: add branchtip() method for faster single-branch lookups...
r16719 try:
branchnode = repo.branchtip(branch)
except error.RepoLookupError:
branchnode = None
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if branch != b'default' and branchnode != ctx.node():
Yuya Nishihara
hgweb: wrap {inbranch} by hybridlist()...
r37925 branches.append(branch)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return templateutil.hybridlist(branches, name=b'name')
Dirkjan Ochtman
hgweb: separate out utility functions
r6392
Augie Fackler
formatting: blacken the codebase...
r43346
Dirkjan Ochtman
hgweb: separate out utility functions
r6392 def nodebranchnodefault(ctx):
branches = []
branch = ctx.branch()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if branch != b'default':
Yuya Nishihara
hgweb: wrap {branch} and {changesetbranch} by hybridlist()...
r37926 branches.append(branch)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return templateutil.hybridlist(branches, name=b'name')
Dirkjan Ochtman
hgweb: separate out utility functions
r6392
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
hgweb: wrap {changelogtag}, {changesettag}, and {changesetbookmark}...
r37930 def _nodenamesgen(context, f, node, name):
for t in f(node):
yield {name: t}
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
hgweb: drop tmpl argument from webutil.showtag() and showbookmark()...
r37931 def showtag(repo, t1, node=nullid):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 args = (repo.nodetags, node, b'tag')
Yuya Nishihara
hgweb: wrap {changelogtag}, {changesettag}, and {changesetbookmark}...
r37930 return templateutil.mappinggenerator(_nodenamesgen, args=args, name=t1)
Dirkjan Ochtman
hgweb: separate out utility functions
r6392
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
hgweb: drop tmpl argument from webutil.showtag() and showbookmark()...
r37931 def showbookmark(repo, t1, node=nullid):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 args = (repo.nodebookmarks, node, b'bookmark')
Yuya Nishihara
hgweb: wrap {changelogtag}, {changesettag}, and {changesetbookmark}...
r37930 return templateutil.mappinggenerator(_nodenamesgen, args=args, name=t1)
Alexander Solovyov
hgweb: add display of bookmarks for changelog and changeset
r13596
Augie Fackler
formatting: blacken the codebase...
r43346
av6
hgweb: move branchentries code from webcommands to webutil
r26129 def branchentries(repo, stripecount, limit=0):
tips = []
heads = repo.heads()
parity = paritygen(stripecount)
sortkey = lambda item: (not item[1], item[0].rev())
Yuya Nishihara
hgweb: wrap {branches} and {entries} of branches with mappinggenerator...
r37932 def entries(context):
av6
hgweb: move branchentries code from webcommands to webutil
r26129 count = 0
if not tips:
for tag, hs, tip, closed in repo.branchmap().iterbranches():
tips.append((repo[tip], closed))
for ctx, closed in sorted(tips, key=sortkey, reverse=True):
if limit > 0 and count >= limit:
return
count += 1
if closed:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 status = b'closed'
av6
hgweb: move branchentries code from webcommands to webutil
r26129 elif ctx.node() not in heads:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 status = b'inactive'
av6
hgweb: move branchentries code from webcommands to webutil
r26129 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 status = b'open'
av6
hgweb: move branchentries code from webcommands to webutil
r26129 yield {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'parity': next(parity),
b'branch': ctx.branch(),
b'status': status,
b'node': ctx.hex(),
b'date': ctx.date(),
av6
hgweb: move branchentries code from webcommands to webutil
r26129 }
Yuya Nishihara
hgweb: wrap {branches} and {entries} of branches with mappinggenerator...
r37932 return templateutil.mappinggenerator(entries)
av6
hgweb: move branchentries code from webcommands to webutil
r26129
Augie Fackler
formatting: blacken the codebase...
r43346
Dirkjan Ochtman
hgweb: separate out utility functions
r6392 def cleanpath(repo, path):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 path = path.lstrip(b'/')
Yuya Nishihara
hgweb: do not audit URL path as working-directory path...
r39507 auditor = pathutil.pathauditor(repo.root, realfs=False)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return pathutil.canonpath(repo.root, b'', path, auditor=auditor)
Dirkjan Ochtman
hgweb: separate out utility functions
r6392
Augie Fackler
formatting: blacken the codebase...
r43346
av6
style: adjust whitespaces in webutil.py...
r25999 def changectx(repo, req):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 changeid = b"tip"
if b'node' in req.qsparams:
changeid = req.qsparams[b'node']
ipos = changeid.find(b':')
Weiwen
hgweb: display diff for a changeset against any parents (issue2810)...
r17991 if ipos != -1:
Augie Fackler
formatting: blacken the codebase...
r43346 changeid = changeid[(ipos + 1) :]
Weiwen
hgweb: display diff for a changeset against any parents (issue2810)...
r17991
Martin von Zweigbergk
hgweb: use revsymbol() for creating context from changeid...
r37351 return scmutil.revsymbol(repo, changeid)
Weiwen
hgweb: display diff for a changeset against any parents (issue2810)...
r17991
Augie Fackler
formatting: blacken the codebase...
r43346
Weiwen
hgweb: display diff for a changeset against any parents (issue2810)...
r17991 def basechangectx(repo, req):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'node' in req.qsparams:
changeid = req.qsparams[b'node']
ipos = changeid.find(b':')
Weiwen
hgweb: display diff for a changeset against any parents (issue2810)...
r17991 if ipos != -1:
changeid = changeid[:ipos]
Martin von Zweigbergk
hgweb: use revsymbol() for creating context from changeid...
r37351 return scmutil.revsymbol(repo, changeid)
Weiwen
hgweb: display diff for a changeset against any parents (issue2810)...
r17991
return None
Augie Fackler
formatting: blacken the codebase...
r43346
Dirkjan Ochtman
hgweb: separate out utility functions
r6392 def filectx(repo, req):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'file' not in req.qsparams:
raise ErrorResponse(HTTP_NOT_FOUND, b'file not given')
path = cleanpath(repo, req.qsparams[b'file'])
if b'node' in req.qsparams:
changeid = req.qsparams[b'node']
elif b'filenode' in req.qsparams:
changeid = req.qsparams[b'filenode']
Dirkjan Ochtman
hgweb: separate out utility functions
r6392 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise ErrorResponse(HTTP_NOT_FOUND, b'node or filenode not given')
Dirkjan Ochtman
hgweb: separate out utility functions
r6392 try:
Martin von Zweigbergk
hgweb: use revsymbol() for creating context from changeid...
r37351 fctx = scmutil.revsymbol(repo, changeid)[path]
Matt Mackall
error: move repo errors...
r7637 except error.RepoError:
Dirkjan Ochtman
hgweb: separate out utility functions
r6392 fctx = repo.filectx(path, fileid=changeid)
return fctx
Dirkjan Ochtman
hgweb: move the diffs() generator into webutil
r7310
Augie Fackler
formatting: blacken the codebase...
r43346
Denis Laxalde
hgweb: handle a "linerange" request parameter in filelog command...
r31665 def linerange(req):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 linerange = req.qsparams.getall(b'linerange')
Gregory Szorc
hgweb: perform all parameter lookup via qsparams...
r36881 if not linerange:
Denis Laxalde
hgweb: handle a "linerange" request parameter in filelog command...
r31665 return None
if len(linerange) > 1:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise ErrorResponse(HTTP_BAD_REQUEST, b'redundant linerange parameter')
Denis Laxalde
hgweb: handle a "linerange" request parameter in filelog command...
r31665 try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 fromline, toline = map(int, linerange[0].split(b':', 1))
Denis Laxalde
hgweb: handle a "linerange" request parameter in filelog command...
r31665 except ValueError:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise ErrorResponse(HTTP_BAD_REQUEST, b'invalid linerange parameter')
Denis Laxalde
hgweb: handle a "linerange" request parameter in filelog command...
r31665 try:
return util.processlinerange(fromline, toline)
except error.ParseError as exc:
Augie Fackler
py3: get bytes-repr of network errors portably...
r36272 raise ErrorResponse(HTTP_BAD_REQUEST, pycompat.bytestr(exc))
Denis Laxalde
hgweb: handle a "linerange" request parameter in filelog command...
r31665
Augie Fackler
formatting: blacken the codebase...
r43346
Denis Laxalde
hgweb: handle a "linerange" request parameter in filelog command...
r31665 def formatlinerange(fromline, toline):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'%d:%d' % (fromline + 1, toline)
Denis Laxalde
hgweb: handle a "linerange" request parameter in filelog command...
r31665
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
hgweb: wrap {succsandmarkers} with mappinggenerator...
r37933 def _succsandmarkersgen(context, mapping):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo = context.resource(mapping, b'repo')
Yuya Nishihara
templatekw: fix return type of {succsandmarkers} (BC)...
r37521 itemmappings = templatekw.showsuccsandmarkers(context, mapping)
for item in itemmappings.tovalue(context, mapping):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 item[b'successors'] = _siblings(
repo[successor] for successor in item[b'successors']
Augie Fackler
formatting: blacken the codebase...
r43346 )
av6
hgweb: link to successors of obsoleted changesets...
r35502 yield item
av6
hgweb: display fate of obsolete changesets...
r35501
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
hgweb: wrap {succsandmarkers} with mappinggenerator...
r37933 def succsandmarkers(context, mapping):
return templateutil.mappinggenerator(_succsandmarkersgen, args=(mapping,))
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
templatekw: switch obsfate-related template keywords to new API
r36612 # teach templater succsandmarkers is switched to (context, mapping) API
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 succsandmarkers._requires = {b'repo', b'ctx'}
Yuya Nishihara
templatekw: switch obsfate-related template keywords to new API
r36612
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
hgweb: wrap {whyunstable} with mappinggenerator...
r37934 def _whyunstablegen(context, mapping):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo = context.resource(mapping, b'repo')
ctx = context.resource(mapping, b'ctx')
av6
hgweb: explain instabilities of unstable changesets
r36973
entries = obsutil.whyunstable(repo, ctx)
for entry in entries:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if entry.get(b'divergentnodes'):
entry[b'divergentnodes'] = _siblings(entry[b'divergentnodes'])
av6
hgweb: explain instabilities of unstable changesets
r36973 yield entry
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
hgweb: wrap {whyunstable} with mappinggenerator...
r37934 def whyunstable(context, mapping):
return templateutil.mappinggenerator(_whyunstablegen, args=(mapping,))
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 whyunstable._requires = {b'repo', b'ctx'}
av6
hgweb: explain instabilities of unstable changesets
r36973
Augie Fackler
formatting: blacken the codebase...
r43346
av6
hgweb: move entry-preparing code from webcommands to webutils.commonentry()...
r27294 def commonentry(repo, ctx):
Yuya Nishihara
hgweb: use scmutil.binnode() to translate None to wdir hash (issue5988)...
r39830 node = scmutil.binnode(ctx)
av6
hgweb: move entry-preparing code from webcommands to webutils.commonentry()...
r27294 return {
Yuya Nishihara
hgweb: make templater mostly compatible with log templates...
r36535 # TODO: perhaps ctx.changectx() should be assigned if ctx is a
# filectx, but I'm not pretty sure if that would always work because
# fctx.parents() != fctx.changectx.parents() for example.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'ctx': ctx,
b'rev': ctx.rev(),
b'node': hex(node),
b'author': ctx.user(),
b'desc': ctx.description(),
b'date': ctx.date(),
b'extra': ctx.extra(),
b'phase': ctx.phasestr(),
b'obsolete': ctx.obsolete(),
b'succsandmarkers': succsandmarkers,
b'instabilities': templateutil.hybridlist(
ctx.instabilities(), name=b'instability'
Augie Fackler
formatting: blacken the codebase...
r43346 ),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'whyunstable': whyunstable,
b'branch': nodebranchnodefault(ctx),
b'inbranch': nodeinbranch(repo, ctx),
b'branches': nodebranchdict(repo, ctx),
b'tags': nodetagsdict(repo, node),
b'bookmarks': nodebookmarksdict(repo, node),
b'parent': lambda context, mapping: parents(ctx),
b'child': lambda context, mapping: children(ctx),
av6
hgweb: move entry-preparing code from webcommands to webutils.commonentry()...
r27294 }
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
hgweb: don't redundantly pass templater with requestcontext (API)...
r36901 def changelistentry(web, ctx):
Gregory Szorc
hgweb: extract changelist entry generation into own function...
r23745 '''Obtain a dictionary to be used for entries in a changelist.
This function is called when producing items for the "entries" list passed
to the "shortlog" and "changelog" templates.
'''
repo = web.repo
rev = ctx.rev()
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 = showtag(repo, b'changelogtag', n)
Yuya Nishihara
hgweb: remove unused argument 'tmpl' from listfilediffs()
r37973 files = listfilediffs(ctx.files(), n, web.maxfiles)
Gregory Szorc
hgweb: extract changelist entry generation into own function...
r23745
av6
hgweb: move entry-preparing code from webcommands to webutils.commonentry()...
r27294 entry = commonentry(repo, ctx)
Augie Fackler
formatting: blacken the codebase...
r43346 entry.update(
{
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'allparents': lambda context, mapping: parents(ctx),
b'parent': lambda context, mapping: parents(ctx, rev - 1),
b'child': lambda context, mapping: children(ctx, rev + 1),
b'changelogtag': showtags,
b'files': files,
Augie Fackler
formatting: blacken the codebase...
r43346 }
)
av6
hgweb: move entry-preparing code from webcommands to webutils.commonentry()...
r27294 return entry
Gregory Szorc
hgweb: extract changelist entry generation into own function...
r23745
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
hgweb: extract code for emitting multiple changelist records...
r38054 def changelistentries(web, revs, maxcount, parityfn):
"""Emit up to N records for an iterable of revisions."""
repo = web.repo
count = 0
for rev in revs:
if count >= maxcount:
break
count += 1
entry = changelistentry(web, repo[rev])
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 entry[b'parity'] = next(parityfn)
Gregory Szorc
hgweb: extract code for emitting multiple changelist records...
r38054
yield entry
Augie Fackler
formatting: blacken the codebase...
r43346
av6
hgweb: provide symrev (symbolic revision) property to the templates...
r25602 def symrevorshortnode(req, ctx):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'node' in req.qsparams:
return templatefilters.revescape(req.qsparams[b'node'])
av6
hgweb: provide symrev (symbolic revision) property to the templates...
r25602 else:
Yuya Nishihara
hgweb: use scmutil.binnode() to translate None to wdir hash (issue5988)...
r39830 return short(scmutil.binnode(ctx))
av6
hgweb: provide symrev (symbolic revision) property to the templates...
r25602
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
hgweb: use template context to render {files} of changesetentry()...
r37970 def _listfilesgen(context, ctx, stripecount):
Yuya Nishihara
hgweb: extract generator of {files} from changesetentry()...
r37968 parity = paritygen(stripecount)
Jordi Gutiérrez Hermoso
hgweb: add a status property to file list context...
r44115 filesadded = ctx.filesadded()
Yuya Nishihara
hgweb: extract generator of {files} from changesetentry()...
r37968 for blockno, f in enumerate(ctx.files()):
Jordi Gutiérrez Hermoso
hgweb: add a status property to file list context...
r44115 if f not in ctx:
status = b'removed'
elif f in filesadded:
status = b'added'
else:
status = b'modified'
template = b'filenolink' if status == b'removed' else b'filenodelink'
Augie Fackler
formatting: blacken the codebase...
r43346 yield context.process(
template,
{
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'node': ctx.hex(),
b'file': f,
b'blockno': blockno + 1,
b'parity': next(parity),
Jordi Gutiérrez Hermoso
hgweb: add a status property to file list context...
r44115 b'status': status,
Augie Fackler
formatting: blacken the codebase...
r43346 },
)
Yuya Nishihara
hgweb: extract generator of {files} from changesetentry()...
r37968
Gregory Szorc
hgweb: pass modern request type into various webutil functions (API)...
r36902 def changesetentry(web, ctx):
Gregory Szorc
hgweb: extract changeset template mapping generation to own function...
r24177 '''Obtain a dictionary to be used to render the "changeset" template.'''
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 showtags = showtag(web.repo, b'changesettag', scmutil.binnode(ctx))
Augie Fackler
formatting: blacken the codebase...
r43346 showbookmarks = showbookmark(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 web.repo, b'changesetbookmark', scmutil.binnode(ctx)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
hgweb: extract changeset template mapping generation to own function...
r24177 showbranch = nodebranchnodefault(ctx)
Gregory Szorc
hgweb: pass modern request type into various webutil functions (API)...
r36902 basectx = basechangectx(web.repo, web.req)
Gregory Szorc
hgweb: extract changeset template mapping generation to own function...
r24177 if basectx is None:
basectx = ctx.p1()
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']
Gregory Szorc
hgweb: extract changeset template mapping generation to own function...
r24177
Gregory Szorc
hgweb: don't redundantly pass templater with requestcontext (API)...
r36901 diff = diffs(web, ctx, basectx, None, style)
Gregory Szorc
hgweb: extract changeset template mapping generation to own function...
r24177
parity = paritygen(web.stripecount)
Yuya Nishihara
hgweb: pass ui to diffstatgen() explicitly
r38604 diffstatsgen = diffstatgen(web.repo.ui, ctx, basectx)
Yuya Nishihara
hgweb: drop unused argument 'tmpl' from webutil.diffstat()
r38070 diffstats = diffstat(ctx, diffstatsgen, parity)
Gregory Szorc
hgweb: extract changeset template mapping generation to own function...
r24177
return dict(
diff=diff,
Gregory Szorc
hgweb: pass modern request type into various webutil functions (API)...
r36902 symrev=symrevorshortnode(web.req, ctx),
Gregory Szorc
hgweb: extract changeset template mapping generation to own function...
r24177 basenode=basectx.hex(),
changesettag=showtags,
changesetbookmark=showbookmarks,
changesetbranch=showbranch,
Augie Fackler
formatting: blacken the codebase...
r43346 files=templateutil.mappedgenerator(
_listfilesgen, args=(ctx, web.stripecount)
),
Matt Harbison
templater: drop support for old style keywords (API)...
r42524 diffsummary=lambda context, mapping: diffsummary(diffstatsgen),
Gregory Szorc
hgweb: extract changeset template mapping generation to own function...
r24177 diffstat=diffstats,
archives=web.archivelist(ctx.hex()),
Augie Fackler
formatting: blacken the codebase...
r43346 **pycompat.strkwargs(commonentry(web.repo, ctx))
)
Gregory Szorc
hgweb: extract changeset template mapping generation to own function...
r24177
Yuya Nishihara
hgweb: use template context to render {files} of changelist entries...
r37972 def _listfilediffsgen(context, files, node, max):
Dirkjan Ochtman
hgweb: move another utility function into the webutil module
r7311 for f in files[:max]:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield context.process(b'filedifflink', {b'node': hex(node), b'file': f})
Dirkjan Ochtman
hgweb: move another utility function into the webutil module
r7311 if len(files) > max:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield context.process(b'fileellipses', {})
Dirkjan Ochtman
hgweb: move another utility function into the webutil module
r7311
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
hgweb: remove unused argument 'tmpl' from listfilediffs()
r37973 def listfilediffs(files, node, max):
Augie Fackler
formatting: blacken the codebase...
r43346 return templateutil.mappedgenerator(
_listfilediffsgen, args=(files, node, max)
)
Yuya Nishihara
hgweb: wrap {files} of changelist entries with mappedgenerator...
r37971
Yuya Nishihara
hgweb: use template context to render {lines} of {diff}...
r38006 def _prettyprintdifflines(context, lines, blockno, lineidprefix):
Yuya Nishihara
hgweb: move prettyprintlines() closure out of diffs()...
r38004 for lineno, l in enumerate(lines, 1):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 difflineno = b"%d.%d" % (blockno, lineno)
if l.startswith(b'+'):
ltype = b"difflineplus"
elif l.startswith(b'-'):
ltype = b"difflineminus"
elif l.startswith(b'@'):
ltype = b"difflineat"
Yuya Nishihara
hgweb: move prettyprintlines() closure out of diffs()...
r38004 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ltype = b"diffline"
Augie Fackler
formatting: blacken the codebase...
r43346 yield context.process(
ltype,
{
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'line': l,
b'lineno': lineno,
b'lineid': lineidprefix + b"l%s" % difflineno,
b'linenumber': b"% 8s" % difflineno,
Augie Fackler
formatting: blacken the codebase...
r43346 },
)
Yuya Nishihara
hgweb: move prettyprintlines() closure out of diffs()...
r38004
Augie Fackler
formatting: blacken the codebase...
r43346 def _diffsgen(
context,
repo,
ctx,
basectx,
files,
style,
stripecount,
linerange,
lineidprefix,
):
Dirkjan Ochtman
hgweb: move the diffs() generator into webutil
r7310 if files:
Martin von Zweigbergk
match: delete unused root and cwd arguments from {always,never,exact}() (API)...
r41825 m = match.exact(files)
Dirkjan Ochtman
hgweb: move the diffs() generator into webutil
r7310 else:
Martin von Zweigbergk
match: delete unused root and cwd arguments from {always,never,exact}() (API)...
r41825 m = match.always()
Dirkjan Ochtman
hgweb: move the diffs() generator into webutil
r7310
diffopts = patch.diffopts(repo.ui, untrusted=True)
Yuya Nishihara
hgweb: convert {diff} to a mappinggenerator with named template...
r38007 parity = paritygen(stripecount)
Dirkjan Ochtman
hgweb: move the diffs() generator into webutil
r7310
Martin von Zweigbergk
patch: pass in context objects into diffhunks() (API)...
r41767 diffhunks = patch.diffhunks(repo, basectx, ctx, m, opts=diffopts)
Denis Laxalde
diff: also yield file context objects in patch.trydiff() (API)...
r34856 for blockno, (fctx1, fctx2, header, hunks) in enumerate(diffhunks, 1):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if style != b'raw':
Denis Laxalde
hgweb: use patch.diffhunks in webutil.diffs to simplify the algorithm...
r31276 header = header[1:]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 lines = [h + b'\n' for h in header]
Denis Laxalde
hgweb: use patch.diffhunks in webutil.diffs to simplify the algorithm...
r31276 for hunkrange, hunklines in hunks:
Denis Laxalde
hgweb: add a 'linerange' parameter to webutil.diffs()...
r31666 if linerange is not None and hunkrange is not None:
s1, l1, s2, l2 = hunkrange
Denis Laxalde
mdiff: add a hunkinrange helper function...
r31808 if not mdiff.hunkinrange((s2, l2), linerange):
Denis Laxalde
hgweb: add a 'linerange' parameter to webutil.diffs()...
r31666 continue
Denis Laxalde
hgweb: use patch.diffhunks in webutil.diffs to simplify the algorithm...
r31276 lines.extend(hunklines)
if lines:
Augie Fackler
formatting: blacken the codebase...
r43346 l = templateutil.mappedgenerator(
_prettyprintdifflines, args=(lines, blockno, lineidprefix)
)
Yuya Nishihara
hgweb: convert {diff} to a mappinggenerator with named template...
r38007 yield {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'parity': next(parity),
b'blockno': blockno,
b'lines': l,
Yuya Nishihara
hgweb: convert {diff} to a mappinggenerator with named template...
r38007 }
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 def diffs(web, ctx, basectx, files, style, linerange=None, lineidprefix=b''):
Augie Fackler
formatting: blacken the codebase...
r43346 args = (
web.repo,
ctx,
basectx,
files,
style,
web.stripecount,
linerange,
lineidprefix,
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return templateutil.mappinggenerator(
_diffsgen, args=args, name=b'diffblock'
)
Dirkjan Ochtman
hgweb: fix up the less/more links on the graph page...
r7345
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
hgweb: convert comparison {lines} to a mappinggenerator with named template...
r38010 def _compline(type, leftlineno, leftline, rightlineno, rightline):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 lineid = leftlineno and (b"l%d" % leftlineno) or b''
lineid += rightlineno and (b"r%d" % rightlineno) or b''
llno = b'%d' % leftlineno if leftlineno else b''
rlno = b'%d' % rightlineno if rightlineno else b''
Yuya Nishihara
hgweb: convert comparison {lines} to a mappinggenerator with named template...
r38010 return {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'type': type,
b'lineid': lineid,
b'leftlineno': leftlineno,
b'leftlinenumber': b"% 6s" % llno,
b'leftline': leftline or b'',
b'rightlineno': rightlineno,
b'rightlinenumber': b"% 6s" % rlno,
b'rightline': rightline or b'',
Yuya Nishihara
hgweb: convert comparison {lines} to a mappinggenerator with named template...
r38010 }
Yuya Nishihara
hgweb: move compline() closure out of compare()
r38008
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
hgweb: convert comparison {lines} to a mappinggenerator with named template...
r38010 def _getcompblockgen(context, leftlines, rightlines, opcodes):
Yuya Nishihara
hgweb: move getblock() closure out of compare()...
r38009 for type, llo, lhi, rlo, rhi in opcodes:
Gregory Szorc
py3: convert diff opcode name to bytes...
r40192 type = pycompat.sysbytes(type)
Yuya Nishihara
hgweb: move getblock() closure out of compare()...
r38009 len1 = lhi - llo
len2 = rhi - rlo
count = min(len1, len2)
Gregory Szorc
global: use pycompat.xrange()...
r38806 for i in pycompat.xrange(count):
Augie Fackler
formatting: blacken the codebase...
r43346 yield _compline(
type=type,
leftlineno=llo + i + 1,
leftline=leftlines[llo + i],
rightlineno=rlo + i + 1,
rightline=rightlines[rlo + i],
)
Yuya Nishihara
hgweb: move getblock() closure out of compare()...
r38009 if len1 > len2:
Gregory Szorc
global: use pycompat.xrange()...
r38806 for i in pycompat.xrange(llo + count, lhi):
Augie Fackler
formatting: blacken the codebase...
r43346 yield _compline(
type=type,
leftlineno=i + 1,
leftline=leftlines[i],
rightlineno=None,
rightline=None,
)
Yuya Nishihara
hgweb: move getblock() closure out of compare()...
r38009 elif len2 > len1:
Gregory Szorc
global: use pycompat.xrange()...
r38806 for i in pycompat.xrange(rlo + count, rhi):
Augie Fackler
formatting: blacken the codebase...
r43346 yield _compline(
type=type,
leftlineno=None,
leftline=None,
rightlineno=i + 1,
rightline=rightlines[i],
)
wujek srujek
hgweb: side-by-side comparison functionality...
r17202
Yuya Nishihara
hgweb: convert comparison {lines} to a mappinggenerator with named template...
r38010 def _getcompblock(leftlines, rightlines, opcodes):
args = (leftlines, rightlines, opcodes)
Augie Fackler
formatting: blacken the codebase...
r43346 return templateutil.mappinggenerator(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _getcompblockgen, args=args, name=b'comparisonline'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Yuya Nishihara
hgweb: convert comparison {lines} to a mappinggenerator with named template...
r38010
Yuya Nishihara
hgweb: convert {comparison} to a mappinggenerator with named template...
r38012 def _comparegen(context, contextnum, leftlines, rightlines):
Yuya Nishihara
hgweb: move getblock() closure out of compare()...
r38009 '''Generator function that provides side-by-side comparison data.'''
wujek srujek
hgweb: side-by-side comparison functionality...
r17202 s = difflib.SequenceMatcher(None, leftlines, rightlines)
Yuya Nishihara
hgweb: rename 'context' argument of webutil.compare() to avoid name conflicts...
r38011 if contextnum < 0:
Yuya Nishihara
hgweb: convert comparison {lines} to a mappinggenerator with named template...
r38010 l = _getcompblock(leftlines, rightlines, s.get_opcodes())
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield {b'lines': l}
wujek srujek
hgweb: side-by-side comparison functionality...
r17202 else:
Yuya Nishihara
hgweb: rename 'context' argument of webutil.compare() to avoid name conflicts...
r38011 for oc in s.get_grouped_opcodes(n=contextnum):
Yuya Nishihara
hgweb: convert comparison {lines} to a mappinggenerator with named template...
r38010 l = _getcompblock(leftlines, rightlines, oc)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield {b'lines': l}
Yuya Nishihara
hgweb: convert {comparison} to a mappinggenerator with named template...
r38012
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
hgweb: drop unused argument 'tmpl' from webutil.compare()
r38013 def compare(contextnum, leftlines, rightlines):
Yuya Nishihara
hgweb: convert {comparison} to a mappinggenerator with named template...
r38012 args = (contextnum, leftlines, rightlines)
Augie Fackler
formatting: blacken the codebase...
r43346 return templateutil.mappinggenerator(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _comparegen, args=args, name=b'comparisonblock'
Augie Fackler
formatting: blacken the codebase...
r43346 )
wujek srujek
hgweb: side-by-side comparison functionality...
r17202
Yuya Nishihara
hgweb: pass ui to diffstatgen() explicitly
r38604 def diffstatgen(ui, ctx, basectx):
Steven Brown
web: provide diff summary to the changeset page...
r14570 '''Generator function that provides the diffstat data.'''
Steven Brown
web: provide diffstat to the changeset page...
r14490
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 diffopts = patch.diffopts(ui, {b'noprefix': False})
Augie Fackler
formatting: blacken the codebase...
r43346 stats = patch.diffstatdata(util.iterlines(ctx.diff(basectx, opts=diffopts)))
Steven Brown
web: provide diffstat to the changeset page...
r14490 maxname, maxtotal, addtotal, removetotal, binary = patch.diffstatsum(stats)
Steven Brown
web: provide diff summary to the changeset page...
r14570 while True:
yield stats, maxname, maxtotal, addtotal, removetotal, binary
Augie Fackler
formatting: blacken the codebase...
r43346
Steven Brown
web: provide diff summary to the changeset page...
r14570 def diffsummary(statgen):
'''Return a short summary of the diff.'''
timeless
py3: convert to next() function...
r29216 stats, maxname, maxtotal, addtotal, removetotal, binary = next(statgen)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return _(b' %d files changed, %d insertions(+), %d deletions(-)\n') % (
Augie Fackler
formatting: blacken the codebase...
r43346 len(stats),
addtotal,
removetotal,
)
Steven Brown
web: provide diff summary to the changeset page...
r14570
Yuya Nishihara
hgweb: use template context to render {diffstat}...
r38069 def _diffstattmplgen(context, ctx, statgen, parity):
timeless
py3: convert to next() function...
r29216 stats, maxname, maxtotal, addtotal, removetotal, binary = next(statgen)
Steven Brown
web: include all files in the diffstat...
r14561 files = ctx.files()
Steven Brown
web: provide diffstat to the changeset page...
r14490
Steven Brown
web: include all files in the diffstat...
r14561 def pct(i):
if maxtotal == 0:
return 0
return (float(i) / maxtotal) * 100
Steven Brown
web: provide diffstat to the changeset page...
r14490
Steven Brown
web: provide the file number to the diffstat templates...
r14562 fileno = 0
Steven Brown
web: include all files in the diffstat...
r14561 for filename, adds, removes, isbinary in stats:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 template = b'diffstatlink' if filename in files else b'diffstatnolink'
Steven Brown
web: include all files in the diffstat...
r14561 total = adds + removes
Steven Brown
web: provide the file number to the diffstat templates...
r14562 fileno += 1
Augie Fackler
formatting: blacken the codebase...
r43346 yield context.process(
template,
{
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'node': ctx.hex(),
b'file': filename,
b'fileno': fileno,
b'total': total,
b'addpct': pct(adds),
b'removepct': pct(removes),
b'parity': next(parity),
Augie Fackler
formatting: blacken the codebase...
r43346 },
)
Steven Brown
web: provide diffstat to the changeset page...
r14490
Yuya Nishihara
hgweb: drop unused argument 'tmpl' from webutil.diffstat()
r38070 def diffstat(ctx, statgen, parity):
Yuya Nishihara
hgweb: wrap {diffstat} with mappedgenerator...
r38068 '''Return a diffstat template for each file in the diff.'''
Yuya Nishihara
hgweb: use template context to render {diffstat}...
r38069 args = (ctx, statgen, parity)
Yuya Nishihara
hgweb: wrap {diffstat} with mappedgenerator...
r38068 return templateutil.mappedgenerator(_diffstattmplgen, args=args)
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
hgweb: lift {sessionvars} to a wrapped type...
r37714 class sessionvars(templateutil.wrapped):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 def __init__(self, vars, start=b'?'):
Yuya Nishihara
hgweb: prefix private variables of sessionvars with '_'
r37712 self._start = start
self._vars = vars
Yuya Nishihara
hgweb: make sessionvars class less dense
r37713
Dirkjan Ochtman
hgweb: fix up the less/more links on the graph page...
r7345 def __getitem__(self, key):
Yuya Nishihara
hgweb: prefix private variables of sessionvars with '_'
r37712 return self._vars[key]
Yuya Nishihara
hgweb: make sessionvars class less dense
r37713
Dirkjan Ochtman
hgweb: fix up the less/more links on the graph page...
r7345 def __setitem__(self, key, value):
Yuya Nishihara
hgweb: prefix private variables of sessionvars with '_'
r37712 self._vars[key] = value
Yuya Nishihara
hgweb: make sessionvars class less dense
r37713
Dirkjan Ochtman
hgweb: fix up the less/more links on the graph page...
r7345 def __copy__(self):
Yuya Nishihara
hgweb: prefix private variables of sessionvars with '_'
r37712 return sessionvars(copy.copy(self._vars), self._start)
Yuya Nishihara
hgweb: make sessionvars class less dense
r37713
Yuya Nishihara
templater: abstract ifcontains() over wrapped types...
r38286 def contains(self, context, mapping, item):
item = templateutil.unwrapvalue(context, mapping, item)
return item in self._vars
Yuya Nishihara
templater: promote getmember() to an interface of wrapped types
r38261 def getmember(self, context, mapping, key):
Yuya Nishihara
templater: resolve type of dict key in getmember()...
r38262 key = templateutil.unwrapvalue(context, mapping, key)
Yuya Nishihara
templater: promote getmember() to an interface of wrapped types
r38261 return self._vars.get(key)
Yuya Nishihara
templater: abstract min/max away...
r38284 def getmin(self, context, mapping):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.ParseError(_(b'not comparable'))
Yuya Nishihara
templater: abstract min/max away...
r38284
def getmax(self, context, mapping):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.ParseError(_(b'not comparable'))
Yuya Nishihara
templater: abstract min/max away...
r38284
Yuya Nishihara
templater: introduce filter() function to remove empty items from list...
r38467 def filter(self, context, mapping, select):
# implement if necessary
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.ParseError(_(b'not filterable'))
Yuya Nishihara
templater: introduce filter() function to remove empty items from list...
r38467
Yuya Nishihara
hgweb: lift {sessionvars} to a wrapped type...
r37714 def itermaps(self, context):
Yuya Nishihara
hgweb: prefix private variables of sessionvars with '_'
r37712 separator = self._start
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for key, value in sorted(pycompat.iteritems(self._vars)):
Augie Fackler
formatting: blacken the codebase...
r43346 yield {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'name': key,
b'value': pycompat.bytestr(value),
b'separator': separator,
Augie Fackler
webutil: use pycompat.bytestr() instead of str()...
r34808 }
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 separator = b'&'
Augie Fackler
hgweb: fix hgweb_mod as well as hgwebdir_mod
r12691
Yuya Nishihara
hgweb: lift {sessionvars} to a wrapped type...
r37714 def join(self, context, mapping, sep):
# could be '{separator}{name}={value|urlescape}'
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.ParseError(_(b'not displayable without template'))
Yuya Nishihara
hgweb: lift {sessionvars} to a wrapped type...
r37714
def show(self, context, mapping):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return self.join(context, b'')
Yuya Nishihara
hgweb: lift {sessionvars} to a wrapped type...
r37714
Yuya Nishihara
templater: abstract truth testing to fix {if(list_of_empty_strings)}...
r38308 def tobool(self, context, mapping):
return bool(self._vars)
Yuya Nishihara
hgweb: lift {sessionvars} to a wrapped type...
r37714 def tovalue(self, context, mapping):
return self._vars
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
hgweb: alias ui module as uimod...
r27007 class wsgiui(uimod.ui):
Augie Fackler
hgweb: fix hgweb_mod as well as hgwebdir_mod
r12691 # default termwidth breaks under mod_wsgi
def termwidth(self):
return 80
Gregory Szorc
hgweb: extract web substitutions table generation to own function...
r26162
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
hgweb: extract web substitutions table generation to own function...
r26162 def getwebsubs(repo):
websubtable = []
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 websubdefs = repo.ui.configitems(b'websub')
Gregory Szorc
hgweb: extract web substitutions table generation to own function...
r26162 # we must maintain interhg backwards compatibility
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 websubdefs += repo.ui.configitems(b'interhg')
Gregory Szorc
hgweb: extract web substitutions table generation to own function...
r26162 for key, pattern in websubdefs:
# grab the delimiter from the character after the "s"
Pulkit Goyal
py3: slice over bytes to prevent getting ascii values...
r36198 unesc = pattern[1:2]
Augie Fackler
cleanup: migrate from re.escape to stringutil.reescape...
r38494 delim = stringutil.reescape(unesc)
Gregory Szorc
hgweb: extract web substitutions table generation to own function...
r26162
# identify portions of the pattern, taking care to avoid escaped
# delimiters. the replace format and flags are optional, but
# delimiters are required.
match = re.match(
Pulkit Goyal
py3: add b'' to make sure regex pattern are bytes in hgweb/webutil.py...
r36201 br'^s%s(.+)(?:(?<=\\\\)|(?<!\\))%s(.*)%s([ilmsux])*$'
Augie Fackler
formatting: blacken the codebase...
r43346 % (delim, delim, delim),
pattern,
)
Gregory Szorc
hgweb: extract web substitutions table generation to own function...
r26162 if not match:
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"websub: invalid pattern for %s: %s\n") % (key, pattern)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
hgweb: extract web substitutions table generation to own function...
r26162 continue
# we need to unescape the delimiter for regexp and format
Pulkit Goyal
py3: add b'' to make sure regex pattern are bytes in hgweb/webutil.py...
r36201 delim_re = re.compile(br'(?<!\\)\\%s' % delim)
Gregory Szorc
hgweb: extract web substitutions table generation to own function...
r26162 regexp = delim_re.sub(unesc, match.group(1))
format = delim_re.sub(unesc, match.group(2))
# the pattern allows for 6 regexp flags, so set them if necessary
flagin = match.group(3)
flags = 0
if flagin:
Connor Sheehan
hgweb: fix websub regex flag syntax on Python 3...
r43189 for flag in pycompat.sysstr(flagin.upper()):
Gregory Szorc
hgweb: extract web substitutions table generation to own function...
r26162 flags |= re.__dict__[flag]
try:
regexp = re.compile(regexp, flags)
websubtable.append((regexp, format))
except re.error:
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"websub: invalid regexp for %s: %s\n") % (key, regexp)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
hgweb: extract web substitutions table generation to own function...
r26162 return websubtable
av6
hgweb: reuse graph node-related functions from templates...
r37928
Augie Fackler
formatting: blacken the codebase...
r43346
av6
hgweb: reuse graph node-related functions from templates...
r37928 def getgraphnode(repo, ctx):
Augie Fackler
formatting: blacken the codebase...
r43346 return templatekw.getgraphnodecurrent(
repo, ctx
) + templatekw.getgraphnodesymbol(ctx)