fileset: roughly adjust weights of functions
authorYuya Nishihara <yuya@tcha.org>
Sun, 22 Jul 2018 11:47:29 +0900
changeset 47224 bfd5def3fe0248340015184a2ad4067e77e3b675
parent 47223 7e7e2b2ff284f00a40b3599ac510b5f97eb9d0a8
child 47225 b975c5801487f9fb29a0c5957178beaba42c1323
push id839
push usergszorc@mozilla.com
push dateSat, 04 Aug 2018 02:01:50 +0000
fileset: roughly adjust weights of functions ... in order to move status predicates far away from basic patterns. I don't know if each weight is appropriate, but it should be good enough as a start.
mercurial/fileset.py
mercurial/registrar.py
--- a/mercurial/fileset.py
+++ b/mercurial/fileset.py
@@ -83,94 +83,94 @@ def func(mctx, a, b):
 #  x - argument in tree form
 symbols = filesetlang.symbols
 
 # filesets using matchctx.status()
 _statuscallers = set()
 
 predicate = registrar.filesetpredicate()
 
-@predicate('modified()', callstatus=True)
+@predicate('modified()', callstatus=True, weight=10)
 def modified(mctx, x):
     """File that is modified according to :hg:`status`.
     """
     # i18n: "modified" is a keyword
     getargs(x, 0, 0, _("modified takes no arguments"))
     s = set(mctx.status().modified)
     return mctx.predicate(s.__contains__, predrepr='modified')
 
-@predicate('added()', callstatus=True)
+@predicate('added()', callstatus=True, weight=10)
 def added(mctx, x):
     """File that is added according to :hg:`status`.
     """
     # i18n: "added" is a keyword
     getargs(x, 0, 0, _("added takes no arguments"))
     s = set(mctx.status().added)
     return mctx.predicate(s.__contains__, predrepr='added')
 
-@predicate('removed()', callstatus=True)
+@predicate('removed()', callstatus=True, weight=10)
 def removed(mctx, x):
     """File that is removed according to :hg:`status`.
     """
     # i18n: "removed" is a keyword
     getargs(x, 0, 0, _("removed takes no arguments"))
     s = set(mctx.status().removed)
     return mctx.predicate(s.__contains__, predrepr='removed')
 
-@predicate('deleted()', callstatus=True)
+@predicate('deleted()', callstatus=True, weight=10)
 def deleted(mctx, x):
     """Alias for ``missing()``.
     """
     # i18n: "deleted" is a keyword
     getargs(x, 0, 0, _("deleted takes no arguments"))
     s = set(mctx.status().deleted)
     return mctx.predicate(s.__contains__, predrepr='deleted')
 
-@predicate('missing()', callstatus=True)
+@predicate('missing()', callstatus=True, weight=10)
 def missing(mctx, x):
     """File that is missing according to :hg:`status`.
     """
     # i18n: "missing" is a keyword
     getargs(x, 0, 0, _("missing takes no arguments"))
     s = set(mctx.status().deleted)
     return mctx.predicate(s.__contains__, predrepr='deleted')
 
-@predicate('unknown()', callstatus=True)
+@predicate('unknown()', callstatus=True, weight=50)
 def unknown(mctx, x):
     """File that is unknown according to :hg:`status`."""
     # i18n: "unknown" is a keyword
     getargs(x, 0, 0, _("unknown takes no arguments"))
     s = set(mctx.status().unknown)
     return mctx.predicate(s.__contains__, predrepr='unknown')
 
-@predicate('ignored()', callstatus=True)
+@predicate('ignored()', callstatus=True, weight=50)
 def ignored(mctx, x):
     """File that is ignored according to :hg:`status`."""
     # i18n: "ignored" is a keyword
     getargs(x, 0, 0, _("ignored takes no arguments"))
     s = set(mctx.status().ignored)
     return mctx.predicate(s.__contains__, predrepr='ignored')
 
-@predicate('clean()', callstatus=True)
+@predicate('clean()', callstatus=True, weight=10)
 def clean(mctx, x):
     """File that is clean according to :hg:`status`.
     """
     # i18n: "clean" is a keyword
     getargs(x, 0, 0, _("clean takes no arguments"))
     s = set(mctx.status().clean)
     return mctx.predicate(s.__contains__, predrepr='clean')
 
 @predicate('tracked()')
 def tracked(mctx, x):
     """File that is under Mercurial control."""
     # i18n: "tracked" is a keyword
     getargs(x, 0, 0, _("tracked takes no arguments"))
     return mctx.predicate(mctx.ctx.__contains__, predrepr='tracked')
 
-@predicate('binary()')
+@predicate('binary()', weight=30)
 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)
 
@@ -187,59 +187,59 @@ def exec_(mctx, x):
 def symlink(mctx, x):
     """File that is marked as a symlink.
     """
     # i18n: "symlink" is a keyword
     getargs(x, 0, 0, _("symlink takes no arguments"))
     ctx = mctx.ctx
     return mctx.predicate(lambda f: ctx.flags(f) == 'l', predrepr='symlink')
 
-@predicate('resolved()')
+@predicate('resolved()', weight=10)
 def resolved(mctx, x):
     """File that is marked resolved according to :hg:`resolve -l`.
     """
     # i18n: "resolved" is a keyword
     getargs(x, 0, 0, _("resolved takes no arguments"))
     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')
 
