--- a/mercurial/revset.py Sat Oct 05 10:29:34 2019 -0400
+++ b/mercurial/revset.py Sun Oct 06 09:45:02 2019 -0400
@@ -93,17 +93,19 @@
#
# There are a few revsets that always redefine the order if 'define' is
# specified: 'sort(X)', 'reverse(X)', 'x:y'.
-anyorder = 'any' # don't care the order, could be even random-shuffled
+anyorder = 'any' # don't care the order, could be even random-shuffled
defineorder = 'define' # ALWAYS redefine, or ALWAYS follow the current order
followorder = 'follow' # MUST follow the current order
# helpers
+
def getset(repo, subset, x, order=defineorder):
if not x:
raise error.ParseError(_("missing argument"))
return methods[x[0]](repo, subset, *x[1:], order=order)
+
def _getrevsource(repo, r):
extra = repo[r].extra()
for label in ('source', 'transplant_source', 'rebase_source'):
@@ -114,11 +116,14 @@
pass
return None
+
def _sortedb(xs):
return sorted(pycompat.rapply(pycompat.maybebytestr, xs))
+
# operator methods
+
def stringset(repo, subset, x, order):
if not x:
raise error.ParseError(_("empty string is not a valid revision"))
@@ -127,6 +132,7 @@
return baseset([x])
return baseset()
+
def rawsmartset(repo, subset, x, order):
"""argument is already a smartset, use that directly"""
if order == followorder:
@@ -134,6 +140,7 @@
else:
return x & subset
+
def rangeset(repo, subset, x, y, order):
m = getset(repo, fullreposet(repo), x)
n = getset(repo, fullreposet(repo), y)
@@ -142,10 +149,12 @@
return baseset()
return _makerangeset(repo, subset, m.first(), n.last(), order)
+
def rangeall(repo, subset, x, order):
assert x is None
return _makerangeset(repo, subset, 0, repo.changelog.tiprev(), order)
+
def rangepre(repo, subset, y, order):
# ':y' can't be rewritten to '0:y' since '0' may be hidden
n = getset(repo, fullreposet(repo), y)
@@ -153,12 +162,15 @@
return baseset()
return _makerangeset(repo, subset, 0, n.last(), order)
+
def rangepost(repo, subset, x, order):
m = getset(repo, fullreposet(repo), x)
if not m:
return baseset()
- return _makerangeset(repo, subset, m.first(), repo.changelog.tiprev(),
- order)
+ return _makerangeset(
+ repo, subset, m.first(), repo.changelog.tiprev(), order
+ )
+
def _makerangeset(repo, subset, m, n, order):
if m == n:
@@ -178,12 +190,15 @@
# carrying the sorting over when possible would be more efficient
return subset & r
+
def dagrange(repo, subset, x, y, order):
r = fullreposet(repo)
- xs = dagop.reachableroots(repo, getset(repo, r, x), getset(repo, r, y),
- includepath=True)
+ xs = dagop.reachableroots(
+ repo, getset(repo, r, x), getset(repo, r, y), includepath=True
+ )
return subset & xs
+
def andset(repo, subset, x, y, order):
if order == anyorder:
yorder = anyorder
@@ -191,6 +206,7 @@
yorder = followorder
return getset(repo, getset(repo, subset, x, order), y, yorder)
+
def andsmallyset(repo, subset, x, y, order):
# 'andsmally(x, y)' is equivalent to 'and(x, y)', but faster when y is small
if order == anyorder:
@@ -199,9 +215,11 @@
yorder = followorder
return getset(repo, getset(repo, subset, y, yorder), x, order)
+
def differenceset(repo, subset, x, y, order):
return getset(repo, subset, x, order) - getset(repo, subset, y, anyorder)
+
def _orsetlist(repo, subset, xs, order):
assert xs
if len(xs) == 1:
@@ -211,6 +229,7 @@
b = _orsetlist(repo, subset, xs[p:], order)
return a + b
+
def orset(repo, subset, x, order):
xs = getlist(x)
if not xs:
@@ -221,12 +240,15 @@
else:
return _orsetlist(repo, subset, xs, order)
+
def notset(repo, subset, x, order):
return subset - getset(repo, subset, x, anyorder)
+
def relationset(repo, subset, x, y, order):
raise error.ParseError(_("can't use a relation in this context"))
+
def _splitrange(a, b):
"""Split range with bounds a and b into two ranges at 0 and return two
tuples of numbers for use as startdepth and stopdepth arguments of
@@ -257,14 +279,17 @@
descdepths = (max(a, 0), b + 1)
return ancdepths, descdepths
+
def generationsrel(repo, subset, x, rel, z, order):
# TODO: rewrite tests, and drop startdepth argument from ancestors() and
# descendants() predicates
- a, b = getintrange(z,
- _('relation subscript must be an integer or a range'),
- _('relation subscript bounds must be integers'),
- deffirst=-(dagop.maxlogdepth - 1),
- deflast=+(dagop.maxlogdepth - 1))
+ a, b = getintrange(
+ z,
+ _('relation subscript must be an integer or a range'),
+ _('relation subscript bounds must be integers'),
+ deffirst=-(dagop.maxlogdepth - 1),
+ deflast=+(dagop.maxlogdepth - 1),
+ )
(ancstart, ancstop), (descstart, descstop) = _splitrange(a, b)
if ancstart is None and descstart is None:
@@ -284,6 +309,7 @@
return subset & s
+
def relsubscriptset(repo, subset, x, y, z, order):
# this is pretty basic implementation of 'x#y[z]' operator, still
# experimental so undocumented. see the wiki for further ideas.
@@ -295,16 +321,22 @@
relnames = [r for r in subscriptrelations.keys() if len(r) > 1]
raise error.UnknownIdentifier(rel, relnames)
+
def subscriptset(repo, subset, x, y, order):
raise error.ParseError(_("can't use a subscript in this context"))
+
def listset(repo, subset, *xs, **opts):
- raise error.ParseError(_("can't use a list in this context"),
- hint=_('see \'hg help "revsets.x or y"\''))
+ raise error.ParseError(
+ _("can't use a list in this context"),
+ hint=_('see \'hg help "revsets.x or y"\''),
+ )
+
def keyvaluepair(repo, subset, k, v, order):
raise error.ParseError(_("can't use a key-value pair in this context"))
+
def func(repo, subset, a, b, order):
f = getsymbol(a)
if f in symbols:
@@ -318,6 +350,7 @@
syms = [s for (s, fn) in symbols.items() if keep(fn)]
raise error.UnknownIdentifier(f, syms)
+
# functions
# symbols are callables like:
@@ -335,12 +368,15 @@
predicate = registrar.revsetpredicate()
+
@predicate('_destupdate')
def _destupdate(repo, subset, x):
# experimental revset for update destination
args = getargsdict(x, 'limit', 'clean')
- return subset & baseset([destutil.destupdate(repo,
- **pycompat.strkwargs(args))[0]])
+ return subset & baseset(
+ [destutil.destupdate(repo, **pycompat.strkwargs(args))[0]]
+ )
+
@predicate('_destmerge')
def _destmerge(repo, subset, x):
@@ -350,6 +386,7 @@
sourceset = getset(repo, fullreposet(repo), x)
return subset & baseset([destutil.destmerge(repo, sourceset=sourceset)])
+
@predicate('adds(pattern)', safe=True, weight=30)
def adds(repo, subset, x):
"""Changesets that add a file matching pattern.
@@ -362,6 +399,7 @@
pat = getstring(x, _("adds requires a pattern"))
return checkstatus(repo, subset, pat, 1)
+
@predicate('ancestor(*changeset)', safe=True, weight=0.5)
def ancestor(repo, subset, x):
"""A greatest common ancestor of the changesets.
@@ -383,14 +421,17 @@
return baseset([r])
return baseset()
-def _ancestors(repo, subset, x, followfirst=False, startdepth=None,
- stopdepth=None):
+
+def _ancestors(
+ repo, subset, x, followfirst=False, startdepth=None, stopdepth=None
+):
heads = getset(repo, fullreposet(repo), x)
if not heads:
return baseset()
s = dagop.revancestors(repo, heads, followfirst, startdepth, stopdepth)
return subset & s
+
@predicate('ancestors(set[, depth])', safe=True)
def ancestors(repo, subset, x):
"""Changesets that are ancestors of changesets in set, including the
@@ -406,8 +447,9 @@
raise error.ParseError(_('ancestors takes at least 1 argument'))
startdepth = stopdepth = None
if 'startdepth' in args:
- n = getinteger(args['startdepth'],
- "ancestors expects an integer startdepth")
+ n = getinteger(
+ args['startdepth'], "ancestors expects an integer startdepth"
+ )
if n < 0:
raise error.ParseError("negative startdepth")
startdepth = n
@@ -417,8 +459,10 @@
if n < 0:
raise error.ParseError(_("negative depth"))
stopdepth = n + 1
- return _ancestors(repo, subset, args['set'],
- startdepth=startdepth, stopdepth=stopdepth)
+ return _ancestors(
+ repo, subset, args['set'], startdepth=startdepth, stopdepth=stopdepth
+ )
+
@predicate('_firstancestors', safe=True)
def _firstancestors(repo, subset, x):
@@ -426,6 +470,7 @@
# Like ``ancestors(set)`` but follows only the first parents.
return _ancestors(repo, subset, x, followfirst=True)
+
def _childrenspec(repo, subset, x, n, order):
"""Changesets that are the Nth child of a changeset
in set.
@@ -438,12 +483,14 @@
break
if len(c) > 1:
raise error.RepoLookupError(
- _("revision in set has more than one child"))
+ _("revision in set has more than one child")
+ )
r = c[0].rev()
else:
cs.add(r)
return subset & cs
+
def ancestorspec(repo, subset, x, n, order):
"""``set~n``
Changesets that are the Nth ancestor (first parents only) of a changeset
@@ -464,6 +511,7 @@
ps.add(r)
return subset & ps
+
@predicate('author(string)', safe=True, weight=10)
def author(repo, subset, x):
"""Alias for ``user(string)``.
@@ -471,8 +519,10 @@
# i18n: "author" is a keyword
n = getstring(x, _("author requires a string"))
kind, pattern, matcher = _substringmatcher(n, casesensitive=False)
- return subset.filter(lambda x: matcher(repo[x].user()),
- condrepr=('<user %r>', n))
+ return subset.filter(
+ lambda x: matcher(repo[x].user()), condrepr=('<user %r>', n)
+ )
+
@predicate('bisect(string)', safe=True)
def bisect(repo, subset, x):
@@ -491,12 +541,14 @@
state = set(hbisect.get(repo, status))
return subset & state
+
# Backward-compatibility
# - no help entry so that we do not advertise it any more
@predicate('bisected', safe=True)
def bisected(repo, subset, x):
return bisect(repo, subset, x)
+
@predicate('bookmark([name])', safe=True)
def bookmark(repo, subset, x):
"""The named bookmark or all bookmarks.
@@ -506,9 +558,11 @@
# i18n: "bookmark" is a keyword
args = getargs(x, 0, 1, _('bookmark takes one or no arguments'))
if args:
- bm = getstring(args[0],
- # i18n: "bookmark" is a keyword
- _('the argument to bookmark must be a string'))
+ bm = getstring(
+ args[0],
+ # i18n: "bookmark" is a keyword
+ _('the argument to bookmark must be a string'),
+ )
kind, pattern, matcher = stringutil.stringmatcher(bm)
bms = set()
if kind == 'literal':
@@ -516,8 +570,9 @@
pattern = repo._bookmarks.expandname(pattern)
bmrev = repo._bookmarks.get(pattern, None)
if not bmrev:
- raise error.RepoLookupError(_("bookmark '%s' does not exist")
- % pattern)
+ raise error.RepoLookupError(
+ _("bookmark '%s' does not exist") % pattern
+ )
bms.add(repo[bmrev].rev())
else:
matchrevs = set()
@@ -531,6 +586,7 @@
bms -= {node.nullrev}
return subset & bms
+
@predicate('branch(string or set)', safe=True, weight=10)
def branch(repo, subset, x):
"""
@@ -541,6 +597,7 @@
:hg:`help revisions.patterns`.
"""
getbi = repo.revbranchcache().branchinfo
+
def getbranch(r):
try:
return getbi(r)[0]
@@ -558,22 +615,28 @@
# note: falls through to the revspec case if no branch with
# this name exists and pattern kind is not specified explicitly
if repo.branchmap().hasbranch(pattern):
- return subset.filter(lambda r: matcher(getbranch(r)),
- condrepr=('<branch %r>', b))
+ return subset.filter(
+ lambda r: matcher(getbranch(r)), condrepr=('<branch %r>', b)
+ )
if b.startswith('literal:'):
- raise error.RepoLookupError(_("branch '%s' does not exist")
- % pattern)
+ raise error.RepoLookupError(
+ _("branch '%s' does not exist") % pattern
+ )
else:
- return subset.filter(lambda r: matcher(getbranch(r)),
- condrepr=('<branch %r>', b))
+ return subset.filter(
+ lambda r: matcher(getbranch(r)), condrepr=('<branch %r>', b)
+ )
s = getset(repo, fullreposet(repo), x)
b = set()
for r in s:
b.add(getbranch(r))
c = s.__contains__
- return subset.filter(lambda r: c(r) or getbranch(r) in b,
- condrepr=lambda: '<branch %r>' % _sortedb(b))
+ return subset.filter(
+ lambda r: c(r) or getbranch(r) in b,
+ condrepr=lambda: '<branch %r>' % _sortedb(b),
+ )
+
@predicate('phasedivergent()', safe=True)
def phasedivergent(repo, subset, x):
@@ -587,6 +650,7 @@
phasedivergent = obsmod.getrevs(repo, 'phasedivergent')
return subset & phasedivergent
+
@predicate('bundle()', safe=True)
def bundle(repo, subset, x):
"""Changesets in the bundle.
@@ -599,6 +663,7 @@
raise error.Abort(_("no bundle provided - specify with -R"))
return subset & bundlerevs
+
def checkstatus(repo, subset, pat, field):
"""Helper for status-related revsets (adds, removes, modifies).
The field parameter says which kind is desired:
@@ -609,6 +674,7 @@
hasset = matchmod.patkind(pat) == 'set'
mcache = [None]
+
def matches(x):
c = repo[x]
if not mcache[0] or hasset:
@@ -637,6 +703,7 @@
return subset.filter(matches, condrepr=('<status[%r] %r>', field, pat))
+
def _children(repo, subset, parentset):
if not parentset:
return baseset()
@@ -654,6 +721,7 @@
cs.add(r)
return baseset(cs)
+
@predicate('children(set)', safe=True)
def children(repo, subset, x):
"""Child changesets of changesets in set.
@@ -662,14 +730,17 @@
cs = _children(repo, subset, s)
return subset & cs
+
@predicate('closed()', safe=True, weight=10)
def closed(repo, subset, x):
"""Changeset is closed.
"""
# i18n: "closed" is a keyword
getargs(x, 0, 0, _("closed takes no arguments"))
- return subset.filter(lambda r: repo[r].closesbranch(),
- condrepr='<branch closed>')
+ return subset.filter(
+ lambda r: repo[r].closesbranch(), condrepr='<branch closed>'
+ )
+
# for internal use
@predicate('_commonancestorheads(set)', safe=True)
@@ -684,6 +755,7 @@
ancs = repo.changelog._commonancestorsheads(*list(startrevs))
return subset & baseset(ancs)
+
@predicate('commonancestors(set)', safe=True)
def commonancestors(repo, subset, x):
"""Changesets that are ancestors of every changeset in set.
@@ -695,6 +767,7 @@
subset &= dagop.revancestors(repo, baseset([r]))
return subset
+
@predicate('contains(pattern)', weight=100)
def contains(repo, subset, x):
"""The revision's manifest contains a file matching pattern (but might not
@@ -722,6 +795,7 @@
return subset.filter(matches, condrepr=('<contains %r>', pat))
+
@predicate('converted([id])', safe=True)
def converted(repo, subset, x):
"""Changesets converted from the given identifier in the old repository if
@@ -742,8 +816,10 @@
source = repo[r].extra().get('convert_revision', None)
return source is not None and (rev is None or source.startswith(rev))
- return subset.filter(lambda r: _matchvalue(r),
- condrepr=('<converted %r>', rev))
+ return subset.filter(
+ lambda r: _matchvalue(r), condrepr=('<converted %r>', rev)
+ )
+
@predicate('date(interval)', safe=True, weight=10)
def date(repo, subset, x):
@@ -752,8 +828,10 @@
# i18n: "date" is a keyword
ds = getstring(x, _("date requires a string"))
dm = dateutil.matchdate(ds)
- return subset.filter(lambda x: dm(repo[x].date()[0]),
- condrepr=('<date %r>', ds))
+ return subset.filter(
+ lambda x: dm(repo[x].date()[0]), condrepr=('<date %r>', ds)
+ )
+
@predicate('desc(string)', safe=True, weight=10)
def desc(repo, subset, x):
@@ -767,17 +845,21 @@
kind, pattern, matcher = _substringmatcher(ds, casesensitive=False)
- return subset.filter(lambda r: matcher(repo[r].description()),
- condrepr=('<desc %r>', ds))
-
-def _descendants(repo, subset, x, followfirst=False, startdepth=None,
- stopdepth=None):
+ return subset.filter(
+ lambda r: matcher(repo[r].description()), condrepr=('<desc %r>', ds)
+ )
+
+
+def _descendants(
+ repo, subset, x, followfirst=False, startdepth=None, stopdepth=None
+):
roots = getset(repo, fullreposet(repo), x)
if not roots:
return baseset()
s = dagop.revdescendants(repo, roots, followfirst, startdepth, stopdepth)
return subset & s
+
@predicate('descendants(set[, depth])', safe=True)
def descendants(repo, subset, x):
"""Changesets which are descendants of changesets in set, including the
@@ -793,8 +875,9 @@
raise error.ParseError(_('descendants takes at least 1 argument'))
startdepth = stopdepth = None
if 'startdepth' in args:
- n = getinteger(args['startdepth'],
- "descendants expects an integer startdepth")
+ n = getinteger(
+ args['startdepth'], "descendants expects an integer startdepth"
+ )
if n < 0:
raise error.ParseError("negative startdepth")
startdepth = n
@@ -804,8 +887,10 @@
if n < 0:
raise error.ParseError(_("negative depth"))
stopdepth = n + 1
- return _descendants(repo, subset, args['set'],
- startdepth=startdepth, stopdepth=stopdepth)
+ return _descendants(
+ repo, subset, args['set'], startdepth=startdepth, stopdepth=stopdepth
+ )
+
@predicate('_firstdescendants', safe=True)
def _firstdescendants(repo, subset, x):
@@ -813,6 +898,7 @@
# Like ``descendants(set)`` but follows only the first parents.
return _descendants(repo, subset, x, followfirst=True)
+
@predicate('destination([set])', safe=True, weight=10)
def destination(repo, subset, x):
"""Changesets that were created by a graft, transplant or rebase operation,
@@ -855,8 +941,11 @@
r = src
src = _getrevsource(repo, r)
- return subset.filter(dests.__contains__,
- condrepr=lambda: '<destination %r>' % _sortedb(dests))
+ return subset.filter(
+ dests.__contains__,
+ condrepr=lambda: '<destination %r>' % _sortedb(dests),
+ )
+
@predicate('contentdivergent()', safe=True)
def contentdivergent(repo, subset, x):
@@ -869,6 +958,7 @@
contentdivergent = obsmod.getrevs(repo, 'contentdivergent')
return subset & contentdivergent
+
@predicate('expectsize(set[, size])', safe=True, takeorder=True)
def expectsize(repo, subset, x, order):
"""Return the given revset if size matches the revset size.
@@ -884,21 +974,25 @@
err = ''
if 'size' not in args or 'set' not in args:
raise error.ParseError(_('invalid set of arguments'))
- minsize, maxsize = getintrange(args['size'],
- _('expectsize requires a size range'
- ' or a positive integer'),
- _('size range bounds must be integers'),
- minsize, maxsize)
+ minsize, maxsize = getintrange(
+ args['size'],
+ _('expectsize requires a size range' ' or a positive integer'),
+ _('size range bounds must be integers'),
+ minsize,
+ maxsize,
+ )
if minsize < 0 or maxsize < 0:
raise error.ParseError(_('negative size'))
rev = getset(repo, fullreposet(repo), args['set'], order=order)
if minsize != maxsize and (len(rev) < minsize or len(rev) > maxsize):
- err = _('revset size mismatch.'
- ' expected between %d and %d, got %d') % (minsize, maxsize,
- len(rev))
+ err = _(
+ 'revset size mismatch.' ' expected between %d and %d, got %d'
+ ) % (minsize, maxsize, len(rev))
elif minsize == maxsize and len(rev) != minsize:
- err = _('revset size mismatch.'
- ' expected %d, got %d') % (minsize, len(rev))
+ err = _('revset size mismatch.' ' expected %d, got %d') % (
+ minsize,
+ len(rev),
+ )
if err:
raise error.RepoLookupError(err)
if order == followorder:
@@ -906,17 +1000,21 @@
else:
return rev & subset
+
@predicate('extdata(source)', safe=False, weight=100)
def extdata(repo, subset, x):
"""Changesets in the specified extdata source. (EXPERIMENTAL)"""
# i18n: "extdata" is a keyword
args = getargsdict(x, 'extdata', 'source')
- source = getstring(args.get('source'),
- # i18n: "extdata" is a keyword
- _('extdata takes at least 1 string argument'))
+ source = getstring(
+ args.get('source'),
+ # i18n: "extdata" is a keyword
+ _('extdata takes at least 1 string argument'),
+ )
data = scmutil.extdatasource(repo, source)
return subset & baseset(data)
+
@predicate('extinct()', safe=True)
def extinct(repo, subset, x):
"""Obsolete changesets with obsolete descendants only.
@@ -926,6 +1024,7 @@
extincts = obsmod.getrevs(repo, 'extinct')
return subset & extincts
+
@predicate('extra(label, [value])', safe=True)
def extra(repo, subset, x):
"""Changesets with the given label in the extra metadata, with the given
@@ -939,22 +1038,26 @@
# i18n: "extra" is a keyword
raise error.ParseError(_('extra takes at least 1 argument'))
# i18n: "extra" is a keyword
- label = getstring(args['label'], _('first argument to extra must be '
- 'a string'))
+ label = getstring(
+ args['label'], _('first argument to extra must be ' 'a string')
+ )
value = None
if 'value' in args:
# i18n: "extra" is a keyword
- value = getstring(args['value'], _('second argument to extra must be '
- 'a string'))
+ value = getstring(
+ args['value'], _('second argument to extra must be ' 'a string')
+ )
kind, value, matcher = stringutil.stringmatcher(value)
def _matchvalue(r):
extra = repo[r].extra()
return label in extra and (value is None or matcher(extra[label]))
- return subset.filter(lambda r: _matchvalue(r),
- condrepr=('<extra[%r] %r>', label, value))
+ return subset.filter(
+ lambda r: _matchvalue(r), condrepr=('<extra[%r] %r>', label, value)
+ )
+
@predicate('filelog(pattern)', safe=True)
def filelog(repo, subset, x):
@@ -1019,12 +1122,14 @@
return subset & s
+
@predicate('first(set, [n])', safe=True, takeorder=True, weight=0)
def first(repo, subset, x, order):
"""An alias for limit().
"""
return limit(repo, subset, x, order)
+
def _follow(repo, subset, x, name, followfirst=False):
args = getargsdict(x, name, 'file startrev')
revs = None
@@ -1039,8 +1144,9 @@
ctx = mctx = repo[r]
if r is None:
ctx = repo['.']
- m = matchmod.match(repo.root, repo.getcwd(), [x],
- ctx=mctx, default='path')
+ m = matchmod.match(
+ repo.root, repo.getcwd(), [x], ctx=mctx, default='path'
+ )
fctxs.extend(ctx[f].introfilectx() for f in ctx.manifest().walk(m))
s = dagop.filerevancestors(fctxs, followfirst)
else:
@@ -1050,6 +1156,7 @@
return subset & s
+
@predicate('follow([file[, startrev]])', safe=True)
def follow(repo, subset, x):
"""
@@ -1059,6 +1166,7 @@
"""
return _follow(repo, subset, x, 'follow')
+
@predicate('_followfirst', safe=True)
def _followfirst(repo, subset, x):
# ``followfirst([file[, startrev]])``
@@ -1066,8 +1174,10 @@
# of every revisions or files revisions.
return _follow(repo, subset, x, '_followfirst', followfirst=True)
-@predicate('followlines(file, fromline:toline[, startrev=., descend=False])',
- safe=True)
+
+@predicate(
+ 'followlines(file, fromline:toline[, startrev=., descend=False])', safe=True
+)
def followlines(repo, subset, x):
"""Changesets modifying `file` in line range ('fromline', 'toline').
@@ -1089,7 +1199,8 @@
if len(revs) != 1:
raise error.ParseError(
# i18n: "followlines" is a keyword
- _("followlines expects exactly one revision"))
+ _("followlines expects exactly one revision")
+ )
rev = revs.last()
pat = getstring(args['file'], _("followlines requires a pattern"))
@@ -1097,29 +1208,45 @@
msg = _("followlines expects exactly one file")
fname = scmutil.parsefollowlinespattern(repo, rev, pat, msg)
fromline, toline = util.processlinerange(
- *getintrange(args['lines'][0],
- # i18n: "followlines" is a keyword
- _("followlines expects a line number or a range"),
- _("line range bounds must be integers")))
+ *getintrange(
+ args['lines'][0],
+ # i18n: "followlines" is a keyword
+ _("followlines expects a line number or a range"),
+ _("line range bounds must be integers"),
+ )
+ )
fctx = repo[rev].filectx(fname)
descend = False
if 'descend' in args:
- descend = getboolean(args['descend'],
- # i18n: "descend" is a keyword
- _("descend argument must be a boolean"))
+ descend = getboolean(
+ args['descend'],
+ # i18n: "descend" is a keyword
+ _("descend argument must be a boolean"),
+ )
if descend:
rs = generatorset(
- (c.rev() for c, _linerange
- in dagop.blockdescendants(fctx, fromline, toline)),
- iterasc=True)
+ (
+ c.rev()
+ for c, _linerange in dagop.blockdescendants(
+ fctx, fromline, toline
+ )
+ ),
+ iterasc=True,
+ )
else:
rs = generatorset(
- (c.rev() for c, _linerange
- in dagop.blockancestors(fctx, fromline, toline)),
- iterasc=False)
+ (
+ c.rev()
+ for c, _linerange in dagop.blockancestors(
+ fctx, fromline, toline
+ )
+ ),
+ iterasc=False,
+ )
return subset & rs
+
@predicate('all()', safe=True)
def getall(repo, subset, x):
"""All changesets, the same as ``0:tip``.
@@ -1128,6 +1255,7 @@
getargs(x, 0, 0, _("all takes no arguments"))
return subset & spanset(repo) # drop "null" if any
+
@predicate('grep(regex)', weight=10)
def grep(repo, subset, x):
"""Like ``keyword(string)`` but accepts a regex. Use ``grep(r'...')``
@@ -1139,7 +1267,8 @@
gr = re.compile(getstring(x, _("grep requires a string")))
except re.error as e:
raise error.ParseError(
- _('invalid match pattern: %s') % stringutil.forcebytestr(e))
+ _('invalid match pattern: %s') % stringutil.forcebytestr(e)
+ )
def matches(x):
c = repo[x]
@@ -1150,6 +1279,7 @@
return subset.filter(matches, condrepr=('<grep %r>', gr.pattern))
+
@predicate('_matchfiles', safe=True)
def _matchfiles(repo, subset, x):
# _matchfiles takes a revset list of prefixed arguments:
@@ -1178,16 +1308,18 @@
exc.append(value)
elif prefix == 'r:':
if rev is not None:
- raise error.ParseError('_matchfiles expected at most one '
- 'revision')
- if value == '': # empty means working directory
+ raise error.ParseError(
+ '_matchfiles expected at most one ' 'revision'
+ )
+ if value == '': # empty means working directory
rev = node.wdirrev
else:
rev = value
elif prefix == 'd:':
if default is not None:
- raise error.ParseError('_matchfiles expected at most one '
- 'default mode')
+ raise error.ParseError(
+ '_matchfiles expected at most one ' 'default mode'
+ )
default = value
else:
raise error.ParseError('invalid _matchfiles prefix: %s' % prefix)
@@ -1201,6 +1333,7 @@
# revisions is quite expensive.
getfiles = repo.changelog.readfiles
wdirrev = node.wdirrev
+
def matches(x):
if x == wdirrev:
files = repo[x].files()
@@ -1209,9 +1342,15 @@
if not mcache[0] or (hasset and rev is None):
r = x if rev is None else rev
- mcache[0] = matchmod.match(repo.root, repo.getcwd(), pats,
- include=inc, exclude=exc, ctx=repo[r],
- default=default)
+ mcache[0] = matchmod.match(
+ repo.root,
+ repo.getcwd(),
+ pats,
+ include=inc,
+ exclude=exc,
+ ctx=repo[r],
+ default=default,
+ )
m = mcache[0]
for f in files:
@@ -1219,10 +1358,19 @@
return True
return False
- return subset.filter(matches,
- condrepr=('<matchfiles patterns=%r, include=%r '
- 'exclude=%r, default=%r, rev=%r>',
- pats, inc, exc, default, rev))
+ return subset.filter(
+ matches,
+ condrepr=(
+ '<matchfiles patterns=%r, include=%r '
+ 'exclude=%r, default=%r, rev=%r>',
+ pats,
+ inc,
+ exc,
+ default,
+ rev,
+ ),
+ )
+
@predicate('file(pattern)', safe=True, weight=10)
def hasfile(repo, subset, x):
@@ -1237,6 +1385,7 @@
pat = getstring(x, _("file requires a pattern"))
return _matchfiles(repo, subset, ('string', 'p:' + pat))
+
@predicate('head()', safe=True)
def head(repo, subset, x):
"""Changeset is a named branch head.
@@ -1249,6 +1398,7 @@
hs.update(cl.rev(h) for h in ls)
return subset & baseset(hs)
+
@predicate('heads(set)', safe=True, takeorder=True)
def heads(repo, subset, x, order):
"""Members of set with no children in set.
@@ -1270,6 +1420,7 @@
heads = baseset(heads)
return subset & heads
+
@predicate('hidden()', safe=True)
def hidden(repo, subset, x):
"""Hidden changesets.
@@ -1279,6 +1430,7 @@
hiddenrevs = repoview.filterrevs(repo, 'visible')
return subset & hiddenrevs
+
@predicate('keyword(string)', safe=True, weight=10)
def keyword(repo, subset, x):
"""Search commit message, user name, and names of changed files for
@@ -1292,11 +1444,14 @@
def matches(r):
c = repo[r]
- return any(kw in encoding.lower(t)
- for t in c.files() + [c.user(), c.description()])
+ return any(
+ kw in encoding.lower(t)
+ for t in c.files() + [c.user(), c.description()]
+ )
return subset.filter(matches, condrepr=('<keyword %r>', kw))
+
@predicate('limit(set[, n[, offset]])', safe=True, takeorder=True, weight=0)
def limit(repo, subset, x, order):
"""First n members of set, defaulting to 1, starting from offset.
@@ -1319,6 +1474,7 @@
return subset & ls
return ls & subset
+
@predicate('last(set, [n])', safe=True, takeorder=True)
def last(repo, subset, x, order):
"""Last n members of set, defaulting to 1.
@@ -1339,6 +1495,7 @@
ls.reverse()
return ls & subset
+
@predicate('max(set)', safe=True)
def maxrev(repo, subset, x):
"""Changeset with highest revision number in set.
@@ -1354,6 +1511,7 @@
pass
return baseset(datarepr=('<max %r, %r>', subset, os))
+
@predicate('merge()', safe=True)
def merge(repo, subset, x):
"""Changeset is a merge changeset.
@@ -1362,13 +1520,16 @@
getargs(x, 0, 0, _("merge takes no arguments"))
cl = repo.changelog
nullrev = node.nullrev
+
def ismerge(r):
try:
return cl.parentrevs(r)[1] != nullrev
except error.WdirUnsupported:
return bool(repo[r].p2())
+
return subset.filter(ismerge, condrepr='<merge>')
+
@predicate('branchpoint()', safe=True)
def branchpoint(repo, subset, x):
"""Changesets with more than one child.
@@ -1381,13 +1542,15 @@
# XXX this should be 'parentset.min()' assuming 'parentset' is a smartset
# (and if it is not, it should.)
baserev = min(subset)
- parentscount = [0]*(len(repo) - baserev)
+ parentscount = [0] * (len(repo) - baserev)
for r in cl.revs(start=baserev + 1):
for p in cl.parentrevs(r):
if p >= baserev:
parentscount[p - baserev] += 1
- return subset.filter(lambda r: parentscount[r - baserev] > 1,
- condrepr='<branchpoint>')
+ return subset.filter(
+ lambda r: parentscount[r - baserev] > 1, condrepr='<branchpoint>'
+ )
+
@predicate('min(set)', safe=True)
def minrev(repo, subset, x):
@@ -1404,6 +1567,7 @@
pass
return baseset(datarepr=('<min %r, %r>', subset, os))
+
@predicate('modifies(pattern)', safe=True, weight=30)
def modifies(repo, subset, x):
"""Changesets modifying files matched by pattern.
@@ -1416,6 +1580,7 @@
pat = getstring(x, _("modifies requires a pattern"))
return checkstatus(repo, subset, pat, 0)
+
@predicate('named(namespace)')
def named(repo, subset, x):
"""The changesets in a given namespace.
@@ -1426,15 +1591,16 @@
# i18n: "named" is a keyword
args = getargs(x, 1, 1, _('named requires a namespace argument'))
- ns = getstring(args[0],
- # i18n: "named" is a keyword
- _('the argument to named must be a string'))
+ ns = getstring(
+ args[0],
+ # i18n: "named" is a keyword
+ _('the argument to named must be a string'),
+ )
kind, pattern, matcher = stringutil.stringmatcher(ns)
namespaces = set()
if kind == 'literal':
if pattern not in repo.names:
- raise error.RepoLookupError(_("namespace '%s' does not exist")
- % ns)
+ raise error.RepoLookupError(_("namespace '%s' does not exist") % ns)
namespaces.add(repo.names[pattern])
else:
for name, ns in repo.names.iteritems():
@@ -1450,6 +1616,7 @@
names -= {node.nullrev}
return subset & names
+
@predicate('id(string)', safe=True)
def node_(repo, subset, x):
"""Revision non-ambiguously specified by the given hex string prefix.
@@ -1481,6 +1648,7 @@
result = baseset([rn])
return result & subset
+
@predicate('none()', safe=True)
def none(repo, subset, x):
"""No changesets.
@@ -1489,6 +1657,7 @@
getargs(x, 0, 0, _("none takes no arguments"))
return baseset()
+
@predicate('obsolete()', safe=True)
def obsolete(repo, subset, x):
"""Mutable changeset with a newer version."""
@@ -1497,6 +1666,7 @@
obsoletes = obsmod.getrevs(repo, 'obsolete')
return subset & obsoletes
+
@predicate('only(set, [set])', safe=True)
def only(repo, subset, x):
"""Changesets that are ancestors of the first set that are not ancestors
@@ -1513,8 +1683,11 @@
return baseset()
descendants = set(dagop.revdescendants(repo, include, False))
- exclude = [rev for rev in cl.headrevs()
- if not rev in descendants and not rev in include]
+ exclude = [
+ rev
+ for rev in cl.headrevs()
+ if not rev in descendants and not rev in include
+ ]
else:
exclude = getset(repo, fullreposet(repo), args[1])
@@ -1523,6 +1696,7 @@
# some optimizations from the fact this is a baseset.
return subset & results
+
@predicate('origin([set])', safe=True)
def origin(repo, subset, x):
"""
@@ -1555,6 +1729,7 @@
# some optimizations from the fact this is a baseset.
return subset & o
+
@predicate('outgoing([path])', safe=False, weight=10)
def outgoing(repo, subset, x):
"""Changesets not found in the specified destination repository, or the
@@ -1565,6 +1740,7 @@
discovery,
hg,
)
+
# i18n: "outgoing" is a keyword
l = getargs(x, 0, 1, _("outgoing takes one or no arguments"))
# i18n: "outgoing" is a keyword
@@ -1574,8 +1750,10 @@
dest = None
path = repo.ui.paths.getpath(dest, default=('default-push', 'default'))
if not path:
- raise error.Abort(_('default repository not configured!'),
- hint=_("see 'hg help config.paths'"))
+ raise error.Abort(
+ _('default repository not configured!'),
+ hint=_("see 'hg help config.paths'"),
+ )
dest = path.pushloc or path.loc
branches = path.branch, []
@@ -1590,6 +1768,7 @@
o = {cl.rev(r) for r in outgoing.missing}
return subset & o
+
@predicate('p1([set])', safe=True)
def p1(repo, subset, x):
"""First parent of changesets in set, or the working directory.
@@ -1612,6 +1791,7 @@
# some optimizations from the fact this is a baseset.
return subset & ps
+
@predicate('p2([set])', safe=True)
def p2(repo, subset, x):
"""Second parent of changesets in set, or the working directory.
@@ -1640,9 +1820,11 @@
# some optimizations from the fact this is a baseset.
return subset & ps
+
def parentpost(repo, subset, x, order):
return p1(repo, subset, x)
+
@predicate('parents([set])', safe=True)
def parents(repo, subset, x):
"""
@@ -1663,16 +1845,19 @@
ps -= {node.nullrev}
return subset & ps
+
def _phase(repo, subset, *targets):
"""helper to select all rev in <targets> phases"""
return repo._phasecache.getrevset(repo, targets, subset)
+
@predicate('_phase(idx)', safe=True)
def phase(repo, subset, x):
- l = getargs(x, 1, 1, ("_phase requires one argument"))
- target = getinteger(l[0], ("_phase expects a number"))
+ l = getargs(x, 1, 1, "_phase requires one argument")
+ target = getinteger(l[0], "_phase expects a number")
return _phase(repo, subset, target)
+
@predicate('draft()', safe=True)
def draft(repo, subset, x):
"""Changeset in draft phase."""
@@ -1681,6 +1866,7 @@
target = phases.draft
return _phase(repo, subset, target)
+
@predicate('secret()', safe=True)
def secret(repo, subset, x):
"""Changeset in secret phase."""
@@ -1689,6 +1875,7 @@
target = phases.secret
return _phase(repo, subset, target)
+
@predicate('stack([revs])', safe=True)
def stack(repo, subset, x):
"""Experimental revset for the stack of changesets or working directory
@@ -1704,6 +1891,7 @@
return subset & stacks
+
def parentspec(repo, subset, x, n, order):
"""``set^0``
The set.
@@ -1737,6 +1925,7 @@
ps.add(parents[1].rev())
return subset & ps
+
@predicate('present(set)', safe=True, takeorder=True)
def present(repo, subset, x, order):
"""An empty set, if any revision in set isn't found; otherwise,
@@ -1751,12 +1940,14 @@
except error.RepoLookupError:
return baseset()
+
# for internal use
@predicate('_notpublic', safe=True)
def _notpublic(repo, subset, x):
getargs(x, 0, 0, "_notpublic takes no arguments")
return _phase(repo, subset, phases.draft, phases.secret)
+
# for internal use
@predicate('_phaseandancestors(phasename, set)', safe=True)
def _phaseandancestors(repo, subset, x):
@@ -1770,7 +1961,7 @@
secret = phases.secret
phasenamemap = {
'_notpublic': draft,
- 'draft': draft, # follow secret's ancestors
+ 'draft': draft, # follow secret's ancestors
'secret': secret,
}
if phasename not in phasenamemap:
@@ -1784,10 +1975,11 @@
revs = dagop.revancestors(repo, s, cutfunc=cutfunc)
- if phasename == 'draft': # need to remove secret changesets
+ if phasename == 'draft': # need to remove secret changesets
revs = revs.filter(lambda r: getphase(repo, r) == draft)
return subset & revs
+
@predicate('public()', safe=True)
def public(repo, subset, x):
"""Changeset in public phase."""
@@ -1795,6 +1987,7 @@
getargs(x, 0, 0, _("public takes no arguments"))
return _phase(repo, subset, phases.public)
+
@predicate('remote([id [,path]])', safe=False)
def remote(repo, subset, x):
"""Local revision that corresponds to the given identifier in a
@@ -1802,13 +1995,14 @@
synonym for the current local branch.
"""
- from . import hg # avoid start-up nasties
+ from . import hg # avoid start-up nasties
+
# i18n: "remote" is a keyword
l = getargs(x, 0, 2, _("remote takes zero, one, or two arguments"))
q = '.'
if len(l) > 0:
- # i18n: "remote" is a keyword
+ # i18n: "remote" is a keyword
q = getstring(l[0], _("remote requires a string id"))
if q == '.':
q = repo['.'].branch()
@@ -1830,6 +2024,7 @@
return baseset([r])
return baseset()
+
@predicate('removes(pattern)', safe=True, weight=30)
def removes(repo, subset, x):
"""Changesets which remove files matching pattern.
@@ -1842,6 +2037,7 @@
pat = getstring(x, _("removes requires a pattern"))
return checkstatus(repo, subset, pat, 2)
+
@predicate('rev(number)', safe=True)
def rev(repo, subset, x):
"""Revision with the given numeric identifier.
@@ -1858,6 +2054,7 @@
return baseset()
return subset & baseset([l])
+
@predicate('_rev(number)', safe=True)
def _rev(repo, subset, x):
# internal version of "rev(x)" that raise error if "x" is invalid
@@ -1869,9 +2066,10 @@
except (TypeError, ValueError):
# i18n: "rev" is a keyword
raise error.ParseError(_("rev expects a number"))
- repo.changelog.node(l) # check that the rev exists
+ repo.changelog.node(l) # check that the rev exists
return subset & baseset([l])
+
@predicate('revset(set)', safe=True, takeorder=True)
def revsetpredicate(repo, subset, x, order):
"""Strictly interpret the content as a revset.
@@ -1882,6 +2080,7 @@
"""
return getset(repo, subset, x, order)
+
@predicate('matching(revision [, field])', safe=True)
def matching(repo, subset, x):
"""Changesets in which a given set of fields match the set of fields in the
@@ -1914,10 +2113,11 @@
fieldlist = ['metadata']
if len(l) > 1:
- fieldlist = getstring(l[1],
- # i18n: "matching" is a keyword
- _("matching requires a string "
- "as its second argument")).split()
+ fieldlist = getstring(
+ l[1],
+ # i18n: "matching" is a keyword
+ _("matching requires a string " "as its second argument"),
+ ).split()
# Make sure that there are no repeated fields,
# expand the 'special' 'metadata' field type
@@ -1943,14 +2143,26 @@
# We may want to match more than one field
# Not all fields take the same amount of time to be matched
# Sort the selected fields in order of increasing matching cost
- fieldorder = ['phase', 'parents', 'user', 'date', 'branch', 'summary',
- 'files', 'description', 'substate', 'diff']
+ fieldorder = [
+ 'phase',
+ 'parents',
+ 'user',
+ 'date',
+ 'branch',
+ 'summary',
+ 'files',
+ 'description',
+ 'substate',
+ 'diff',
+ ]
+
def fieldkeyfunc(f):
try:
return fieldorder.index(f)
except ValueError:
# assume an unknown field is very costly
return len(fieldorder)
+
fields = list(fields)
fields.sort(key=fieldkeyfunc)
@@ -1967,15 +2179,18 @@
'phase': lambda r: repo[r].phase(),
'substate': lambda r: repo[r].substate,
'summary': lambda r: repo[r].description().splitlines()[0],
- 'diff': lambda r: list(repo[r].diff(
- opts=diffutil.diffallopts(repo.ui, {'git': True}))),
+ 'diff': lambda r: list(
+ repo[r].diff(opts=diffutil.diffallopts(repo.ui, {'git': True}))
+ ),
}
for info in fields:
getfield = _funcs.get(info, None)
if getfield is None:
raise error.ParseError(
# i18n: "matching" is a keyword
- _("unexpected field name passed to matching: %s") % info)
+ _("unexpected field name passed to matching: %s")
+ % info
+ )
getfieldfuncs.append(getfield)
# convert the getfield array of functions into a "getinfo" function
# which returns an array of field values (or a single value if there
@@ -1995,6 +2210,7 @@
return subset.filter(matches, condrepr=('<matching%r %r>', fields, revs))
+
@predicate('reverse(set)', safe=True, takeorder=True, weight=0)
def reverse(repo, subset, x, order):
"""Reverse order of set.
@@ -2004,19 +2220,23 @@
l.reverse()
return l
+
@predicate('roots(set)', safe=True)
def roots(repo, subset, x):
"""Changesets in set with no parent changeset in set.
"""
s = getset(repo, fullreposet(repo), x)
parents = repo.changelog.parentrevs
+
def filter(r):
for p in parents(r):
if 0 <= p and p in s:
return False
return True
+
return subset & s.filter(filter, condrepr='<roots>')
+
_sortkeyfuncs = {
'rev': lambda c: c.rev(),
'branch': lambda c: c.branch(),
@@ -2026,6 +2246,7 @@
'date': lambda c: c.date()[0],
}
+
def _getsortargs(x):
"""Parse sort options into (set, [(key, reverse)], opts)"""
args = getargsdict(x, 'sort', 'set keys topo.firstbranch')
@@ -2040,18 +2261,20 @@
keyflags = []
for k in keys.split():
fk = k
- reverse = (k.startswith('-'))
+ reverse = k.startswith('-')
if reverse:
k = k[1:]
if k not in _sortkeyfuncs and k != 'topo':
raise error.ParseError(
- _("unknown sort key %r") % pycompat.bytestr(fk))
+ _("unknown sort key %r") % pycompat.bytestr(fk)
+ )
keyflags.append((k, reverse))
if len(keyflags) > 1 and any(k == 'topo' for k, reverse in keyflags):
# i18n: "topo" is a keyword
- raise error.ParseError(_('topo sort order cannot be combined '
- 'with other sort keys'))
+ raise error.ParseError(
+ _('topo sort order cannot be combined ' 'with other sort keys')
+ )
opts = {}
if 'topo.firstbranch' in args:
@@ -2059,13 +2282,19 @@
opts['topo.firstbranch'] = args['topo.firstbranch']
else:
# i18n: "topo" and "topo.firstbranch" are keywords
- raise error.ParseError(_('topo.firstbranch can only be used '
- 'when using the topo sort key'))
+ raise error.ParseError(
+ _(
+ 'topo.firstbranch can only be used '
+ 'when using the topo sort key'
+ )
+ )
return args['set'], keyflags, opts
-@predicate('sort(set[, [-]key... [, ...]])', safe=True, takeorder=True,
- weight=10)
+
+@predicate(
+ 'sort(set[, [-]key... [, ...]])', safe=True, takeorder=True, weight=10
+)
def sort(repo, subset, x, order):
"""Sort set by keys. The default sort order is ascending, specify a key
as ``-key`` to sort in descending order.
@@ -2096,9 +2325,10 @@
firstbranch = ()
if 'topo.firstbranch' in opts:
firstbranch = getset(repo, subset, opts['topo.firstbranch'])
- revs = baseset(dagop.toposort(revs, repo.changelog.parentrevs,
- firstbranch),
- istopo=True)
+ revs = baseset(
+ dagop.toposort(revs, repo.changelog.parentrevs, firstbranch),
+ istopo=True,
+ )
if keyflags[0][1]:
revs.reverse()
return revs
@@ -2109,6 +2339,7 @@
ctxs.sort(key=_sortkeyfuncs[k], reverse=reverse)
return baseset([c.rev() for c in ctxs])
+
@predicate('subrepo([pattern])')
def subrepo(repo, subset, x):
"""Changesets that add, modify or remove the given subrepo. If no subrepo
@@ -2153,6 +2384,7 @@
return subset.filter(matches, condrepr=('<subrepo %r>', pat))
+
def _mapbynodefunc(repo, s, f):
"""(repo, smartset, [node] -> [node]) -> smartset
@@ -2167,6 +2399,7 @@
result = set(torev(n) for n in f(tonode(r) for r in s) if n in nodemap)
return smartset.baseset(result - repo.changelog.filteredrevs)
+
@predicate('successors(set)', safe=True)
def successors(repo, subset, x):
"""All successors for set, including the given set themselves"""
@@ -2175,9 +2408,11 @@
d = _mapbynodefunc(repo, s, f)
return subset & d
+
def _substringmatcher(pattern, casesensitive=True):
kind, pattern, matcher = stringutil.stringmatcher(
- pattern, casesensitive=casesensitive)
+ pattern, casesensitive=casesensitive
+ )
if kind == 'literal':
if not casesensitive:
pattern = encoding.lower(pattern)
@@ -2186,6 +2421,7 @@
matcher = lambda s: pattern in s
return kind, pattern, matcher
+
@predicate('tag([name])', safe=True)
def tag(repo, subset, x):
"""The specified tag by name, or all tagged revisions if no name is given.
@@ -2197,16 +2433,19 @@
args = getargs(x, 0, 1, _("tag takes one or no arguments"))
cl = repo.changelog
if args:
- pattern = getstring(args[0],
- # i18n: "tag" is a keyword
- _('the argument to tag must be a string'))
+ pattern = getstring(
+ args[0],
+ # i18n: "tag" is a keyword
+ _('the argument to tag must be a string'),
+ )
kind, pattern, matcher = stringutil.stringmatcher(pattern)
if kind == 'literal':
# avoid resolving all tags
tn = repo._tagscache.tags.get(pattern, None)
if tn is None:
- raise error.RepoLookupError(_("tag '%s' does not exist")
- % pattern)
+ raise error.RepoLookupError(
+ _("tag '%s' does not exist") % pattern
+ )
s = {repo[tn].rev()}
else:
s = {cl.rev(n) for t, n in repo.tagslist() if matcher(t)}
@@ -2214,10 +2453,12 @@
s = {cl.rev(n) for t, n in repo.tagslist() if t != 'tip'}
return subset & s
+
@predicate('tagged', safe=True)
def tagged(repo, subset, x):
return tag(repo, subset, x)
+
@predicate('orphan()', safe=True)
def orphan(repo, subset, x):
"""Non-obsolete changesets with obsolete ancestors. (EXPERIMENTAL)
@@ -2237,6 +2478,7 @@
"""
return author(repo, subset, x)
+
@predicate('wdir()', safe=True, weight=0)
def wdir(repo, subset, x):
"""Working directory. (EXPERIMENTAL)"""
@@ -2246,6 +2488,7 @@
return baseset([node.wdirrev])
return baseset()
+
def _orderedlist(repo, subset, x):
s = getstring(x, "internal error")
if not s:
@@ -2268,12 +2511,16 @@
for r in revs:
if r in seen:
continue
- if (r in subset
- or r in _virtualrevs and isinstance(subset, fullreposet)):
+ if (
+ r in subset
+ or r in _virtualrevs
+ and isinstance(subset, fullreposet)
+ ):
ls.append(r)
seen.add(r)
return baseset(ls)
+
# for internal use
@predicate('_list', safe=True, takeorder=True)
def _list(repo, subset, x, order):
@@ -2283,6 +2530,7 @@
else:
return _orderedlist(repo, subset, x)
+
def _orderedintlist(repo, subset, x):
s = getstring(x, "internal error")
if not s:
@@ -2291,6 +2539,7 @@
s = subset
return baseset([r for r in ls if r in s])
+
# for internal use
@predicate('_intlist', safe=True, takeorder=True, weight=0)
def _intlist(repo, subset, x, order):
@@ -2300,6 +2549,7 @@
else:
return _orderedintlist(repo, subset, x)
+
def _orderedhexlist(repo, subset, x):
s = getstring(x, "internal error")
if not s:
@@ -2309,6 +2559,7 @@
s = subset
return baseset([r for r in ls if r in s])
+
# for internal use
@predicate('_hexlist', safe=True, takeorder=True)
def _hexlist(repo, subset, x, order):
@@ -2318,6 +2569,7 @@
else:
return _orderedhexlist(repo, subset, x)
+
methods = {
"range": rangeset,
"rangeall": rangeall,
@@ -2348,13 +2600,16 @@
"generations": generationsrel,
}
+
def lookupfn(repo):
return lambda symbol: scmutil.isrevsymbol(repo, symbol)
+
def match(ui, spec, lookup=None):
"""Create a matcher for a single revision spec"""
return matchany(ui, [spec], lookup=lookup)
+
def matchany(ui, specs, lookup=None, localalias=None):
"""Create a matcher that will include any revisions matching one of the
given specs
@@ -2366,16 +2621,20 @@
precedence over [revsetalias] config section.
"""
if not specs:
+
def mfunc(repo, subset=None):
return baseset()
+
return mfunc
if not all(specs):
raise error.ParseError(_("empty query"))
if len(specs) == 1:
tree = revsetlang.parse(specs[0], lookup)
else:
- tree = ('or',
- ('list',) + tuple(revsetlang.parse(s, lookup) for s in specs))
+ tree = (
+ 'or',
+ ('list',) + tuple(revsetlang.parse(s, lookup) for s in specs),
+ )
aliases = []
warn = None
@@ -2391,8 +2650,10 @@
tree = revsetlang.optimize(tree)
return makematcher(tree)
+
def makematcher(tree):
"""Create a matcher from an evaluatable tree"""
+
def mfunc(repo, subset=None, order=None):
if order is None:
if subset is None:
@@ -2402,8 +2663,10 @@
if subset is None:
subset = fullreposet(repo)
return getset(repo, subset, tree, order)
+
return mfunc
+
def loadpredicate(ui, extname, registrarobj):
"""Load revset predicates from specified registrarobj
"""
@@ -2412,6 +2675,7 @@
if func._safe:
safesymbols.add(name)
+
# load built-in predicates explicitly to setup safesymbols
loadpredicate(None, None, predicate)