D657: revset: move weight information to predicate
quark (Jun Wu)
phabricator at mercurial-scm.org
Mon Sep 18 19:47:15 EDT 2017
quark updated this revision to Diff 1882.
REPOSITORY
rHG Mercurial
CHANGES SINCE LAST UPDATE
https://phab.mercurial-scm.org/D657?vs=1666&id=1882
REVISION DETAIL
https://phab.mercurial-scm.org/D657
AFFECTED FILES
mercurial/registrar.py
mercurial/revset.py
mercurial/revsetlang.py
CHANGE DETAILS
diff --git a/mercurial/revsetlang.py b/mercurial/revsetlang.py
--- a/mercurial/revsetlang.py
+++ b/mercurial/revsetlang.py
@@ -49,6 +49,8 @@
keywords = {'and', 'or', 'not'}
+symbols = {}
+
_quoteletters = {'"', "'"}
_simpleopletters = set(pycompat.iterbytestr("()[]#:=,-|&+!~^%"))
@@ -441,21 +443,7 @@
elif op == 'func':
f = getsymbol(x[1])
wa, ta = _optimize(x[2])
- if f in ('author', 'branch', 'closed', 'date', 'desc', 'file', 'grep',
- 'keyword', 'outgoing', 'user', 'destination'):
- w = 10 # slow
- elif f in ('modifies', 'adds', 'removes'):
- w = 30 # slower
- elif f == "contains":
- w = 100 # very slow
- elif f == "ancestor":
- w = 0.5
- elif f in ('reverse', 'limit', 'first', 'wdir', '_intlist'):
- w = 0
- elif f == "sort":
- w = 10 # assume most sorts look at changelog
- else:
- w = 1
+ w = getattr(symbols.get(f), '_weight', 1)
return w + wa, (op, x[1], ta)
raise ValueError('invalid operator %r' % op)
diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -253,7 +253,7 @@
# repo - current repository instance
# subset - of revisions to be examined
# x - argument in tree form
-symbols = {}
+symbols = revsetlang.symbols
# symbols which can't be used for a DoS attack for any given input
# (e.g. those which accept regexes as plain strings shouldn't be included)
@@ -276,7 +276,7 @@
sourceset = getset(repo, fullreposet(repo), x)
return subset & baseset([destutil.destmerge(repo, sourceset=sourceset)])
- at predicate('adds(pattern)', safe=True)
+ at predicate('adds(pattern)', safe=True, weight=30)
def adds(repo, subset, x):
"""Changesets that add a file matching pattern.
@@ -288,7 +288,7 @@
pat = getstring(x, _("adds requires a pattern"))
return checkstatus(repo, subset, pat, 1)
- at predicate('ancestor(*changeset)', safe=True)
+ at predicate('ancestor(*changeset)', safe=True, weight=0.5)
def ancestor(repo, subset, x):
"""A greatest common ancestor of the changesets.
@@ -394,7 +394,7 @@
ps.add(r)
return subset & ps
- at predicate('author(string)', safe=True)
+ at predicate('author(string)', safe=True, weight=10)
def author(repo, subset, x):
"""Alias for ``user(string)``.
"""
@@ -462,7 +462,7 @@
bms -= {node.nullrev}
return subset & bms
- at predicate('branch(string or set)', safe=True)
+ at predicate('branch(string or set)', safe=True, weight=10)
def branch(repo, subset, x):
"""
All changesets belonging to the given branch or the branches of the given
@@ -595,16 +595,16 @@
cs = _children(repo, subset, s)
return subset & cs
- at predicate('closed()', safe=True)
+ at 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>')
- at predicate('contains(pattern)')
+ at predicate('contains(pattern)', weight=100)
def contains(repo, subset, x):
"""The revision's manifest contains a file matching pattern (but might not
modify it). See :hg:`help patterns` for information about file patterns.
@@ -654,7 +654,7 @@
return subset.filter(lambda r: _matchvalue(r),
condrepr=('<converted %r>', rev))
- at predicate('date(interval)', safe=True)
+ at predicate('date(interval)', safe=True, weight=10)
def date(repo, subset, x):
"""Changesets within the interval, see :hg:`help dates`.
"""
@@ -664,7 +664,7 @@
return subset.filter(lambda x: dm(repo[x].date()[0]),
condrepr=('<date %r>', ds))
- at predicate('desc(string)', safe=True)
+ at predicate('desc(string)', safe=True, weight=10)
def desc(repo, subset, x):
"""Search commit message for string. The match is case-insensitive.
@@ -722,7 +722,7 @@
# Like ``descendants(set)`` but follows only the first parents.
return _descendants(repo, subset, x, followfirst=True)
- at predicate('destination([set])', safe=True)
+ at predicate('destination([set])', safe=True, weight=10)
def destination(repo, subset, x):
"""Changesets that were created by a graft, transplant or rebase operation,
with the given revisions specified as the source. Omitting the optional set
@@ -891,7 +891,7 @@
return subset & s
- at predicate('first(set, [n])', safe=True, takeorder=True)
+ at predicate('first(set, [n])', safe=True, takeorder=True, weight=0)
def first(repo, subset, x, order):
"""An alias for limit().
"""
@@ -1012,7 +1012,7 @@
getargs(x, 0, 0, _("all takes no arguments"))
return subset & spanset(repo) # drop "null" if any
- at predicate('grep(regex)')
+ at predicate('grep(regex)', weight=10)
def grep(repo, subset, x):
"""Like ``keyword(string)`` but accepts a regex. Use ``grep(r'...')``
to ensure special escape characters are handled correctly. Unlike
@@ -1097,7 +1097,7 @@
'exclude=%r, default=%r, rev=%r>',
pats, inc, exc, default, rev))
- at predicate('file(pattern)', safe=True)
+ at predicate('file(pattern)', safe=True, weight=10)
def hasfile(repo, subset, x):
"""Changesets affecting files matched by pattern.
@@ -1139,7 +1139,7 @@
hiddenrevs = repoview.filterrevs(repo, 'visible')
return subset & hiddenrevs
- at predicate('keyword(string)', safe=True)
+ at predicate('keyword(string)', safe=True, weight=10)
def keyword(repo, subset, x):
"""Search commit message, user name, and names of changed files for
string. The match is case-insensitive.
@@ -1157,7 +1157,7 @@
return subset.filter(matches, condrepr=('<keyword %r>', kw))
- at predicate('limit(set[, n[, offset]])', safe=True, takeorder=True)
+ at 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.
"""
@@ -1259,7 +1259,7 @@
pass
return baseset(datarepr=('<min %r, %r>', subset, os))
- at predicate('modifies(pattern)', safe=True)
+ at predicate('modifies(pattern)', safe=True, weight=30)
def modifies(repo, subset, x):
"""Changesets modifying files matched by pattern.
@@ -1403,7 +1403,7 @@
# some optimizations from the fact this is a baseset.
return subset & o
- at predicate('outgoing([path])', safe=False)
+ at predicate('outgoing([path])', safe=False, weight=10)
def outgoing(repo, subset, x):
"""Changesets not found in the specified destination repository, or the
default push location.
@@ -1654,7 +1654,7 @@
return baseset([r])
return baseset()
- at predicate('removes(pattern)', safe=True)
+ at predicate('removes(pattern)', safe=True, weight=30)
def removes(repo, subset, x):
"""Changesets which remove files matching pattern.
@@ -1794,7 +1794,7 @@
return subset.filter(matches, condrepr=('<matching%r %r>', fields, revs))
- at predicate('reverse(set)', safe=True, takeorder=True)
+ at predicate('reverse(set)', safe=True, takeorder=True, weight=0)
def reverse(repo, subset, x, order):
"""Reverse order of set.
"""
@@ -1862,7 +1862,8 @@
return args['set'], keyflags, opts
- at predicate('sort(set[, [-]key... [, ...]])', safe=True, takeorder=True)
+ at 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.
@@ -2033,16 +2034,16 @@
return subset & orphan
- at predicate('user(string)', safe=True)
+ at predicate('user(string)', safe=True, weight=10)
def user(repo, subset, x):
"""User name contains string. The match is case-insensitive.
Pattern matching is supported for `string`. See
:hg:`help revisions.patterns`.
"""
return author(repo, subset, x)
- at predicate('wdir()', safe=True)
+ at predicate('wdir()', safe=True, weight=0)
def wdir(repo, subset, x):
"""Working directory. (EXPERIMENTAL)"""
# i18n: "wdir" is a keyword
@@ -2097,7 +2098,7 @@
return baseset([r for r in ls if r in s])
# for internal use
- at predicate('_intlist', safe=True, takeorder=True)
+ at predicate('_intlist', safe=True, takeorder=True, weight=0)
def _intlist(repo, subset, x, order):
if order == followorder:
# slow path to take the subset order
diff --git a/mercurial/registrar.py b/mercurial/registrar.py
--- a/mercurial/registrar.py
+++ b/mercurial/registrar.py
@@ -166,6 +166,16 @@
Optional argument 'takeorder' indicates whether a predicate function
takes ordering policy as the last argument.
+ Optional argument 'weight' indicates the estimated run-time cost, useful
+ for static optimization, default is 1. Higher weight means more expensive.
+ Usually, revsets that are fast and returns only one single revision has a
+ weight of 0.5 (ex. a string symbol); revsets with O(changelog) complexity
+ have weight 10 (ex. author); revsets which also needs reading manifest
+ diffs usually have weight 30 (ex. adds); revset reading file contents
+ usually have weight 100 (ex. contains). Note: those values are not
+ absolute, if the revset has a same big-O time complexity as `contains`,
+ but with a smaller constant, it might have a weight of 90.
+
'revsetpredicate' instance in example above can be used to
decorate multiple functions.
@@ -178,9 +188,10 @@
_getname = _funcregistrarbase._parsefuncdecl
_docformat = "``%s``\n %s"
- def _extrasetup(self, name, func, safe=False, takeorder=False):
+ def _extrasetup(self, name, func, safe=False, takeorder=False, weight=1):
func._safe = safe
func._takeorder = takeorder
+ func._weight = weight
class filesetpredicate(_funcregistrarbase):
"""Decorator to register fileset predicate
To: quark, #hg-reviewers, phillco, krbullock
Cc: krbullock, yuja, phillco, mercurial-devel
More information about the Mercurial-devel
mailing list