--- a/mercurial/fileset.py Sat Oct 05 10:29:34 2019 -0400
+++ b/mercurial/fileset.py Sun Oct 06 09:45:02 2019 -0400
@@ -21,9 +21,7 @@
scmutil,
util,
)
-from .utils import (
- stringutil,
-)
+from .utils import stringutil
# common weight constants
_WEIGHT_CHECK_FILENAME = filesetlang.WEIGHT_CHECK_FILENAME
@@ -38,49 +36,67 @@
getpattern = filesetlang.getpattern
getargs = filesetlang.getargs
+
def getmatch(mctx, x):
if not x:
raise error.ParseError(_("missing argument"))
return methods[x[0]](mctx, *x[1:])
+
def getmatchwithstatus(mctx, x, hint):
keys = set(getstring(hint, 'status hint must be a string').split())
return getmatch(mctx.withstatus(keys), x)
+
def stringmatch(mctx, x):
return mctx.matcher([x])
+
def kindpatmatch(mctx, x, y):
- return stringmatch(mctx, _getkindpat(x, y, matchmod.allpatternkinds,
- _("pattern must be a string")))
+ return stringmatch(
+ mctx,
+ _getkindpat(
+ x, y, matchmod.allpatternkinds, _("pattern must be a string")
+ ),
+ )
+
def patternsmatch(mctx, *xs):
allkinds = matchmod.allpatternkinds
- patterns = [getpattern(x, allkinds, _("pattern must be a string"))
- for x in xs]
+ patterns = [
+ getpattern(x, allkinds, _("pattern must be a string")) for x in xs
+ ]
return mctx.matcher(patterns)
+
def andmatch(mctx, x, y):
xm = getmatch(mctx, x)
ym = getmatch(mctx.narrowed(xm), y)
return matchmod.intersectmatchers(xm, ym)
+
def ormatch(mctx, *xs):
ms = [getmatch(mctx, x) for x in xs]
return matchmod.unionmatcher(ms)
+
def notmatch(mctx, x):
m = getmatch(mctx, x)
return mctx.predicate(lambda f: not m(f), predrepr=('<not %r>', m))
+
def minusmatch(mctx, x, y):
xm = getmatch(mctx, x)
ym = getmatch(mctx.narrowed(xm), y)
return matchmod.differencematcher(xm, ym)
+
def listmatch(mctx, *xs):
- raise error.ParseError(_("can't use a list in this context"),
- hint=_('see \'hg help "filesets.x or y"\''))
+ raise error.ParseError(
+ _("can't use a list in this context"),
+ hint=_('see \'hg help "filesets.x or y"\''),
+ )
+
def func(mctx, a, b):
funcname = getsymbol(a)
@@ -92,6 +108,7 @@
syms = [s for (s, fn) in symbols.items() if keep(fn)]
raise error.UnknownIdentifier(funcname, syms)
+
# symbols are callable like:
# fun(mctx, x)
# with:
@@ -101,6 +118,7 @@
predicate = registrar.filesetpredicate(symbols)
+
@predicate('modified()', callstatus=True, weight=_WEIGHT_STATUS)
def modified(mctx, x):
"""File that is modified according to :hg:`status`.
@@ -110,6 +128,7 @@
s = set(mctx.status().modified)
return mctx.predicate(s.__contains__, predrepr='modified')
+
@predicate('added()', callstatus=True, weight=_WEIGHT_STATUS)
def added(mctx, x):
"""File that is added according to :hg:`status`.
@@ -119,6 +138,7 @@
s = set(mctx.status().added)
return mctx.predicate(s.__contains__, predrepr='added')
+
@predicate('removed()', callstatus=True, weight=_WEIGHT_STATUS)
def removed(mctx, x):
"""File that is removed according to :hg:`status`.
@@ -128,6 +148,7 @@
s = set(mctx.status().removed)
return mctx.predicate(s.__contains__, predrepr='removed')
+
@predicate('deleted()', callstatus=True, weight=_WEIGHT_STATUS)
def deleted(mctx, x):
"""Alias for ``missing()``.
@@ -137,6 +158,7 @@
s = set(mctx.status().deleted)
return mctx.predicate(s.__contains__, predrepr='deleted')
+
@predicate('missing()', callstatus=True, weight=_WEIGHT_STATUS)
def missing(mctx, x):
"""File that is missing according to :hg:`status`.
@@ -146,6 +168,7 @@
s = set(mctx.status().deleted)
return mctx.predicate(s.__contains__, predrepr='deleted')
+
@predicate('unknown()', callstatus=True, weight=_WEIGHT_STATUS_THOROUGH)
def unknown(mctx, x):
"""File that is unknown according to :hg:`status`."""
@@ -154,6 +177,7 @@
s = set(mctx.status().unknown)
return mctx.predicate(s.__contains__, predrepr='unknown')
+
@predicate('ignored()', callstatus=True, weight=_WEIGHT_STATUS_THOROUGH)
def ignored(mctx, x):
"""File that is ignored according to :hg:`status`."""
@@ -162,6 +186,7 @@
s = set(mctx.status().ignored)
return mctx.predicate(s.__contains__, predrepr='ignored')
+
@predicate('clean()', callstatus=True, weight=_WEIGHT_STATUS)
def clean(mctx, x):
"""File that is clean according to :hg:`status`.
@@ -171,6 +196,7 @@
s = set(mctx.status().clean)
return mctx.predicate(s.__contains__, predrepr='clean')
+
@predicate('tracked()')
def tracked(mctx, x):
"""File that is under Mercurial control."""
@@ -178,14 +204,17 @@
getargs(x, 0, 0, _("tracked takes no arguments"))
return mctx.predicate(mctx.ctx.__contains__, predrepr='tracked')
+
@predicate('binary()', weight=_WEIGHT_READ_CONTENTS)
def binary(mctx, x):
"""File that appears to be binary (contains NUL bytes).
"""
# i18n: "binary" is a keyword
getargs(x, 0, 0, _("binary takes no arguments"))
- return mctx.fpredicate(lambda fctx: fctx.isbinary(),
- predrepr='binary', cache=True)
+ return mctx.fpredicate(
+ lambda fctx: fctx.isbinary(), predrepr='binary', cache=True
+ )
+
@predicate('exec()')
def exec_(mctx, x):
@@ -196,6 +225,7 @@
ctx = mctx.ctx
return mctx.predicate(lambda f: ctx.flags(f) == 'x', predrepr='exec')
+
@predicate('symlink()')
def symlink(mctx, x):
"""File that is marked as a symlink.
@@ -205,6 +235,7 @@
ctx = mctx.ctx
return mctx.predicate(lambda f: ctx.flags(f) == 'l', predrepr='symlink')
+
@predicate('resolved()', weight=_WEIGHT_STATUS)
def resolved(mctx, x):
"""File that is marked resolved according to :hg:`resolve -l`.
@@ -214,8 +245,10 @@
if mctx.ctx.rev() is not None:
return mctx.never()
ms = merge.mergestate.read(mctx.ctx.repo())
- return mctx.predicate(lambda f: f in ms and ms[f] == 'r',
- predrepr='resolved')
+ return mctx.predicate(
+ lambda f: f in ms and ms[f] == 'r', predrepr='resolved'
+ )
+
@predicate('unresolved()', weight=_WEIGHT_STATUS)
def unresolved(mctx, x):
@@ -226,8 +259,10 @@
if mctx.ctx.rev() is not None:
return mctx.never()
ms = merge.mergestate.read(mctx.ctx.repo())
- return mctx.predicate(lambda f: f in ms and ms[f] == 'u',
- predrepr='unresolved')
+ return mctx.predicate(
+ lambda f: f in ms and ms[f] == 'u', predrepr='unresolved'
+ )
+
@predicate('hgignore()', weight=_WEIGHT_STATUS)
def hgignore(mctx, x):
@@ -237,6 +272,7 @@
getargs(x, 0, 0, _("hgignore takes no arguments"))
return mctx.ctx.repo().dirstate._ignore
+
@predicate('portable()', weight=_WEIGHT_CHECK_FILENAME)
def portable(mctx, x):
"""File that has a portable name. (This doesn't include filenames with case
@@ -244,8 +280,10 @@
"""
# i18n: "portable" is a keyword
getargs(x, 0, 0, _("portable takes no arguments"))
- return mctx.predicate(lambda f: util.checkwinfilename(f) is None,
- predrepr='portable')
+ return mctx.predicate(
+ lambda f: util.checkwinfilename(f) is None, predrepr='portable'
+ )
+
@predicate('grep(regex)', weight=_WEIGHT_READ_CONTENTS)
def grep(mctx, x):
@@ -255,10 +293,15 @@
# i18n: "grep" is a keyword
r = re.compile(getstring(x, _("grep requires a pattern")))
except re.error as e:
- raise error.ParseError(_('invalid match pattern: %s') %
- stringutil.forcebytestr(e))
- return mctx.fpredicate(lambda fctx: r.search(fctx.data()),
- predrepr=('grep(%r)', r.pattern), cache=True)
+ raise error.ParseError(
+ _('invalid match pattern: %s') % stringutil.forcebytestr(e)
+ )
+ return mctx.fpredicate(
+ lambda fctx: r.search(fctx.data()),
+ predrepr=('grep(%r)', r.pattern),
+ cache=True,
+ )
+
def _sizetomax(s):
try:
@@ -266,7 +309,7 @@
for k, v in util._sizeunits:
if s.endswith(k):
# max(4k) = 5k - 1, max(4.5k) = 4.6k - 1
- n = s[:-len(k)]
+ n = s[: -len(k)]
inc = 1.0
if "." in n:
inc /= 10 ** len(n.split(".")[1])
@@ -276,10 +319,11 @@
except ValueError:
raise error.ParseError(_("couldn't parse size: %s") % s)
+
def sizematcher(expr):
"""Return a function(size) -> bool from the ``size()`` expression"""
expr = expr.strip()
- if '-' in expr: # do we have a range?
+ if '-' in expr: # do we have a range?
a, b = expr.split('-', 1)
a = util.sizetoint(a)
b = util.sizetoint(b)
@@ -301,6 +345,7 @@
b = _sizetomax(expr)
return lambda x: x >= a and x <= b
+
@predicate('size(expression)', weight=_WEIGHT_STATUS)
def size(mctx, x):
"""File size matches the given expression. Examples:
@@ -313,8 +358,10 @@
# i18n: "size" is a keyword
expr = getstring(x, _("size requires an expression"))
m = sizematcher(expr)
- return mctx.fpredicate(lambda fctx: m(fctx.size()),
- predrepr=('size(%r)', expr), cache=True)
+ return mctx.fpredicate(
+ lambda fctx: m(fctx.size()), predrepr=('size(%r)', expr), cache=True
+ )
+
@predicate('encoding(name)', weight=_WEIGHT_READ_CONTENTS)
def encoding(mctx, x):
@@ -338,6 +385,7 @@
return mctx.fpredicate(encp, predrepr=('encoding(%r)', enc), cache=True)
+
@predicate('eol(style)', weight=_WEIGHT_READ_CONTENTS)
def eol(mctx, x):
"""File contains newlines of the given style (dos, unix, mac). Binary
@@ -359,19 +407,24 @@
elif enc == 'mac' and re.search('\r(?!\n)', d):
return True
return False
+
return mctx.fpredicate(eolp, predrepr=('eol(%r)', enc), cache=True)
+
@predicate('copied()')
def copied(mctx, x):
"""File that is recorded as being copied.
"""
# i18n: "copied" is a keyword
getargs(x, 0, 0, _("copied takes no arguments"))
+
def copiedp(fctx):
p = fctx.parents()
return p and p[0].path() != fctx.path()
+
return mctx.fpredicate(copiedp, predrepr='copied', cache=True)
+
@predicate('revs(revs, pattern)', weight=_WEIGHT_STATUS)
def revs(mctx, x):
"""Evaluate set in the specified revisions. If the revset match multiple
@@ -395,6 +448,7 @@
return matchers[0]
return matchmod.unionmatcher(matchers)
+
@predicate('status(base, rev, pattern)', weight=_WEIGHT_STATUS)
def status(mctx, x):
"""Evaluate predicate using status change between ``base`` and
@@ -418,6 +472,7 @@
mc = mctx.switch(basectx, ctx)
return getmatch(mc, x)
+
@predicate('subrepo([pattern])')
def subrepo(mctx, x):
"""Subrepositories whose paths match the given pattern.
@@ -427,20 +482,27 @@
ctx = mctx.ctx
sstate = ctx.substate
if x:
- pat = getpattern(x, matchmod.allpatternkinds,
- # i18n: "subrepo" is a keyword
- _("subrepo requires a pattern or no arguments"))
+ pat = getpattern(
+ x,
+ matchmod.allpatternkinds,
+ # i18n: "subrepo" is a keyword
+ _("subrepo requires a pattern or no arguments"),
+ )
fast = not matchmod.patkind(pat)
if fast:
+
def m(s):
- return (s == pat)
+ return s == pat
+
else:
m = matchmod.match(ctx.repo().root, '', [pat], ctx=ctx)
- return mctx.predicate(lambda f: f in sstate and m(f),
- predrepr=('subrepo(%r)', pat))
+ return mctx.predicate(
+ lambda f: f in sstate and m(f), predrepr=('subrepo(%r)', pat)
+ )
else:
return mctx.predicate(sstate.__contains__, predrepr='subrepo')
+
methods = {
'withstatus': getmatchwithstatus,
'string': stringmatch,
@@ -455,6 +517,7 @@
'func': func,
}
+
class matchctx(object):
def __init__(self, basectx, ctx, badfn=None):
self._basectx = basectx
@@ -484,10 +547,13 @@
return mctx
def _buildstatus(self, keys):
- self._status = self._basectx.status(self.ctx, self._match,
- listignored='ignored' in keys,
- listclean='clean' in keys,
- listunknown='unknown' in keys)
+ self._status = self._basectx.status(
+ self.ctx,
+ self._match,
+ listignored='ignored' in keys,
+ listclean='clean' in keys,
+ listunknown='unknown' in keys,
+ )
def status(self):
return self._status
@@ -499,8 +565,9 @@
"""Create a matcher to select files by predfn(filename)"""
if cache:
predfn = util.cachefunc(predfn)
- return matchmod.predicatematcher(predfn, predrepr=predrepr,
- badfn=self._badfn)
+ return matchmod.predicatematcher(
+ predfn, predrepr=predrepr, badfn=self._badfn
+ )
def fpredicate(self, predfn, predrepr=None, cache=False):
"""Create a matcher to select files by predfn(fctx) at the current
@@ -510,6 +577,7 @@
"""
ctx = self.ctx
if ctx.rev() is None:
+
def fctxpredfn(f):
try:
fctx = ctx[f]
@@ -523,23 +591,31 @@
return predfn(fctx)
except (IOError, OSError) as e:
# open()-ing a directory fails with EACCES on Windows
- if e.errno in (errno.ENOENT, errno.EACCES, errno.ENOTDIR,
- errno.EISDIR):
+ if e.errno in (
+ errno.ENOENT,
+ errno.EACCES,
+ errno.ENOTDIR,
+ errno.EISDIR,
+ ):
return False
raise
+
else:
+
def fctxpredfn(f):
try:
fctx = ctx[f]
except error.LookupError:
return False
return predfn(fctx)
+
return self.predicate(fctxpredfn, predrepr=predrepr, cache=cache)
def never(self):
"""Create a matcher to select nothing"""
return matchmod.never(badfn=self._badfn)
+
def match(ctx, expr, badfn=None):
"""Create a matcher for a single fileset expression"""
tree = filesetlang.parse(expr)
@@ -555,5 +631,6 @@
for name, func in registrarobj._table.iteritems():
symbols[name] = func
+
# tell hggettext to extract docstrings from these functions:
i18nfunctions = symbols.values()