-@predicate('unresolved()')
+@predicate('unresolved()', weight=10)
 def unresolved(mctx, x):
     """File that is marked unresolved according to :hg:`resolve -l`.
     """
     # i18n: "unresolved" is a keyword
     getargs(x, 0, 0, _("unresolved takes no arguments"))
     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')
 
-@predicate('hgignore()')
+@predicate('hgignore()', weight=10)
 def hgignore(mctx, x):
     """File that matches the active .hgignore pattern.
     """
     # i18n: "hgignore" is a keyword
     getargs(x, 0, 0, _("hgignore takes no arguments"))
     return mctx.ctx.repo().dirstate._ignore
 
-@predicate('portable()')
+@predicate('portable()', weight=0.5)
 def portable(mctx, x):
     """File that has a portable name. (This doesn't include filenames with case
     collisions.)
     """
     # 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')
 
-@predicate('grep(regex)')
+@predicate('grep(regex)', weight=30)
 def grep(mctx, x):
     """File contains the given regular expression.
     """
     try:
         # 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') %
@@ -283,32 +283,32 @@ def sizematcher(expr):
     elif expr.startswith(">"):
         a = util.sizetoint(expr[1:])
         return lambda x: x > a
     else:
         a = util.sizetoint(expr)
         b = _sizetomax(expr)
         return lambda x: x >= a and x <= b
 
-@predicate('size(expression)')
+@predicate('size(expression)', weight=10)
 def size(mctx, x):
     """File size matches the given expression. Examples:
 
     - size('1k') - files from 1024 to 2047 bytes
     - size('< 20k') - files less than 20480 bytes
     - size('>= .5MB') - files at least 524288 bytes
     - size('4k - 1MB') - files from 4096 bytes to 1048576 bytes
     """
     # 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)
 
-@predicate('encoding(name)')
+@predicate('encoding(name)', weight=30)
 def encoding(mctx, x):
     """File can be successfully decoded with the given character
     encoding. May not be useful for encodings other than ASCII and
     UTF-8.
     """
 
     # i18n: "encoding" is a keyword
     enc = getstring(x, _("encoding requires an encoding name"))
@@ -320,17 +320,17 @@ def encoding(mctx, x):
             return True
         except LookupError:
             raise error.Abort(_("unknown encoding '%s'") % enc)
         except UnicodeDecodeError:
             return False
 
     return mctx.fpredicate(encp, predrepr=('encoding(%r)', enc), cache=True)
 
-@predicate('eol(style)')
+@predicate('eol(style)', weight=30)
 def eol(mctx, x):
     """File contains newlines of the given style (dos, unix, mac). Binary
     files are excluded, files with mixed line endings match multiple
     styles.
     """
 
     # i18n: "eol" is a keyword
     enc = getstring(x, _("eol requires a style name"))
@@ -354,17 +354,17 @@ def copied(mctx, x):
     """
     # 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)')
+@predicate('revs(revs, pattern)', weight=10)
 def revs(mctx, x):
     """Evaluate set in the specified revisions. If the revset match multiple
     revs, this will return file matching pattern in any of the revision.
     """
     # i18n: "revs" is a keyword
     r, x = getargs(x, 2, 2, _("revs takes two arguments"))
     # i18n: "revs" is a keyword
     revspec = getstring(r, _("first argument to revs must be a revision"))
@@ -376,17 +376,17 @@ def revs(mctx, x):
         ctx = repo[r]
         matchers.append(getmatch(mctx.switch(ctx, _buildstatus(ctx, x)), x))
     if not matchers:
         return mctx.never()
     if len(matchers) == 1:
         return matchers[0]
     return matchmod.unionmatcher(matchers)
 
-@predicate('status(base, rev, pattern)')
+@predicate('status(base, rev, pattern)', weight=10)
 def status(mctx, x):
     """Evaluate predicate using status change between ``base`` and
     ``rev``. Examples:
 
     - ``status(3, 7, added())`` - matches files added from "3" to "7"
     """
     repo = mctx.ctx.repo()
     # i18n: "status" is a keyword
--- a/mercurial/registrar.py
+++ b/mercurial/registrar.py
@@ -245,16 +245,25 @@ class filesetpredicate(_funcregistrarbas
 
     Optional argument 'callstatus' indicates whether a predicate
      implies 'matchctx.status()' at runtime or not (False, by
      default).
 
     Optional argument 'weight' indicates the estimated run-time cost, useful
     for static optimization, default is 1. Higher weight means more expensive.
 
+    ====== =============================================================
+    Weight Description and examples
+    ====== =============================================================
+    0.5    basic match patterns (e.g. a symbol)
+    10     computing status (e.g. added()) or accessing a few files
+    30     reading file content for each (e.g. grep())
+    50     scanning working directory (ignored())
+    ====== =============================================================
+
     'filesetpredicate' instance in example above can be used to
     decorate multiple functions.
 
     Decorated functions are registered automatically at loading
     extension, if an instance named as 'filesetpredicate' is used for
     decorating in extension.
 
     Otherwise, explicit 'fileset.loadpredicate()' is needed.