##// END OF EJS Templates
match: add `filepath:` pattern to match an exact filepath relative to the root...
match: add `filepath:` pattern to match an exact filepath relative to the root It's useful in certain automated workflows to make sure we recurse in directories whose name conflicts with files in other revisions. In addition it makes it possible to avoid building a potentially costly regex, improving performance when the set of files to match explicitly is large. The benchmark below are run in the following configuration : # data-env-vars.name = mozilla-central-2018-08-01-zstd-sparse-revlog # benchmark.name = files # benchmark.variants.rev = tip # benchmark.variants.files = all-list-filepath-sorted # bin-env-vars.hg.flavor = no-rust It also includes timings using the re2 engine (through the `google-re2` module) to show how much can be saved by just using a better regexp engine. Pattern time (seconds) time using re2 ----------------------------------------------------------- just "." 0.4 0.4 list of "filepath:…" 1.3 1.3 list of "path:…" 25.7 3.9 list of patterns 29.7 10.4 As you can see, Without re2, using "filepath:" instead of "path:" is a huge win. With re2, it is still about three times faster to not have to build the regex.

File last commit:

r50517:dcb2581e stable
r51588:1c31b343 default
Show More
logcmdutil.py
1293 lines | 42.8 KiB | text/x-python | PythonLexer
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 # logcmdutil.py - utility for log-like commands
#
Raphaël Gomès
contributor: change mentions of mpm to olivia...
r47575 # Copyright 2005-2007 Olivia Mackall <olivia@selenic.com>
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 #
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
import itertools
import os
Martin von Zweigbergk
patch: replace "prefix" and "relroot" arguments by "pathfn" (API)...
r41795 import posixpath
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
from .i18n import _
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 from .node import nullrev, wdirrev
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Yuya Nishihara
log: introduce struct that carries log traversal options...
r46139 from .thirdparty import attr
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 from . import (
dagop,
error,
formatter,
graphmod,
match as matchmod,
mdiff,
Martin von Zweigbergk
diff: extract function for getting possibly re-merged parent to diff against...
r47247 merge,
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 patch,
pathutil,
pycompat,
revset,
revsetlang,
scmutil,
smartset,
templatekw,
templater,
util,
)
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 from .utils import (
dateutil,
stringutil,
)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
typing: consolidate "if not globals():" trick...
r44212 if pycompat.TYPE_CHECKING:
Augie Fackler
logcmdutil: add a type annotation...
r44100 from typing import (
Any,
Yuya Nishihara
log: extract function that builds (revs, makefilematcher) from walkopts...
r46203 Callable,
Yuya Nishihara
log: introduce struct that carries log traversal options...
r46139 Dict,
Yuya Nishihara
typing: fix return type of logcmdutil.getrevs()...
r44213 Optional,
Matt Harbison
typing: switch an argument type to the generic form...
r47509 Sequence,
Augie Fackler
logcmdutil: add a type annotation...
r44100 Tuple,
)
Matt Harbison
typing: drop annotations on `mercurial/logcmdutil.walkopts` attributes...
r48827 for t in (Any, Callable, Dict, Optional, Tuple):
Augie Fackler
logcmdutil: add a type annotation...
r44100 assert t
Yuya Nishihara
logcmdutil: drop redundant "log" from function names (API)...
r35905 def getlimit(opts):
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 """get the log limit according to option -l/--limit"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 limit = opts.get(b'limit')
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if limit:
try:
limit = int(limit)
except ValueError:
Martin von Zweigbergk
logcmdutil: raise `InputError` on bad CLI arguments...
r49401 raise error.InputError(_(b'limit must be a positive integer'))
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if limit <= 0:
Martin von Zweigbergk
logcmdutil: raise `InputError` on bad CLI arguments...
r49401 raise error.InputError(_(b'limit must be positive'))
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 else:
limit = None
return limit
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
diff: extract function for getting possibly re-merged parent to diff against...
r47247 def diff_parent(ctx):
"""get the context object to use as parent when diffing
If diff.merge is enabled, an overlayworkingctx of the auto-merged parents will be returned.
"""
repo = ctx.repo()
Joerg Sonnenberger
refactor: prefer checks against nullrev over nullid...
r47601 if repo.ui.configbool(b"diff", b"merge") and ctx.p2().rev() != nullrev:
Martin von Zweigbergk
diff: extract function for getting possibly re-merged parent to diff against...
r47247 # avoid cycle context -> subrepo -> cmdutil -> logcmdutil
from . import context
wctx = context.overlayworkingctx(repo)
wctx.setbase(ctx.p1())
with repo.ui.configoverride(
{
(
b"ui",
b"forcemerge",
): b"internal:merge3-lie-about-conflicts",
},
b"merge-diff",
):
Martin von Zweigbergk
ui: add a context manager for silencing the ui (pushbuffer+popbuffer)...
r48230 with repo.ui.silent():
merge.merge(ctx.p2(), wc=wctx)
Martin von Zweigbergk
diff: extract function for getting possibly re-merged parent to diff against...
r47247 return wctx
else:
return ctx.p1()
Augie Fackler
formatting: blacken the codebase...
r43346 def diffordiffstat(
ui,
repo,
diffopts,
Augie Fackler
cleanup: avoid extra node/ctx conversions in logcmdutil.diffordiffstat...
r45340 ctx1,
ctx2,
Augie Fackler
formatting: blacken the codebase...
r43346 match,
changes=None,
stat=False,
fp=None,
graphwidth=0,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 prefix=b'',
root=b'',
Augie Fackler
formatting: blacken the codebase...
r43346 listsubrepos=False,
hunksfilterfn=None,
):
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 '''show diff or diffstat.'''
if root:
relroot = pathutil.canonpath(repo.root, repo.getcwd(), root)
else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 relroot = b''
Martin von Zweigbergk
patch: accept second matcher that applies only to copy sources (API)...
r41769 copysourcematch = None
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
diff: make `hg diff --root=subrepo` work...
r41796 def compose(f, g):
return lambda x: f(g(x))
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
patch: replace "prefix" and "relroot" arguments by "pathfn" (API)...
r41795 def pathfn(f):
return posixpath.join(prefix, f)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if relroot != b'':
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 # XXX relative roots currently don't work if the root is within a
# subrepo
Martin von Zweigbergk
diff: respect ui.relative-paths for warning about path outside --root...
r41804 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
uirelroot = uipathfn(pathfn(relroot))
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 relroot += b'/'
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 for matchroot in match.files():
if not matchroot.startswith(relroot):
Augie Fackler
formatting: blacken the codebase...
r43346 ui.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'warning: %s not inside relative root %s\n')
Augie Fackler
formatting: blacken the codebase...
r43346 % (uipathfn(pathfn(matchroot)), uirelroot)
)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 relrootmatch = scmutil.match(ctx2, pats=[relroot], default=b'path')
Martin von Zweigbergk
patch: let caller pass in root-filtering matcher (API)...
r41768 match = matchmod.intersectmatchers(match, relrootmatch)
Martin von Zweigbergk
patch: accept second matcher that applies only to copy sources (API)...
r41769 copysourcematch = relrootmatch
Martin von Zweigbergk
patch: let caller pass in root-filtering matcher (API)...
r41768
Augie Fackler
formatting: blacken the codebase...
r43346 checkroot = repo.ui.configbool(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'devel', b'all-warnings'
) or repo.ui.configbool(b'devel', b'check-relroot')
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
diff: make `hg diff --root=subrepo` work...
r41796 def relrootpathfn(f):
Martin von Zweigbergk
patch: replace "prefix" and "relroot" arguments by "pathfn" (API)...
r41795 if checkroot and not f.startswith(relroot):
raise AssertionError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"file %s doesn't start with relroot %s" % (f, relroot)
Augie Fackler
formatting: blacken the codebase...
r43346 )
return f[len(relroot) :]
Martin von Zweigbergk
diff: make `hg diff --root=subrepo` work...
r41796 pathfn = compose(relrootpathfn, pathfn)
Martin von Zweigbergk
patch: replace "prefix" and "relroot" arguments by "pathfn" (API)...
r41795
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if stat:
diffopts = diffopts.copy(context=0, noprefix=False)
width = 80
if not ui.plain():
Navaneeth Suresh
log: fix line wrap on diffstat with -G/--graph (issue5800)...
r41129 width = ui.termwidth() - graphwidth
Martin von Zweigbergk
diff: make --stat respect ui.relative-paths...
r41819 # If an explicit --root was given, don't respect ui.relative-paths
if not relroot:
pathfn = compose(scmutil.getuipathfn(repo), pathfn)
Joerg Sonnenberger
diff: improve ui.write performance when not coloring on Windows...
r35979
Augie Fackler
formatting: blacken the codebase...
r43346 chunks = ctx2.diff(
ctx1,
match,
changes,
opts=diffopts,
pathfn=pathfn,
copysourcematch=copysourcematch,
hunksfilterfn=hunksfilterfn,
)
Joerg Sonnenberger
diff: improve ui.write performance when not coloring on Windows...
r35979
if fp is not None or ui.canwritewithoutlabels():
Yuya Nishihara
diff: remove fp.write() wrapper which drops label argument...
r36025 out = fp or ui
Joerg Sonnenberger
diff: improve ui.write performance when not coloring on Windows...
r35979 if stat:
Gregory Szorc
py3: preserve chunks as an iterable of bytes...
r36132 chunks = [patch.diffstat(util.iterlines(chunks), width=width)]
Joerg Sonnenberger
diff: improve ui.write performance when not coloring on Windows...
r35979 for chunk in util.filechunkiter(util.chunkbuffer(chunks)):
Yuya Nishihara
diff: remove fp.write() wrapper which drops label argument...
r36025 out.write(chunk)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 else:
Joerg Sonnenberger
diff: improve ui.write performance when not coloring on Windows...
r35979 if stat:
chunks = patch.diffstatui(util.iterlines(chunks), width=width)
else:
Augie Fackler
formatting: blacken the codebase...
r43346 chunks = patch.difflabel(
lambda chunks, **kwargs: chunks, chunks, opts=diffopts
)
Joerg Sonnenberger
diff: improve ui.write performance when not coloring on Windows...
r35979 if ui.canbatchlabeledwrites():
Augie Fackler
formatting: blacken the codebase...
r43346
Joerg Sonnenberger
diff: improve ui.write performance when not coloring on Windows...
r35979 def gen():
for chunk, label in chunks:
yield ui.label(chunk, label=label)
Augie Fackler
formatting: blacken the codebase...
r43346
Joerg Sonnenberger
diff: improve ui.write performance when not coloring on Windows...
r35979 for chunk in util.filechunkiter(util.chunkbuffer(gen())):
Yuya Nishihara
diff: remove fp.write() wrapper which drops label argument...
r36025 ui.write(chunk)
Joerg Sonnenberger
diff: improve ui.write performance when not coloring on Windows...
r35979 else:
for chunk, label in chunks:
Yuya Nishihara
diff: remove fp.write() wrapper which drops label argument...
r36025 ui.write(chunk, label=label)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Augie Fackler
cleanup: avoid extra node/ctx conversions in logcmdutil.diffordiffstat...
r45340 node2 = ctx2.node()
Matt Harbison
diff: support diffing explicit files in subrepos...
r42177 for subpath, sub in scmutil.itersubrepos(ctx1, ctx2):
tempnode2 = node2
try:
if node2 is not None:
tempnode2 = ctx2.substate[subpath][1]
except KeyError:
# A subrepo that existed in node1 was deleted between node1 and
# node2 (inclusive). Thus, ctx2's substate won't contain that
# subpath. The best we can do is to ignore it.
tempnode2 = None
submatch = matchmod.subdirmatcher(subpath, match)
subprefix = repo.wvfs.reljoin(prefix, subpath)
if listsubrepos or match.exact(subpath) or any(submatch.files()):
Augie Fackler
formatting: blacken the codebase...
r43346 sub.diff(
ui,
diffopts,
tempnode2,
submatch,
changes=changes,
stat=stat,
fp=fp,
prefix=subprefix,
)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Gregory Szorc
py3: use class X: instead of class X(object):...
r49801 class changesetdiffer:
Yuya Nishihara
log: pack filematcher and hunksfilter into changesetdiffer object...
r36024 """Generate diff of changeset with pre-configured filtering functions"""
def _makefilematcher(self, ctx):
return scmutil.matchall(ctx.repo())
def _makehunksfilter(self, ctx):
return None
Navaneeth Suresh
log: fix line wrap on diffstat with -G/--graph (issue5800)...
r41129 def showdiff(self, ui, ctx, diffopts, graphwidth=0, stat=False):
Augie Fackler
formatting: blacken the codebase...
r43346 diffordiffstat(
ui,
Augie Fackler
cleanup: avoid extra node/ctx conversions in logcmdutil.diffordiffstat...
r45340 ctx.repo(),
Augie Fackler
formatting: blacken the codebase...
r43346 diffopts,
Martin von Zweigbergk
log: respect diff.merge in -p output...
r47248 diff_parent(ctx),
Augie Fackler
cleanup: avoid extra node/ctx conversions in logcmdutil.diffordiffstat...
r45340 ctx,
Augie Fackler
formatting: blacken the codebase...
r43346 match=self._makefilematcher(ctx),
stat=stat,
graphwidth=graphwidth,
hunksfilterfn=self._makehunksfilter(ctx),
)
Yuya Nishihara
log: pack filematcher and hunksfilter into changesetdiffer object...
r36024
Yuya Nishihara
logcmdutil: rename classes and functions to conform to our coding style (API)...
r35904 def changesetlabels(ctx):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 labels = [b'log.changeset', b'changeset.%s' % ctx.phasestr()]
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if ctx.obsolete():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 labels.append(b'changeset.obsolete')
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if ctx.isunstable():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 labels.append(b'changeset.unstable')
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 for instability in ctx.instabilities():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 labels.append(b'instability.%s' % instability)
return b' '.join(labels)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
py3: use class X: instead of class X(object):...
r49801 class changesetprinter:
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 '''show changeset information when templating not requested.'''
Yuya Nishihara
log: pack filematcher and hunksfilter into changesetdiffer object...
r36024 def __init__(self, ui, repo, differ=None, diffopts=None, buffered=False):
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 self.ui = ui
self.repo = repo
self.buffered = buffered
Yuya Nishihara
log: pack filematcher and hunksfilter into changesetdiffer object...
r36024 self._differ = differ or changesetdiffer()
Yuya Nishihara
log: cache diffopts instance...
r37858 self._diffopts = patch.diffallopts(ui, diffopts)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._includestat = diffopts and diffopts.get(b'stat')
self._includediff = diffopts and diffopts.get(b'patch')
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 self.header = {}
self.hunk = {}
self.lastheader = None
self.footer = None
self._columns = templatekw.getlogcolumns()
def flush(self, ctx):
rev = ctx.rev()
if rev in self.header:
h = self.header[rev]
if h != self.lastheader:
self.lastheader = h
self.ui.write(h)
del self.header[rev]
if rev in self.hunk:
self.ui.write(self.hunk[rev])
del self.hunk[rev]
def close(self):
if self.footer:
self.ui.write(self.footer)
Yuya Nishihara
logcmdutil: hold makefilematcher/makehunksfilter() by changesetpriner (API)...
r36020 def show(self, ctx, copies=None, **props):
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 props = pycompat.byteskwargs(props)
if self.buffered:
self.ui.pushbuffer(labeled=True)
Yuya Nishihara
logcmdutil: hold makefilematcher/makehunksfilter() by changesetpriner (API)...
r36020 self._show(ctx, copies, props)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 self.hunk[ctx.rev()] = self.ui.popbuffer()
else:
Yuya Nishihara
logcmdutil: hold makefilematcher/makehunksfilter() by changesetpriner (API)...
r36020 self._show(ctx, copies, props)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Yuya Nishihara
logcmdutil: hold makefilematcher/makehunksfilter() by changesetpriner (API)...
r36020 def _show(self, ctx, copies, props):
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 '''show a single changeset or file revision'''
changenode = ctx.node()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 graphwidth = props.get(b'graphwidth', 0)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
if self.ui.quiet:
Augie Fackler
formatting: blacken the codebase...
r43346 self.ui.write(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"%s\n" % scmutil.formatchangeid(ctx), label=b'log.node'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 return
columns = self._columns
Augie Fackler
formatting: blacken the codebase...
r43346 self.ui.write(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 columns[b'changeset'] % scmutil.formatchangeid(ctx),
Augie Fackler
formatting: blacken the codebase...
r43346 label=changesetlabels(ctx),
)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
# branches are shown first before any other names due to backwards
# compatibility
branch = ctx.branch()
# don't show the default branch name
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if branch != b'default':
self.ui.write(columns[b'branch'] % branch, label=b'log.branch')
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Gregory Szorc
global: bulk replace simple pycompat.iteritems(x) with x.items()...
r49768 for nsname, ns in self.repo.names.items():
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 # branches has special logic already handled above, so here we just
# skip it
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if nsname == b'branches':
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 continue
# we will use the templatename as the color name since those two
# should be the same
for name in ns.names(self.repo, changenode):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.ui.write(ns.logfmt % name, label=b'log.%s' % ns.colorname)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if self.ui.debugflag:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.ui.write(
columns[b'phase'] % ctx.phasestr(), label=b'log.phase'
)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 for pctx in scmutil.meaningfulparents(self.repo, ctx):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 label = b'log.parent changeset.%s' % pctx.phasestr()
Augie Fackler
formatting: blacken the codebase...
r43346 self.ui.write(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 columns[b'parent'] % scmutil.formatchangeid(pctx), label=label
Augie Fackler
formatting: blacken the codebase...
r43346 )
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Yuya Nishihara
log: fill in pseudo rev and node as wdir() manifest identifiers...
r39832 if self.ui.debugflag:
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 mnode = ctx.manifestnode()
Yuya Nishihara
log: fill in pseudo rev and node as wdir() manifest identifiers...
r39832 if mnode is None:
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 mnode = self.repo.nodeconstants.wdirid
Yuya Nishihara
log: fill in pseudo rev and node as wdir() manifest identifiers...
r39832 mrev = wdirrev
else:
mrev = self.repo.manifestlog.rev(mnode)
Augie Fackler
formatting: blacken the codebase...
r43346 self.ui.write(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 columns[b'manifest']
Augie Fackler
formatting: blacken the codebase...
r43346 % scmutil.formatrevnode(self.ui, mrev, mnode),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 label=b'ui.debug log.manifest',
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.ui.write(columns[b'user'] % ctx.user(), label=b'log.user')
Augie Fackler
formatting: blacken the codebase...
r43346 self.ui.write(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 columns[b'date'] % dateutil.datestr(ctx.date()), label=b'log.date'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
if ctx.isunstable():
instabilities = ctx.instabilities()
Augie Fackler
formatting: blacken the codebase...
r43346 self.ui.write(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 columns[b'instability'] % b', '.join(instabilities),
label=b'log.instability',
Augie Fackler
formatting: blacken the codebase...
r43346 )
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
elif ctx.obsolete():
self._showobsfate(ctx)
self._exthook(ctx)
if self.ui.debugflag:
Augie Fackler
logcmdutil: use field names instead of field numbers on scmutil.status...
r44047 for key, value in zip(
[b'files', b'files+', b'files-'],
av6
logcmdutil: use the same data as {file*} template keywords (issue6642)...
r50210 [ctx.filesmodified(), ctx.filesadded(), ctx.filesremoved()],
Augie Fackler
logcmdutil: use field names instead of field numbers on scmutil.status...
r44047 ):
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if value:
Augie Fackler
formatting: blacken the codebase...
r43346 self.ui.write(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 columns[key] % b" ".join(value),
label=b'ui.debug log.files',
Augie Fackler
formatting: blacken the codebase...
r43346 )
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 elif ctx.files() and self.ui.verbose:
Augie Fackler
formatting: blacken the codebase...
r43346 self.ui.write(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 columns[b'files'] % b" ".join(ctx.files()),
label=b'ui.note log.files',
Augie Fackler
formatting: blacken the codebase...
r43346 )
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if copies and self.ui.verbose:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 copies = [b'%s (%s)' % c for c in copies]
Augie Fackler
formatting: blacken the codebase...
r43346 self.ui.write(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 columns[b'copies'] % b' '.join(copies),
label=b'ui.note log.copies',
Augie Fackler
formatting: blacken the codebase...
r43346 )
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
extra = ctx.extra()
if extra and self.ui.debugflag:
for key, value in sorted(extra.items()):
Augie Fackler
formatting: blacken the codebase...
r43346 self.ui.write(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 columns[b'extra'] % (key, stringutil.escapestr(value)),
label=b'ui.debug log.extra',
Augie Fackler
formatting: blacken the codebase...
r43346 )
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
description = ctx.description().strip()
if description:
if self.ui.verbose:
Augie Fackler
formatting: blacken the codebase...
r43346 self.ui.write(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"description:\n"), label=b'ui.note log.description'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.ui.write(description, label=b'ui.note log.description')
self.ui.write(b"\n\n")
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 else:
Augie Fackler
formatting: blacken the codebase...
r43346 self.ui.write(
Martin von Zweigbergk
logcmdutil: use new function for getting first line of string...
r49893 columns[b'summary'] % stringutil.firstline(description),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 label=b'log.summary',
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.ui.write(b"\n")
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Navaneeth Suresh
log: fix line wrap on diffstat with -G/--graph (issue5800)...
r41129 self._showpatch(ctx, graphwidth)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
def _showobsfate(self, ctx):
Yuya Nishihara
log: do not invoke templatekw.showobsfate() as a function...
r36534 # TODO: do not depend on templater
tres = formatter.templateresources(self.repo.ui, self.repo)
Augie Fackler
formatting: blacken the codebase...
r43346 t = formatter.maketemplater(
self.repo.ui,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'{join(obsfate, "\n")}',
Augie Fackler
formatting: blacken the codebase...
r43346 defaults=templatekw.keywords,
resources=tres,
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 obsfate = t.renderdefault({b'ctx': ctx}).splitlines()
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
if obsfate:
for obsfateline in obsfate:
Augie Fackler
formatting: blacken the codebase...
r43346 self.ui.write(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._columns[b'obsolete'] % obsfateline,
label=b'log.obsfate',
Augie Fackler
formatting: blacken the codebase...
r43346 )
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
def _exthook(self, ctx):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """empty method used by extension as a hook point"""
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Navaneeth Suresh
log: fix line wrap on diffstat with -G/--graph (issue5800)...
r41129 def _showpatch(self, ctx, graphwidth=0):
Yuya Nishihara
log: consume --stat/patch options at constructor of changesetprinter...
r37859 if self._includestat:
Augie Fackler
formatting: blacken the codebase...
r43346 self._differ.showdiff(
self.ui, ctx, self._diffopts, graphwidth, stat=True
)
Yuya Nishihara
log: consume --stat/patch options at constructor of changesetprinter...
r37859 if self._includestat and self._includediff:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.ui.write(b"\n")
Yuya Nishihara
log: consume --stat/patch options at constructor of changesetprinter...
r37859 if self._includediff:
Augie Fackler
formatting: blacken the codebase...
r43346 self._differ.showdiff(
self.ui, ctx, self._diffopts, graphwidth, stat=False
)
Yuya Nishihara
log: consume --stat/patch options at constructor of changesetprinter...
r37859 if self._includestat or self._includediff:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.ui.write(b"\n")
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
logcmdutil: pass formatter to jsonchangeset as argument...
r37791 class changesetformatter(changesetprinter):
"""Format changeset information by generic formatter"""
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Augie Fackler
formatting: blacken the codebase...
r43346 def __init__(
self, ui, repo, fm, differ=None, diffopts=None, buffered=False
):
Yuya Nishihara
log: pack filematcher and hunksfilter into changesetdiffer object...
r36024 changesetprinter.__init__(self, ui, repo, differ, diffopts, buffered)
Yuya Nishihara
log: cache diffopts instance...
r37858 self._diffopts = patch.difffeatureopts(ui, diffopts, git=True)
Yuya Nishihara
logcmdutil: pass formatter to jsonchangeset as argument...
r37791 self._fm = fm
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
def close(self):
Yuya Nishihara
logcmdutil: rewrite jsonchangeset printer to be backed by jsonformatter...
r37790 self._fm.end()
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Yuya Nishihara
logcmdutil: hold makefilematcher/makehunksfilter() by changesetpriner (API)...
r36020 def _show(self, ctx, copies, props):
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 '''show a single changeset or file revision'''
Yuya Nishihara
logcmdutil: rewrite jsonchangeset printer to be backed by jsonformatter...
r37790 fm = self._fm
fm.startitem()
Yuya Nishihara
log: make changesetformatter pass in changectx to formatter...
r39741 fm.context(ctx=ctx)
Augie Fackler
formatting: blacken the codebase...
r43346 fm.data(rev=scmutil.intrev(ctx), node=fm.hexfunc(scmutil.binnode(ctx)))
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Yuya Nishihara
log: populate keywords if specified in custom -Tjson(...) or -Tcbor(...)...
r43372 datahint = fm.datahint()
if self.ui.quiet and not datahint:
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 return
Augie Fackler
formatting: blacken the codebase...
r43346 fm.data(
branch=ctx.branch(),
phase=ctx.phasestr(),
user=ctx.user(),
date=fm.formatdate(ctx.date()),
desc=ctx.description(),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 bookmarks=fm.formatlist(ctx.bookmarks(), name=b'bookmark'),
tags=fm.formatlist(ctx.tags(), name=b'tag'),
Augie Fackler
formatting: blacken the codebase...
r43346 parents=fm.formatlist(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 [fm.hexfunc(c.node()) for c in ctx.parents()], name=b'node'
Augie Fackler
formatting: blacken the codebase...
r43346 ),
)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Yuya Nishihara
log: populate keywords if specified in custom -Tjson(...) or -Tcbor(...)...
r43372 if self.ui.debugflag or b'manifest' in datahint:
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 fm.data(
manifest=fm.hexfunc(
ctx.manifestnode() or self.repo.nodeconstants.wdirid
)
)
Yuya Nishihara
log: populate keywords if specified in custom -Tjson(...) or -Tcbor(...)...
r43372 if self.ui.debugflag or b'extra' in datahint:
fm.data(extra=fm.formatdict(ctx.extra()))
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Yuya Nishihara
log: populate keywords if specified in custom -Tjson(...) or -Tcbor(...)...
r43372 if (
self.ui.debugflag
or b'modified' in datahint
or b'added' in datahint
or b'removed' in datahint
):
Augie Fackler
formatting: blacken the codebase...
r43346 fm.data(
av6
logcmdutil: use the same data as {file*} template keywords (issue6642)...
r50210 modified=fm.formatlist(ctx.filesmodified(), name=b'file'),
added=fm.formatlist(ctx.filesadded(), name=b'file'),
removed=fm.formatlist(ctx.filesremoved(), name=b'file'),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Yuya Nishihara
log: populate keywords if specified in custom -Tjson(...) or -Tcbor(...)...
r43372 verbose = not self.ui.debugflag and self.ui.verbose
if verbose or b'files' in datahint:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 fm.data(files=fm.formatlist(ctx.files(), name=b'file'))
Yuya Nishihara
log: populate keywords if specified in custom -Tjson(...) or -Tcbor(...)...
r43372 if verbose and copies or b'copies' in datahint:
fm.data(
copies=fm.formatdict(copies or {}, key=b'name', value=b'source')
)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Yuya Nishihara
log: populate keywords if specified in custom -Tjson(...) or -Tcbor(...)...
r43372 if self._includestat or b'diffstat' in datahint:
Yuya Nishihara
logcmdutil: unindent diff generator of changesetprinter...
r36021 self.ui.pushbuffer()
Yuya Nishihara
log: cache diffopts instance...
r37858 self._differ.showdiff(self.ui, ctx, self._diffopts, stat=True)
Yuya Nishihara
logcmdutil: rewrite jsonchangeset printer to be backed by jsonformatter...
r37790 fm.data(diffstat=self.ui.popbuffer())
Yuya Nishihara
log: populate keywords if specified in custom -Tjson(...) or -Tcbor(...)...
r43372 if self._includediff or b'diff' in datahint:
Yuya Nishihara
logcmdutil: unindent diff generator of changesetprinter...
r36021 self.ui.pushbuffer()
Yuya Nishihara
log: cache diffopts instance...
r37858 self._differ.showdiff(self.ui, ctx, self._diffopts, stat=False)
Yuya Nishihara
logcmdutil: rewrite jsonchangeset printer to be backed by jsonformatter...
r37790 fm.data(diff=self.ui.popbuffer())
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
logcmdutil: rename classes and functions to conform to our coding style (API)...
r35904 class changesettemplater(changesetprinter):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """format changeset information.
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Note: there are a variety of convenience functions to build a
Yuya Nishihara
logcmdutil: rename classes and functions to conform to our coding style (API)...
r35904 changesettemplater for common cases. See functions such as:
Yuya Nishihara
logcmdutil: drop redundant "log" from function names (API)...
r35905 maketemplater, changesetdisplayer, buildcommittemplate, or other
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 functions that use changesest_templater.
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
# Arguments before "buffered" used to be positional. Consider not
# adding/removing arguments before "buffered" to not break callers.
Augie Fackler
formatting: blacken the codebase...
r43346 def __init__(
self, ui, repo, tmplspec, differ=None, diffopts=None, buffered=False
):
Yuya Nishihara
log: pack filematcher and hunksfilter into changesetdiffer object...
r36024 changesetprinter.__init__(self, ui, repo, differ, diffopts, buffered)
Yuya Nishihara
log: do no expect templateresources() returning a dict...
r37090 # tres is shared with _graphnodeformatter()
self._tresources = tres = formatter.templateresources(ui, repo)
Augie Fackler
formatting: blacken the codebase...
r43346 self.t = formatter.loadtemplater(
ui,
tmplspec,
defaults=templatekw.keywords,
resources=tres,
cache=templatekw.defaulttempl,
)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 self._counter = itertools.count()
self._tref = tmplspec.ref
Augie Fackler
formatting: blacken the codebase...
r43346 self._parts = {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'header': b'',
b'footer': b'',
Augie Fackler
formatting: blacken the codebase...
r43346 tmplspec.ref: tmplspec.ref,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'docheader': b'',
b'docfooter': b'',
b'separator': b'',
Augie Fackler
formatting: blacken the codebase...
r43346 }
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if tmplspec.mapfile:
# find correct templates for current mode, for backward
# compatibility with 'log -v/-q/--debug' using a mapfile
tmplmodes = [
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 (True, b''),
(self.ui.verbose, b'_verbose'),
(self.ui.quiet, b'_quiet'),
(self.ui.debugflag, b'_debug'),
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 ]
for mode, postfix in tmplmodes:
for t in self._parts:
cur = t + postfix
if mode and cur in self.t:
self._parts[t] = cur
else:
partnames = [p for p in self._parts.keys() if p != tmplspec.ref]
m = formatter.templatepartsmap(tmplspec, self.t, partnames)
self._parts.update(m)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self._parts[b'docheader']:
self.ui.write(self.t.render(self._parts[b'docheader'], {}))
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
def close(self):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self._parts[b'docfooter']:
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if not self.footer:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.footer = b""
self.footer += self.t.render(self._parts[b'docfooter'], {})
Yuya Nishihara
logcmdutil: rename classes and functions to conform to our coding style (API)...
r35904 return super(changesettemplater, self).close()
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Yuya Nishihara
logcmdutil: hold makefilematcher/makehunksfilter() by changesetpriner (API)...
r36020 def _show(self, ctx, copies, props):
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 '''show a single changeset or file revision'''
props = props.copy()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 props[b'ctx'] = ctx
props[b'index'] = index = next(self._counter)
props[b'revcache'] = {b'copies': copies}
graphwidth = props.get(b'graphwidth', 0)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
# write separator, which wouldn't work well with the header part below
# since there's inherently a conflict between header (across items) and
# separator (per item)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self._parts[b'separator'] and index > 0:
self.ui.write(self.t.render(self._parts[b'separator'], {}))
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
# write header
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self._parts[b'header']:
h = self.t.render(self._parts[b'header'], props)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if self.buffered:
self.header[ctx.rev()] = h
else:
if self.lastheader != h:
self.lastheader = h
self.ui.write(h)
# write changeset metadata, then patch if requested
key = self._parts[self._tref]
Yuya Nishihara
templater: factor out helper that renders named template as string...
r37004 self.ui.write(self.t.render(key, props))
Denis Laxalde
logcmdutil: call _exthook() in changesettemplater...
r44282 self._exthook(ctx)
Navaneeth Suresh
log: fix line wrap on diffstat with -G/--graph (issue5800)...
r41129 self._showpatch(ctx, graphwidth)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self._parts[b'footer']:
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if not self.footer:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.footer = self.t.render(self._parts[b'footer'], props)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
logcmdutil: drop redundant "log" from function names (API)...
r35905 def templatespec(tmpl, mapfile):
Martin von Zweigbergk
templatespec: logcmdutil.templatespec() gets either template or mapfile...
r45825 assert not (tmpl and mapfile)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if mapfile:
Martin von Zweigbergk
templatespec: logcmdutil.templatespec() gets either template or mapfile...
r45825 return formatter.mapfile_templatespec(b'changeset', mapfile)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 else:
Martin von Zweigbergk
templatespec: logcmdutil.templatespec() gets either template or mapfile...
r45825 return formatter.literal_templatespec(tmpl)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
logcmdutil: drop redundant "log" from function names (API)...
r35905 def _lookuptemplate(ui, tmpl, style):
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 """Find the template matching the given template spec or style
See formatter.lookuptemplate() for details.
"""
# ui settings
Augie Fackler
formatting: blacken the codebase...
r43346 if not tmpl and not style: # template are stronger than style
Martin von Zweigbergk
config: add a new [command-templates] section for templates defined by hg...
r46350 tmpl = ui.config(b'command-templates', b'log')
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if tmpl:
Martin von Zweigbergk
templatespec: use new factory functions in logcmdutil...
r45827 return formatter.literal_templatespec(templater.unquotestring(tmpl))
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 style = util.expandpath(ui.config(b'ui', b'style'))
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
if not tmpl and style:
mapfile = style
Martin von Zweigbergk
templater: pass opened file-like object to templatespec...
r45870 fp = None
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if not os.path.split(mapfile)[0]:
Martin von Zweigbergk
templater: add exception-raising version of open_template()...
r45880 (mapname, fp) = templater.try_open_template(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'map-cmdline.' + mapfile
Martin von Zweigbergk
templater: add exception-raising version of open_template()...
r45880 ) or templater.try_open_template(mapfile)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if mapname:
mapfile = mapname
Martin von Zweigbergk
templater: pass opened file-like object to templatespec...
r45870 return formatter.mapfile_templatespec(b'changeset', mapfile, fp)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return formatter.lookuptemplate(ui, b'changeset', tmpl)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
logcmdutil: drop redundant "log" from function names (API)...
r35905 def maketemplater(ui, repo, tmpl, buffered=False):
Yuya Nishihara
logcmdutil: rename classes and functions to conform to our coding style (API)...
r35904 """Create a changesettemplater from a literal template 'tmpl'
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 byte-string."""
Martin von Zweigbergk
templatespec: use new factory functions in logcmdutil...
r45827 spec = formatter.literal_templatespec(tmpl)
Yuya Nishihara
logcmdutil: rename classes and functions to conform to our coding style (API)...
r35904 return changesettemplater(ui, repo, spec, buffered=buffered)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
log: pack filematcher and hunksfilter into changesetdiffer object...
r36024 def changesetdisplayer(ui, repo, opts, differ=None, buffered=False):
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 """show one changeset using template or regular display.
Display format will be the first non-empty hit of:
1. option 'template'
2. option 'style'
Martin von Zweigbergk
config: add a new [command-templates] section for templates defined by hg...
r46350 3. [command-templates] setting 'log'
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 4. [ui] setting 'style'
If all of these values are either the unset or the empty string,
Yuya Nishihara
logcmdutil: rename classes and functions to conform to our coding style (API)...
r35904 regular display via changesetprinter() is done.
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 """
Yuya Nishihara
log: pack filematcher and hunksfilter into changesetdiffer object...
r36024 postargs = (differ, opts, buffered)
Yuya Nishihara
formatter: parse name of built-in formatter templates in standard way...
r43370 spec = _lookuptemplate(ui, opts.get(b'template'), opts.get(b'style'))
# machine-readable formats have slightly different keyword set than
# plain templates, which are handled by changesetformatter.
# note that {b'pickle', b'debug'} can also be added to the list if needed.
if spec.ref in {b'cbor', b'json'}:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 fm = ui.formatter(b'log', opts)
Yuya Nishihara
logcmdutil: pass formatter to jsonchangeset as argument...
r37791 return changesetformatter(ui, repo, fm, *postargs)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
if not spec.ref and not spec.tmpl and not spec.mapfile:
Yuya Nishihara
logcmdutil: hold makefilematcher/makehunksfilter() by changesetpriner (API)...
r36020 return changesetprinter(ui, repo, *postargs)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Yuya Nishihara
logcmdutil: hold makefilematcher/makehunksfilter() by changesetpriner (API)...
r36020 return changesettemplater(ui, repo, spec, *postargs)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
log: introduce struct that carries log traversal options...
r46139 @attr.s
Gregory Szorc
py3: use class X: instead of class X(object):...
r49801 class walkopts:
Yuya Nishihara
log: introduce struct that carries log traversal options...
r46139 """Options to configure a set of revisions and file matcher factory
to scan revision/file history
"""
# raw command-line parameters, which a matcher will be built from
Matt Harbison
typing: drop annotations on `mercurial/logcmdutil.walkopts` attributes...
r48827 pats = attr.ib()
opts = attr.ib()
Yuya Nishihara
log: introduce struct that carries log traversal options...
r46139
Yuya Nishihara
log: pass around --rev option by walkopts
r46142 # a list of revset expressions to be traversed; if follow, it specifies
# the start revisions
Matt Harbison
typing: drop annotations on `mercurial/logcmdutil.walkopts` attributes...
r48827 revspec = attr.ib()
Yuya Nishihara
log: pass around --rev option by walkopts
r46142
Yuya Nishihara
log: move miscellaneous filter/matcher options to walkopts...
r46201 # miscellaneous queries to filter revisions (see "hg help log" for details)
Matt Harbison
typing: drop annotations on `mercurial/logcmdutil.walkopts` attributes...
r48827 bookmarks = attr.ib(default=attr.Factory(list))
branches = attr.ib(default=attr.Factory(list))
date = attr.ib(default=None)
keywords = attr.ib(default=attr.Factory(list))
no_merges = attr.ib(default=False)
only_merges = attr.ib(default=False)
prune_ancestors = attr.ib(default=attr.Factory(list))
users = attr.ib(default=attr.Factory(list))
Yuya Nishihara
log: move miscellaneous filter/matcher options to walkopts...
r46201
# miscellaneous matcher arguments
Matt Harbison
typing: drop annotations on `mercurial/logcmdutil.walkopts` attributes...
r48827 include_pats = attr.ib(default=attr.Factory(list))
exclude_pats = attr.ib(default=attr.Factory(list))
Yuya Nishihara
log: move miscellaneous filter/matcher options to walkopts...
r46201
Yuya Nishihara
log: pass around --follow/--follow-first options by walkopts
r46140 # 0: no follow, 1: follow first, 2: follow both parents
Matt Harbison
typing: drop annotations on `mercurial/logcmdutil.walkopts` attributes...
r48827 follow = attr.ib(default=0)
Yuya Nishihara
log: pass around --follow/--follow-first options by walkopts
r46140
Yuya Nishihara
log: map --removed to walkopts.force_changelog_traversal...
r46200 # do not attempt filelog-based traversal, which may be fast but cannot
# include revisions where files were removed
Matt Harbison
typing: drop annotations on `mercurial/logcmdutil.walkopts` attributes...
r48827 force_changelog_traversal = attr.ib(default=False)
Yuya Nishihara
log: map --removed to walkopts.force_changelog_traversal...
r46200
Yuya Nishihara
grep: add option for logcmdutil.makewalker() to not filter revs by file pats...
r46224 # filter revisions by file patterns, which should be disabled only if
# you want to include revisions where files were unmodified
Matt Harbison
typing: drop annotations on `mercurial/logcmdutil.walkopts` attributes...
r48827 filter_revisions_by_pats = attr.ib(default=True)
Yuya Nishihara
grep: add option for logcmdutil.makewalker() to not filter revs by file pats...
r46224
Yuya Nishihara
log: move --graph and topo sort options to walkopts...
r46202 # sort revisions prior to traversal: 'desc', 'topo', or None
Matt Harbison
typing: drop annotations on `mercurial/logcmdutil.walkopts` attributes...
r48827 sort_revisions = attr.ib(default=None)
Yuya Nishihara
log: move --graph and topo sort options to walkopts...
r46202
Yuya Nishihara
log: parse --limit option by logcmdutil.parseopts()
r46141 # limit number of changes displayed; None means unlimited
Matt Harbison
typing: drop annotations on `mercurial/logcmdutil.walkopts` attributes...
r48827 limit = attr.ib(default=None)
Yuya Nishihara
log: parse --limit option by logcmdutil.parseopts()
r46141
Yuya Nishihara
log: introduce struct that carries log traversal options...
r46139
def parseopts(ui, pats, opts):
Matt Harbison
typing: switch an argument type to the generic form...
r47509 # type: (Any, Sequence[bytes], Dict[bytes, Any]) -> walkopts
Yuya Nishihara
log: introduce struct that carries log traversal options...
r46139 """Parse log command options into walkopts
Yuya Nishihara
log: extract function that builds (revs, makefilematcher) from walkopts...
r46203 The returned walkopts will be passed in to getrevs() or makewalker().
Yuya Nishihara
log: introduce struct that carries log traversal options...
r46139 """
Yuya Nishihara
log: pass around --follow/--follow-first options by walkopts
r46140 if opts.get(b'follow_first'):
follow = 1
elif opts.get(b'follow'):
follow = 2
else:
follow = 0
Yuya Nishihara
log: move --graph and topo sort options to walkopts...
r46202 if opts.get(b'graph'):
if ui.configbool(b'experimental', b'log.topo'):
sort_revisions = b'topo'
else:
sort_revisions = b'desc'
else:
sort_revisions = None
Yuya Nishihara
log: pass around --rev option by walkopts
r46142 return walkopts(
pats=pats,
opts=opts,
revspec=opts.get(b'rev', []),
Yuya Nishihara
log: do not override other filtering and sorting options by --bookmark...
r46656 bookmarks=opts.get(b'bookmark', []),
Yuya Nishihara
log: move miscellaneous filter/matcher options to walkopts...
r46201 # branch and only_branch are really aliases and must be handled at
# the same time
branches=opts.get(b'branch', []) + opts.get(b'only_branch', []),
date=opts.get(b'date'),
keywords=opts.get(b'keyword', []),
no_merges=bool(opts.get(b'no_merges')),
only_merges=bool(opts.get(b'only_merges')),
prune_ancestors=opts.get(b'prune', []),
users=opts.get(b'user', []),
include_pats=opts.get(b'include', []),
exclude_pats=opts.get(b'exclude', []),
Yuya Nishihara
log: pass around --rev option by walkopts
r46142 follow=follow,
Yuya Nishihara
log: map --removed to walkopts.force_changelog_traversal...
r46200 force_changelog_traversal=bool(opts.get(b'removed')),
Yuya Nishihara
log: move --graph and topo sort options to walkopts...
r46202 sort_revisions=sort_revisions,
Yuya Nishihara
log: pass around --rev option by walkopts
r46142 limit=getlimit(opts),
)
Yuya Nishihara
log: introduce struct that carries log traversal options...
r46139
def _makematcher(repo, revs, wopts):
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 """Build matcher and expanded patterns from log options
If --follow, revs are the revisions to follow from.
Returns (match, pats, slowpath) where
- match: a matcher built from the given pats and -I/-X opts
- pats: patterns used (globs are expanded on Windows)
- slowpath: True if patterns aren't as simple as scanning filelogs
"""
# pats/include/exclude are passed to match.match() directly in
Yuya Nishihara
cmdutil: remove remainder of old walkchangerevs() implementation
r46228 # _matchfiles() revset, but a log-like command should build its matcher
# with scmutil.match(). The difference is input pats are globbed on
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 # platforms without shell expansion (windows).
wctx = repo[None]
Yuya Nishihara
log: introduce struct that carries log traversal options...
r46139 match, pats = scmutil.matchandpats(wctx, wopts.pats, wopts.opts)
slowpath = match.anypats() or (
Yuya Nishihara
log: map --removed to walkopts.force_changelog_traversal...
r46200 not match.always() and wopts.force_changelog_traversal
Yuya Nishihara
log: introduce struct that carries log traversal options...
r46139 )
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if not slowpath:
Yuya Nishihara
log: pass around --rev option by walkopts
r46142 if wopts.follow and wopts.revspec:
Yuya Nishihara
log: make -frREV PATH detect missing files before falling back to slow path...
r46045 # There may be the case that a path doesn't exist in some (but
# not all) of the specified start revisions, but let's consider
# the path is valid. Missing files will be warned by the matcher.
memory-usage: fix `hg log --follow --rev R F` space complexity...
r50517 all_files = list(match.files())
missing_files = set(all_files)
files = all_files
for r in revs:
if not files:
# We don't have any file to check anymore.
break
ctx = repo[r]
for f in files:
if f in ctx:
missing_files.discard(f)
elif ctx.hasdir(f):
Yuya Nishihara
log: make -frREV PATH detect missing files before falling back to slow path...
r46045 # If a directory exists in any of the start revisions,
# take the slow path.
memory-usage: fix `hg log --follow --rev R F` space complexity...
r50517 missing_files.discard(f)
slowpath = True
# we found on slow path, no need to search for more.
files = missing_files
for f in all_files:
if f in missing_files:
Martin von Zweigbergk
logcmdutil: raise `StateError` when file to follow doesn't exist...
r49402 raise error.StateError(
Yuya Nishihara
log: make -frREV PATH detect missing files before falling back to slow path...
r46045 _(
b'cannot follow file not in any of the specified '
b'revisions: "%s"'
)
% f
)
Yuya Nishihara
log: pass around --follow/--follow-first options by walkopts
r46140 elif wopts.follow:
Yuya Nishihara
log: reorganize if-else and for loop in logcmdutil._makematcher()...
r46043 for f in match.files():
if f not in wctx:
# If the file exists, it may be a directory, so let it
# take the slow path.
if os.path.exists(repo.wjoin(f)):
slowpath = True
continue
else:
Martin von Zweigbergk
logcmdutil: raise `StateError` when file to follow doesn't exist...
r49402 raise error.StateError(
Yuya Nishihara
log: reorganize if-else and for loop in logcmdutil._makematcher()...
r46043 _(
b'cannot follow file not in parent '
b'revision: "%s"'
)
% f
)
filelog = repo.file(f)
if not filelog:
Yuya Nishihara
log: fix -fr'wdir()' PATH to follow newly added file...
r46044 # A file exists in wdir but not in history, which means
# the file isn't committed yet.
Martin von Zweigbergk
logcmdutil: raise `StateError` when file to follow doesn't exist...
r49402 raise error.StateError(
Yuya Nishihara
log: reorganize if-else and for loop in logcmdutil._makematcher()...
r46043 _(b'cannot follow nonexistent file: "%s"') % f
)
else:
for f in match.files():
filelog = repo.file(f)
if not filelog:
# A zero count may be a directory or deleted file, so
# try to find matching entries on the slow path.
slowpath = True
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
# We decided to fall back to the slowpath because at least one
# of the paths was not a file. Check to see if at least one of them
# existed in history - in that case, we'll continue down the
# slowpath; otherwise, we can turn off the slowpath
if slowpath:
for path in match.files():
Yuya Nishihara
log: fix handling of root (or empty) path provided by matcher (issue6478)...
r47352 if not path or path in repo.store:
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 break
else:
slowpath = False
return match, pats, slowpath
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 def _fileancestors(repo, revs, match, followfirst):
fctxs = []
for r in revs:
ctx = repo[r]
fctxs.extend(ctx[f].introfilectx() for f in ctx.walk(match))
# When displaying a revision with --patch --follow FILE, we have
# to know which file of the revision must be diffed. With
# --follow, we want the names of the ancestors of FILE in the
# revision, stored in "fcache". "fcache" is populated as a side effect
# of the graph traversal.
fcache = {}
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
log: pass ctx to makefilematcher() and makehunksfilter() functions...
r36019 def filematcher(ctx):
Yuya Nishihara
log: fix crash and bad filematcher lookup by -fr'wdir()' PATH...
r46019 return scmutil.matchfiles(repo, fcache.get(scmutil.intrev(ctx), []))
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
def revgen():
for rev, cs in dagop.filectxancestors(fctxs, followfirst=followfirst):
fcache[rev] = [c.path() for c in cs]
yield rev
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 return smartset.generatorset(revgen(), iterasc=False), filematcher
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
logcmdutil: drop redundant "log" from function names (API)...
r35905 def _makenofollowfilematcher(repo, pats, opts):
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 '''hook for extensions to override the filematcher for non-follow cases'''
return None
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
errors: raise InputError from revsingle() iff revset provided by the user...
r48930 def revsingle(repo, revspec, default=b'.', localalias=None):
"""Resolves user-provided revset(s) into a single revision.
This just wraps the lower-level scmutil.revsingle() in order to raise an
exception indicating user error.
"""
try:
return scmutil.revsingle(repo, revspec, default, localalias)
except error.RepoLookupError as e:
raise error.InputError(e.args[0], hint=e.hint)
Martin von Zweigbergk
errors: raise InputError from revpair() iff revset provided by the user...
r48929 def revpair(repo, revs):
"""Resolves user-provided revset(s) into two revisions.
This just wraps the lower-level scmutil.revpair() in order to raise an
exception indicating user error.
"""
try:
return scmutil.revpair(repo, revs)
except error.RepoLookupError as e:
raise error.InputError(e.args[0], hint=e.hint)
Martin von Zweigbergk
errors: raise InputError on bad revset to revrange() iff provided by the user...
r48928 def revrange(repo, specs, localalias=None):
"""Resolves user-provided revset(s).
This just wraps the lower-level scmutil.revrange() in order to raise an
exception indicating user error.
"""
try:
return scmutil.revrange(repo, specs, localalias)
except error.RepoLookupError as e:
raise error.InputError(e.args[0], hint=e.hint)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 _opt2logrevset = {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'no_merges': (b'not merge()', None),
b'only_merges': (b'merge()', None),
b'_matchfiles': (None, b'_matchfiles(%ps)'),
b'date': (b'date(%s)', None),
b'branch': (b'branch(%s)', b'%lr'),
b'_patslog': (b'filelog(%s)', b'%lr'),
b'keyword': (b'keyword(%s)', b'%lr'),
b'prune': (b'ancestors(%s)', b'not %lr'),
b'user': (b'user(%s)', b'%lr'),
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 }
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
log: introduce struct that carries log traversal options...
r46139 def _makerevset(repo, wopts, slowpath):
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 """Return a revset string built from log options and file patterns"""
Yuya Nishihara
log: move miscellaneous filter/matcher options to walkopts...
r46201 opts = {
Yuya Nishihara
log: do not accept string-matcher pattern as -u/-b/-B parameter...
r46657 b'branch': [b'literal:' + repo.lookupbranch(b) for b in wopts.branches],
Yuya Nishihara
log: move miscellaneous filter/matcher options to walkopts...
r46201 b'date': wopts.date,
b'keyword': wopts.keywords,
b'no_merges': wopts.no_merges,
b'only_merges': wopts.only_merges,
b'prune': wopts.prune_ancestors,
Yuya Nishihara
log: do not accept string-matcher pattern as -u/-b/-B parameter...
r46657 b'user': [b'literal:' + v for v in wopts.users],
Yuya Nishihara
log: move miscellaneous filter/matcher options to walkopts...
r46201 }
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Yuya Nishihara
grep: add option for logcmdutil.makewalker() to not filter revs by file pats...
r46224 if wopts.filter_revisions_by_pats and slowpath:
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 # pats/include/exclude cannot be represented as separate
# revset expressions as their filtering logic applies at file
# level. For instance "-I a -X b" matches a revision touching
# "a" and "b" while "file(a) and not file(b)" does
# not. Besides, filesets are evaluated against the working
# directory.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 matchargs = [b'r:', b'd:relpath']
Yuya Nishihara
log: introduce struct that carries log traversal options...
r46139 for p in wopts.pats:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 matchargs.append(b'p:' + p)
Yuya Nishihara
log: move miscellaneous filter/matcher options to walkopts...
r46201 for p in wopts.include_pats:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 matchargs.append(b'i:' + p)
Yuya Nishihara
log: move miscellaneous filter/matcher options to walkopts...
r46201 for p in wopts.exclude_pats:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 matchargs.append(b'x:' + p)
opts[b'_matchfiles'] = matchargs
Yuya Nishihara
grep: add option for logcmdutil.makewalker() to not filter revs by file pats...
r46224 elif wopts.filter_revisions_by_pats and not wopts.follow:
Yuya Nishihara
log: introduce struct that carries log traversal options...
r46139 opts[b'_patslog'] = list(wopts.pats)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
expr = []
Gregory Szorc
global: bulk replace simple pycompat.iteritems(x) with x.items()...
r49768 for op, val in sorted(opts.items()):
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if not val:
continue
revop, listop = _opt2logrevset[op]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if revop and b'%' not in revop:
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 expr.append(revop)
elif not listop:
expr.append(revsetlang.formatspec(revop, val))
else:
if revop:
val = [revsetlang.formatspec(revop, v) for v in val]
expr.append(revsetlang.formatspec(listop, val))
Yuya Nishihara
log: do not override other filtering and sorting options by --bookmark...
r46656 if wopts.bookmarks:
expr.append(
revsetlang.formatspec(
b'%lr',
[scmutil.format_bookmark_revspec(v) for v in wopts.bookmarks],
)
)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if expr:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 expr = b'(' + b' and '.join(expr) + b')'
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 else:
expr = None
return expr
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
log: introduce struct that carries log traversal options...
r46139 def _initialrevs(repo, wopts):
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 """Return the initial set of revisions to be filtered or followed"""
Yuya Nishihara
log: pass around --rev option by walkopts
r46142 if wopts.revspec:
Martin von Zweigbergk
errors: raise InputError on bad revset to revrange() iff provided by the user...
r48928 revs = revrange(repo, wopts.revspec)
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 elif wopts.follow and repo.dirstate.p1() == repo.nullid:
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 revs = smartset.baseset()
Yuya Nishihara
log: pass around --follow/--follow-first options by walkopts
r46140 elif wopts.follow:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 revs = repo.revs(b'.')
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 else:
revs = smartset.spanset(repo)
revs.reverse()
return revs
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
log: extract function that builds (revs, makefilematcher) from walkopts...
r46203 def makewalker(repo, wopts):
# type: (Any, walkopts) -> Tuple[smartset.abstractsmartset, Optional[Callable[[Any], matchmod.basematcher]]]
"""Build (revs, makefilematcher) to scan revision/file history
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Yuya Nishihara
log: extract function that builds (revs, makefilematcher) from walkopts...
r46203 - revs is the smartset to be traversed.
- makefilematcher is a function to map ctx to a matcher for that revision
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 """
Yuya Nishihara
log: introduce struct that carries log traversal options...
r46139 revs = _initialrevs(repo, wopts)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if not revs:
return smartset.baseset(), None
Yuya Nishihara
log: map --removed to walkopts.force_changelog_traversal...
r46200 # TODO: might want to merge slowpath with wopts.force_changelog_traversal
Yuya Nishihara
log: introduce struct that carries log traversal options...
r46139 match, pats, slowpath = _makematcher(repo, revs, wopts)
wopts = attr.evolve(wopts, pats=pats)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 filematcher = None
Yuya Nishihara
log: pass around --follow/--follow-first options by walkopts
r46140 if wopts.follow:
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if slowpath or match.always():
Yuya Nishihara
log: pass around --follow/--follow-first options by walkopts
r46140 revs = dagop.revancestors(repo, revs, followfirst=wopts.follow == 1)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 else:
Yuya Nishihara
log: map --removed to walkopts.force_changelog_traversal...
r46200 assert not wopts.force_changelog_traversal
Yuya Nishihara
log: pass around --follow/--follow-first options by walkopts
r46140 revs, filematcher = _fileancestors(
repo, revs, match, followfirst=wopts.follow == 1
)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 revs.reverse()
if filematcher is None:
Yuya Nishihara
log: introduce struct that carries log traversal options...
r46139 filematcher = _makenofollowfilematcher(repo, wopts.pats, wopts.opts)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if filematcher is None:
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
log: pass ctx to makefilematcher() and makehunksfilter() functions...
r36019 def filematcher(ctx):
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 return match
Yuya Nishihara
log: introduce struct that carries log traversal options...
r46139 expr = _makerevset(repo, wopts, slowpath)
Yuya Nishihara
log: move --graph and topo sort options to walkopts...
r46202 if wopts.sort_revisions:
assert wopts.sort_revisions in {b'topo', b'desc'}
if wopts.sort_revisions == b'topo':
Martin von Zweigbergk
log: add config for making `hg log -G` always topo-sorted...
r42500 if not revs.istopo():
revs = dagop.toposort(revs, repo.changelog.parentrevs)
# TODO: try to iterate the set lazily
Yuya Nishihara
log: flag topo-sorted set as such...
r42510 revs = revset.baseset(list(revs), istopo=True)
Martin von Zweigbergk
log: add config for making `hg log -G` always topo-sorted...
r42500 elif not (revs.isdescending() or revs.istopo()):
Yuya Nishihara
log: remove stale comment about order of user revset...
r46137 # User-specified revs might be unsorted
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 revs.sort(reverse=True)
if expr:
matcher = revset.match(None, expr)
revs = matcher(repo, revs)
Yuya Nishihara
log: parse --limit option by logcmdutil.parseopts()
r46141 if wopts.limit is not None:
revs = revs.slice(0, wopts.limit)
Yuya Nishihara
log: pack filematcher and hunksfilter into changesetdiffer object...
r36024
Yuya Nishihara
log: extract function that builds (revs, makefilematcher) from walkopts...
r46203 return revs, filematcher
def getrevs(repo, wopts):
# type: (Any, walkopts) -> Tuple[smartset.abstractsmartset, Optional[changesetdiffer]]
"""Return (revs, differ) where revs is a smartset
differ is a changesetdiffer with pre-configured file matcher.
"""
revs, filematcher = makewalker(repo, wopts)
if not revs:
return revs, None
Yuya Nishihara
log: pack filematcher and hunksfilter into changesetdiffer object...
r36024 differ = changesetdiffer()
differ._makefilematcher = filematcher
return revs, differ
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
logcmdutil: drop redundant "log" from function names (API)...
r35905 def _parselinerangeopt(repo, opts):
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 """Parse --line-range log option and return a list of tuples (filename,
(fromline, toline)).
"""
linerangebyfname = []
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for pat in opts.get(b'line_range', []):
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pat, linerange = pat.rsplit(b',', 1)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 except ValueError:
Martin von Zweigbergk
logcmdutil: raise `InputError` on bad CLI arguments...
r49401 raise error.InputError(
_(b'malformatted line-range pattern %s') % pat
)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 fromline, toline = map(int, linerange.split(b':'))
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 except ValueError:
Martin von Zweigbergk
logcmdutil: raise `InputError` on bad CLI arguments...
r49401 raise error.InputError(_(b"invalid line range for %s") % pat)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 msg = _(b"line range pattern '%s' must match exactly one file") % pat
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 fname = scmutil.parsefollowlinespattern(repo, None, pat, msg)
linerangebyfname.append(
Augie Fackler
formatting: blacken the codebase...
r43346 (fname, util.processlinerange(fromline, toline))
)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 return linerangebyfname
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
logcmdutil: drop redundant "log" from function names (API)...
r35905 def getlinerangerevs(repo, userrevs, opts):
Yuya Nishihara
log: pack filematcher and hunksfilter into changesetdiffer object...
r36024 """Return (revs, differ).
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
"revs" are revisions obtained by processing "line-range" log options and
walking block ancestors of each specified file/line-range.
Yuya Nishihara
log: pack filematcher and hunksfilter into changesetdiffer object...
r36024 "differ" is a changesetdiffer with pre-configured file matcher and hunks
filter.
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 """
wctx = repo[None]
# Two-levels map of "rev -> file ctx -> [line range]".
linerangesbyrev = {}
Yuya Nishihara
logcmdutil: drop redundant "log" from function names (API)...
r35905 for fname, (fromline, toline) in _parselinerangeopt(repo, opts):
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if fname not in wctx:
Martin von Zweigbergk
logcmdutil: raise `StateError` when file to follow doesn't exist...
r49402 raise error.StateError(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 _(b'cannot follow file not in parent revision: "%s"') % fname
Augie Fackler
formatting: blacken the codebase...
r43346 )
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 fctx = wctx.filectx(fname)
for fctx, linerange in dagop.blockancestors(fctx, fromline, toline):
rev = fctx.introrev()
Denis Laxalde
log: map None rev to wdirrev when filtering revisions with --line-range...
r44173 if rev is None:
rev = wdirrev
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if rev not in userrevs:
continue
Augie Fackler
formatting: blacken the codebase...
r43346 linerangesbyrev.setdefault(rev, {}).setdefault(
fctx.path(), []
).append(linerange)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Yuya Nishihara
logcmdutil: create hunksfilter and filematcher even if no diff option given...
r36022 def nofilterhunksfn(fctx, hunks):
return hunks
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Yuya Nishihara
logcmdutil: create hunksfilter and filematcher even if no diff option given...
r36022 def hunksfilter(ctx):
Denis Laxalde
log: map None rev to wdirrev when filtering revisions with --line-range...
r44173 fctxlineranges = linerangesbyrev.get(scmutil.intrev(ctx))
Yuya Nishihara
logcmdutil: create hunksfilter and filematcher even if no diff option given...
r36022 if fctxlineranges is None:
return nofilterhunksfn
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Yuya Nishihara
logcmdutil: create hunksfilter and filematcher even if no diff option given...
r36022 def filterfn(fctx, hunks):
lineranges = fctxlineranges.get(fctx.path())
if lineranges is not None:
for hr, lines in hunks:
Augie Fackler
formatting: blacken the codebase...
r43346 if hr is None: # binary
Yuya Nishihara
logcmdutil: create hunksfilter and filematcher even if no diff option given...
r36022 yield hr, lines
continue
Augie Fackler
formatting: blacken the codebase...
r43346 if any(mdiff.hunkinrange(hr[2:], lr) for lr in lineranges):
Yuya Nishihara
logcmdutil: create hunksfilter and filematcher even if no diff option given...
r36022 yield hr, lines
else:
for hunk in hunks:
yield hunk
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Yuya Nishihara
logcmdutil: create hunksfilter and filematcher even if no diff option given...
r36022 return filterfn
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Yuya Nishihara
logcmdutil: create hunksfilter and filematcher even if no diff option given...
r36022 def filematcher(ctx):
Denis Laxalde
log: map None rev to wdirrev when filtering revisions with --line-range...
r44173 files = list(linerangesbyrev.get(scmutil.intrev(ctx), []))
Yuya Nishihara
logcmdutil: create hunksfilter and filematcher even if no diff option given...
r36022 return scmutil.matchfiles(repo, files)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
revs = sorted(linerangesbyrev, reverse=True)
Yuya Nishihara
log: pack filematcher and hunksfilter into changesetdiffer object...
r36024 differ = changesetdiffer()
differ._makefilematcher = filematcher
differ._makehunksfilter = hunksfilter
Denis Laxalde
logcmdutil: let getlinerangerevs() return "revs" as a smartset...
r44029 return smartset.baseset(revs), differ
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 def _graphnodeformatter(ui, displayer):
Martin von Zweigbergk
config: rename ui.graphnodetemplate to command-templates.graphnode...
r46351 spec = ui.config(b'command-templates', b'graphnode')
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if not spec:
Yuya Nishihara
templatekw: extract non-templatekw function as getgraphnode()...
r36530 return templatekw.getgraphnode # fast path for "{graphnode}"
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
spec = templater.unquotestring(spec)
Yuya Nishihara
logcmdutil: rename classes and functions to conform to our coding style (API)...
r35904 if isinstance(displayer, changesettemplater):
Yuya Nishihara
templater: convert resources to a table of callables for future extension...
r36997 # reuse cache of slow templates
Yuya Nishihara
log: do no expect templateresources() returning a dict...
r37090 tres = displayer._tresources
else:
tres = formatter.templateresources(ui)
Augie Fackler
formatting: blacken the codebase...
r43346 templ = formatter.maketemplater(
ui, spec, defaults=templatekw.keywords, resources=tres
)
Martin von Zweigbergk
graphlog: use '%' for other context in merge conflict...
r44819 def formatnode(repo, ctx, cache):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 props = {b'ctx': ctx, b'repo': repo}
Yuya Nishihara
templater: rename .render(mapping) to .renderdefault(mapping) (API)...
r37003 return templ.renderdefault(props)
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 return formatnode
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
log: pass getcopies() function instead of getrenamed() to displayer (API)...
r42704 def displaygraph(ui, repo, dag, displayer, edgefn, getcopies=None, props=None):
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 props = props or {}
formatnode = _graphnodeformatter(ui, displayer)
state = graphmod.asciistate()
Yuya Nishihara
graphlog: change state dict to attr struct...
r44215 styles = state.styles
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
# only set graph styling if HGPLAIN is not set.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if ui.plain(b'graph'):
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 # set all edge styles to |, the default pre-3.8 behaviour
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 styles.update(dict.fromkeys(styles, b'|'))
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 else:
edgetypes = {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'parent': graphmod.PARENT,
b'grandparent': graphmod.GRANDPARENT,
b'missing': graphmod.MISSINGPARENT,
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 }
for name, key in edgetypes.items():
# experimental config: experimental.graphstyle.*
Augie Fackler
formatting: blacken the codebase...
r43346 styles[key] = ui.config(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'experimental', b'graphstyle.%s' % name, styles[key]
Augie Fackler
formatting: blacken the codebase...
r43346 )
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if not styles[key]:
styles[key] = None
# experimental config: experimental.graphshorten
Yuya Nishihara
graphlog: change state dict to attr struct...
r44215 state.graphshorten = ui.configbool(b'experimental', b'graphshorten')
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Martin von Zweigbergk
graphlog: use '%' for other context in merge conflict...
r44819 formatnode_cache = {}
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 for rev, type, ctx, parents in dag:
Martin von Zweigbergk
graphlog: use '%' for other context in merge conflict...
r44819 char = formatnode(repo, ctx, formatnode_cache)
Martin von Zweigbergk
log: pass getcopies() function instead of getrenamed() to displayer (API)...
r42704 copies = getcopies(ctx) if getcopies else None
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 edges = edgefn(type, char, state, rev, parents)
firstedge = next(edges)
width = firstedge[2]
Augie Fackler
formatting: blacken the codebase...
r43346 displayer.show(
ctx, copies=copies, graphwidth=width, **pycompat.strkwargs(props)
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 lines = displayer.hunk.pop(rev).split(b'\n')
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if not lines[-1]:
del lines[-1]
displayer.flush(ctx)
for type, char, width, coldata in itertools.chain([firstedge], edges):
graphmod.ascii(ui, state, type, char, lines, coldata)
lines = []
displayer.close()
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
log: factor out function to feed revisions to displayer
r36216 def displaygraphrevs(ui, repo, revs, displayer, getrenamed):
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 revdag = graphmod.dagwalker(repo, revs)
Yuya Nishihara
logcmdutil: hold makefilematcher/makehunksfilter() by changesetpriner (API)...
r36020 displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges, getrenamed)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
log: pass getcopies() function instead of getrenamed() to displayer (API)...
r42704 def displayrevs(ui, repo, revs, displayer, getcopies):
Yuya Nishihara
log: factor out function to feed revisions to displayer
r36216 for rev in revs:
ctx = repo[rev]
Martin von Zweigbergk
log: pass getcopies() function instead of getrenamed() to displayer (API)...
r42704 copies = getcopies(ctx) if getcopies else None
Yuya Nishihara
log: factor out function to feed revisions to displayer
r36216 displayer.show(ctx, copies=copies)
displayer.flush(ctx)
displayer.close()
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 def checkunsupportedgraphflags(pats, opts):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for op in [b"newest_first"]:
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 if op in opts and opts[op]:
Martin von Zweigbergk
logcmdutil: raise `InputError` on bad CLI arguments...
r49401 raise error.InputError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"-G/--graph option is incompatible with --%s")
% op.replace(b"_", b"-")
Augie Fackler
formatting: blacken the codebase...
r43346 )
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
def graphrevs(repo, nodes, opts):
Yuya Nishihara
logcmdutil: drop redundant "log" from function names (API)...
r35905 limit = getlimit(opts)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 nodes.reverse()
if limit is not None:
nodes = nodes[:limit]
return graphmod.nodes(repo, nodes)