##// END OF EJS Templates
interfaces: convert `repository.ifilestorage` to a Protocol class...
interfaces: convert `repository.ifilestorage` to a Protocol class Same as cdd4bc69bfc1 for `imanifestrevisionstored`, but also make the methods in the super classes abstract as well.

File last commit:

r52756:f4733654 default
r53385:8c89e978 default
Show More
logcmdutil.py
1339 lines | 43.4 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.
Matt Harbison
typing: add `from __future__ import annotations` to most files...
r52756 from __future__ import annotations
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
import itertools
import os
Martin von Zweigbergk
patch: replace "prefix" and "relroot" arguments by "pathfn" (API)...
r41795 import posixpath
Matt Harbison
typing: induce pytype to use the standard `attr` instead of the vendored copy...
r52622 import typing
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903
pytype: import typing directly...
r52178 from typing import (
Any,
Callable,
Dict,
Optional,
Sequence,
Tuple,
)
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 from .i18n import _
pacien
util: move diff_parent from logcmdutil to diffutil...
r52036 from .node import 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
Matt Harbison
typing: induce pytype to use the standard `attr` instead of the vendored copy...
r52622 # Force pytype to use the non-vendored package
if typing.TYPE_CHECKING:
# noinspection PyPackageRequirements
import attr
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 from . import (
dagop,
pacien
util: move diff_parent from logcmdutil to diffutil...
r52036 diffutil,
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 error,
formatter,
graphmod,
match as matchmod,
mdiff,
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
logcmdutil: add a type annotation...
r44100
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
zegervdv
logcmdutil: return structured diffstat data for json
r52035 def get_diff_chunks(
Augie Fackler
formatting: blacken the codebase...
r43346 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,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 prefix=b'',
root=b'',
Augie Fackler
formatting: blacken the codebase...
r43346 hunksfilterfn=None,
):
Yuya Nishihara
cmdutil: split functions of log-like commands to new module (API)...
r35903 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)
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
zegervdv
logcmdutil: return structured diffstat data for json
r52035 return ctx2.diff(
Augie Fackler
formatting: blacken the codebase...
r43346 ctx1,
match,
changes,
opts=diffopts,
pathfn=pathfn,
copysourcematch=copysourcematch,
hunksfilterfn=hunksfilterfn,
)
Joerg Sonnenberger
diff: improve ui.write performance when not coloring on Windows...
r35979
zegervdv
logcmdutil: return structured diffstat data for json
r52035
def diffordiffstat(
ui,
repo,
diffopts,
ctx1,
ctx2,
match,
changes=None,
stat=False,
fp=None,
graphwidth=0,
prefix=b'',
root=b'',
listsubrepos=False,
hunksfilterfn=None,
):
'''show diff or diffstat.'''
chunks = get_diff_chunks(
ui,
repo,
diffopts,
ctx1,
ctx2,
match,
changes=changes,
stat=stat,
prefix=prefix,
root=root,
hunksfilterfn=hunksfilterfn,
)
if stat:
diffopts = diffopts.copy(context=0, noprefix=False)
width = 80
if not ui.plain():
width = ui.termwidth() - graphwidth
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,
pacien
util: move diff_parent from logcmdutil to diffutil...
r52036 diffutil.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),
)
zegervdv
logcmdutil: return structured diffstat data for json
r52035 def getdiffstats(self, ui, ctx, diffopts, stat=False):
chunks = get_diff_chunks(
ui,
ctx.repo(),
diffopts,
pacien
util: move diff_parent from logcmdutil to diffutil...
r52036 diffutil.diff_parent(ctx),
zegervdv
logcmdutil: return structured diffstat data for json
r52035 ctx,
match=self._makefilematcher(ctx),
stat=stat,
hunksfilterfn=self._makehunksfilter(ctx),
)
diffdata = []
for filename, additions, removals, binary in patch.diffstatdata(
util.iterlines(chunks)
):
diffdata.append(
{
b"name": filename,
b"additions": additions,
b"removals": removals,
b"binary": binary,
}
)
return diffdata
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:
zegervdv
logcmdutil: return structured diffstat data for json
r52035 data = self._differ.getdiffstats(
self.ui, ctx, self._diffopts, stat=True
)
fm.data(diffstat=fm.formatlist(data, name=b'diffstat'))
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
Matt Harbison
typing: lock in correct changes from pytype 2023.04.11 -> 2023.06.16...
r52708 _tresources: formatter.templateresources
lastheader: Optional[bytes]
t: templater.templater
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
Matt Harbison
typing: lock in correct changes from pytype 2023.04.11 -> 2023.06.16...
r52708 def templatespec(tmpl, mapfile) -> formatter.templatespec:
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
Matt Harbison
typing: lock in correct changes from pytype 2023.04.11 -> 2023.06.16...
r52708 def _lookuptemplate(ui, tmpl, style) -> formatter.templatespec:
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
pytype: move some type comment to proper annotation...
r52180 def parseopts(
ui: Any,
pats: Sequence[bytes],
opts: 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
pytype: move some type comment to proper annotation...
r52180 def makewalker(
repo: Any,
wopts: walkopts,
) -> Tuple[
smartset.abstractsmartset, Optional[Callable[[Any], matchmod.basematcher]]
]:
Yuya Nishihara
log: extract function that builds (revs, makefilematcher) from walkopts...
r46203 """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
pytype: move some type comment to proper annotation...
r52180 def getrevs(
repo: Any,
wopts: walkopts,
) -> Tuple[smartset.abstractsmartset, Optional[changesetdiffer]]:
Yuya Nishihara
log: extract function that builds (revs, makefilematcher) from walkopts...
r46203 """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)