##// END OF EJS Templates
revset: move weight information to predicate...
Jun Wu -
r34274:b0790beb default
parent child Browse files
Show More
@@ -166,6 +166,16 b' class revsetpredicate(_funcregistrarbase'
166 Optional argument 'takeorder' indicates whether a predicate function
166 Optional argument 'takeorder' indicates whether a predicate function
167 takes ordering policy as the last argument.
167 takes ordering policy as the last argument.
168
168
169 Optional argument 'weight' indicates the estimated run-time cost, useful
170 for static optimization, default is 1. Higher weight means more expensive.
171 Usually, revsets that are fast and return only one revision has a weight of
172 0.5 (ex. a symbol); revsets with O(changelog) complexity and read only the
173 changelog have weight 10 (ex. author); revsets reading manifest deltas have
174 weight 30 (ex. adds); revset reading manifest contents have weight 100
175 (ex. contains). Note: those values are flexible. If the revset has a
176 same big-O time complexity as 'contains', but with a smaller constant, it
177 might have a weight of 90.
178
169 'revsetpredicate' instance in example above can be used to
179 'revsetpredicate' instance in example above can be used to
170 decorate multiple functions.
180 decorate multiple functions.
171
181
@@ -178,9 +188,10 b' class revsetpredicate(_funcregistrarbase'
178 _getname = _funcregistrarbase._parsefuncdecl
188 _getname = _funcregistrarbase._parsefuncdecl
179 _docformat = "``%s``\n %s"
189 _docformat = "``%s``\n %s"
180
190
181 def _extrasetup(self, name, func, safe=False, takeorder=False):
191 def _extrasetup(self, name, func, safe=False, takeorder=False, weight=1):
182 func._safe = safe
192 func._safe = safe
183 func._takeorder = takeorder
193 func._takeorder = takeorder
194 func._weight = weight
184
195
185 class filesetpredicate(_funcregistrarbase):
196 class filesetpredicate(_funcregistrarbase):
186 """Decorator to register fileset predicate
197 """Decorator to register fileset predicate
@@ -253,7 +253,7 b' def func(repo, subset, a, b, order):'
253 # repo - current repository instance
253 # repo - current repository instance
254 # subset - of revisions to be examined
254 # subset - of revisions to be examined
255 # x - argument in tree form
255 # x - argument in tree form
256 symbols = {}
256 symbols = revsetlang.symbols
257
257
258 # symbols which can't be used for a DoS attack for any given input
258 # symbols which can't be used for a DoS attack for any given input
259 # (e.g. those which accept regexes as plain strings shouldn't be included)
259 # (e.g. those which accept regexes as plain strings shouldn't be included)
@@ -276,7 +276,7 b' def _destmerge(repo, subset, x):'
276 sourceset = getset(repo, fullreposet(repo), x)
276 sourceset = getset(repo, fullreposet(repo), x)
277 return subset & baseset([destutil.destmerge(repo, sourceset=sourceset)])
277 return subset & baseset([destutil.destmerge(repo, sourceset=sourceset)])
278
278
279 @predicate('adds(pattern)', safe=True)
279 @predicate('adds(pattern)', safe=True, weight=30)
280 def adds(repo, subset, x):
280 def adds(repo, subset, x):
281 """Changesets that add a file matching pattern.
281 """Changesets that add a file matching pattern.
282
282
@@ -288,7 +288,7 b' def adds(repo, subset, x):'
288 pat = getstring(x, _("adds requires a pattern"))
288 pat = getstring(x, _("adds requires a pattern"))
289 return checkstatus(repo, subset, pat, 1)
289 return checkstatus(repo, subset, pat, 1)
290
290
291 @predicate('ancestor(*changeset)', safe=True)
291 @predicate('ancestor(*changeset)', safe=True, weight=0.5)
292 def ancestor(repo, subset, x):
292 def ancestor(repo, subset, x):
293 """A greatest common ancestor of the changesets.
293 """A greatest common ancestor of the changesets.
294
294
@@ -394,7 +394,7 b' def ancestorspec(repo, subset, x, n, ord'
394 ps.add(r)
394 ps.add(r)
395 return subset & ps
395 return subset & ps
396
396
397 @predicate('author(string)', safe=True)
397 @predicate('author(string)', safe=True, weight=10)
398 def author(repo, subset, x):
398 def author(repo, subset, x):
399 """Alias for ``user(string)``.
399 """Alias for ``user(string)``.
400 """
400 """
@@ -462,7 +462,7 b' def bookmark(repo, subset, x):'
462 bms -= {node.nullrev}
462 bms -= {node.nullrev}
463 return subset & bms
463 return subset & bms
464
464
465 @predicate('branch(string or set)', safe=True)
465 @predicate('branch(string or set)', safe=True, weight=10)
466 def branch(repo, subset, x):
466 def branch(repo, subset, x):
467 """
467 """
468 All changesets belonging to the given branch or the branches of the given
468 All changesets belonging to the given branch or the branches of the given
@@ -595,7 +595,7 b' def children(repo, subset, x):'
595 cs = _children(repo, subset, s)
595 cs = _children(repo, subset, s)
596 return subset & cs
596 return subset & cs
597
597
598 @predicate('closed()', safe=True)
598 @predicate('closed()', safe=True, weight=10)
599 def closed(repo, subset, x):
599 def closed(repo, subset, x):
600 """Changeset is closed.
600 """Changeset is closed.
601 """
601 """
@@ -604,7 +604,7 b' def closed(repo, subset, x):'
604 return subset.filter(lambda r: repo[r].closesbranch(),
604 return subset.filter(lambda r: repo[r].closesbranch(),
605 condrepr='<branch closed>')
605 condrepr='<branch closed>')
606
606
607 @predicate('contains(pattern)')
607 @predicate('contains(pattern)', weight=100)
608 def contains(repo, subset, x):
608 def contains(repo, subset, x):
609 """The revision's manifest contains a file matching pattern (but might not
609 """The revision's manifest contains a file matching pattern (but might not
610 modify it). See :hg:`help patterns` for information about file patterns.
610 modify it). See :hg:`help patterns` for information about file patterns.
@@ -654,7 +654,7 b' def converted(repo, subset, x):'
654 return subset.filter(lambda r: _matchvalue(r),
654 return subset.filter(lambda r: _matchvalue(r),
655 condrepr=('<converted %r>', rev))
655 condrepr=('<converted %r>', rev))
656
656
657 @predicate('date(interval)', safe=True)
657 @predicate('date(interval)', safe=True, weight=10)
658 def date(repo, subset, x):
658 def date(repo, subset, x):
659 """Changesets within the interval, see :hg:`help dates`.
659 """Changesets within the interval, see :hg:`help dates`.
660 """
660 """
@@ -664,7 +664,7 b' def date(repo, subset, x):'
664 return subset.filter(lambda x: dm(repo[x].date()[0]),
664 return subset.filter(lambda x: dm(repo[x].date()[0]),
665 condrepr=('<date %r>', ds))
665 condrepr=('<date %r>', ds))
666
666
667 @predicate('desc(string)', safe=True)
667 @predicate('desc(string)', safe=True, weight=10)
668 def desc(repo, subset, x):
668 def desc(repo, subset, x):
669 """Search commit message for string. The match is case-insensitive.
669 """Search commit message for string. The match is case-insensitive.
670
670
@@ -722,7 +722,7 b' def _firstdescendants(repo, subset, x):'
722 # Like ``descendants(set)`` but follows only the first parents.
722 # Like ``descendants(set)`` but follows only the first parents.
723 return _descendants(repo, subset, x, followfirst=True)
723 return _descendants(repo, subset, x, followfirst=True)
724
724
725 @predicate('destination([set])', safe=True)
725 @predicate('destination([set])', safe=True, weight=10)
726 def destination(repo, subset, x):
726 def destination(repo, subset, x):
727 """Changesets that were created by a graft, transplant or rebase operation,
727 """Changesets that were created by a graft, transplant or rebase operation,
728 with the given revisions specified as the source. Omitting the optional set
728 with the given revisions specified as the source. Omitting the optional set
@@ -891,7 +891,7 b' def filelog(repo, subset, x):'
891
891
892 return subset & s
892 return subset & s
893
893
894 @predicate('first(set, [n])', safe=True, takeorder=True)
894 @predicate('first(set, [n])', safe=True, takeorder=True, weight=0)
895 def first(repo, subset, x, order):
895 def first(repo, subset, x, order):
896 """An alias for limit().
896 """An alias for limit().
897 """
897 """
@@ -1012,7 +1012,7 b' def getall(repo, subset, x):'
1012 getargs(x, 0, 0, _("all takes no arguments"))
1012 getargs(x, 0, 0, _("all takes no arguments"))
1013 return subset & spanset(repo) # drop "null" if any
1013 return subset & spanset(repo) # drop "null" if any
1014
1014
1015 @predicate('grep(regex)')
1015 @predicate('grep(regex)', weight=10)
1016 def grep(repo, subset, x):
1016 def grep(repo, subset, x):
1017 """Like ``keyword(string)`` but accepts a regex. Use ``grep(r'...')``
1017 """Like ``keyword(string)`` but accepts a regex. Use ``grep(r'...')``
1018 to ensure special escape characters are handled correctly. Unlike
1018 to ensure special escape characters are handled correctly. Unlike
@@ -1097,7 +1097,7 b' def _matchfiles(repo, subset, x):'
1097 'exclude=%r, default=%r, rev=%r>',
1097 'exclude=%r, default=%r, rev=%r>',
1098 pats, inc, exc, default, rev))
1098 pats, inc, exc, default, rev))
1099
1099
1100 @predicate('file(pattern)', safe=True)
1100 @predicate('file(pattern)', safe=True, weight=10)
1101 def hasfile(repo, subset, x):
1101 def hasfile(repo, subset, x):
1102 """Changesets affecting files matched by pattern.
1102 """Changesets affecting files matched by pattern.
1103
1103
@@ -1139,7 +1139,7 b' def hidden(repo, subset, x):'
1139 hiddenrevs = repoview.filterrevs(repo, 'visible')
1139 hiddenrevs = repoview.filterrevs(repo, 'visible')
1140 return subset & hiddenrevs
1140 return subset & hiddenrevs
1141
1141
1142 @predicate('keyword(string)', safe=True)
1142 @predicate('keyword(string)', safe=True, weight=10)
1143 def keyword(repo, subset, x):
1143 def keyword(repo, subset, x):
1144 """Search commit message, user name, and names of changed files for
1144 """Search commit message, user name, and names of changed files for
1145 string. The match is case-insensitive.
1145 string. The match is case-insensitive.
@@ -1157,7 +1157,7 b' def keyword(repo, subset, x):'
1157
1157
1158 return subset.filter(matches, condrepr=('<keyword %r>', kw))
1158 return subset.filter(matches, condrepr=('<keyword %r>', kw))
1159
1159
1160 @predicate('limit(set[, n[, offset]])', safe=True, takeorder=True)
1160 @predicate('limit(set[, n[, offset]])', safe=True, takeorder=True, weight=0)
1161 def limit(repo, subset, x, order):
1161 def limit(repo, subset, x, order):
1162 """First n members of set, defaulting to 1, starting from offset.
1162 """First n members of set, defaulting to 1, starting from offset.
1163 """
1163 """
@@ -1259,7 +1259,7 b' def minrev(repo, subset, x):'
1259 pass
1259 pass
1260 return baseset(datarepr=('<min %r, %r>', subset, os))
1260 return baseset(datarepr=('<min %r, %r>', subset, os))
1261
1261
1262 @predicate('modifies(pattern)', safe=True)
1262 @predicate('modifies(pattern)', safe=True, weight=30)
1263 def modifies(repo, subset, x):
1263 def modifies(repo, subset, x):
1264 """Changesets modifying files matched by pattern.
1264 """Changesets modifying files matched by pattern.
1265
1265
@@ -1403,7 +1403,7 b' def origin(repo, subset, x):'
1403 # some optimizations from the fact this is a baseset.
1403 # some optimizations from the fact this is a baseset.
1404 return subset & o
1404 return subset & o
1405
1405
1406 @predicate('outgoing([path])', safe=False)
1406 @predicate('outgoing([path])', safe=False, weight=10)
1407 def outgoing(repo, subset, x):
1407 def outgoing(repo, subset, x):
1408 """Changesets not found in the specified destination repository, or the
1408 """Changesets not found in the specified destination repository, or the
1409 default push location.
1409 default push location.
@@ -1654,7 +1654,7 b' def remote(repo, subset, x):'
1654 return baseset([r])
1654 return baseset([r])
1655 return baseset()
1655 return baseset()
1656
1656
1657 @predicate('removes(pattern)', safe=True)
1657 @predicate('removes(pattern)', safe=True, weight=30)
1658 def removes(repo, subset, x):
1658 def removes(repo, subset, x):
1659 """Changesets which remove files matching pattern.
1659 """Changesets which remove files matching pattern.
1660
1660
@@ -1794,7 +1794,7 b' def matching(repo, subset, x):'
1794
1794
1795 return subset.filter(matches, condrepr=('<matching%r %r>', fields, revs))
1795 return subset.filter(matches, condrepr=('<matching%r %r>', fields, revs))
1796
1796
1797 @predicate('reverse(set)', safe=True, takeorder=True)
1797 @predicate('reverse(set)', safe=True, takeorder=True, weight=0)
1798 def reverse(repo, subset, x, order):
1798 def reverse(repo, subset, x, order):
1799 """Reverse order of set.
1799 """Reverse order of set.
1800 """
1800 """
@@ -1862,7 +1862,8 b' def _getsortargs(x):'
1862
1862
1863 return args['set'], keyflags, opts
1863 return args['set'], keyflags, opts
1864
1864
1865 @predicate('sort(set[, [-]key... [, ...]])', safe=True, takeorder=True)
1865 @predicate('sort(set[, [-]key... [, ...]])', safe=True, takeorder=True,
1866 weight=10)
1866 def sort(repo, subset, x, order):
1867 def sort(repo, subset, x, order):
1867 """Sort set by keys. The default sort order is ascending, specify a key
1868 """Sort set by keys. The default sort order is ascending, specify a key
1868 as ``-key`` to sort in descending order.
1869 as ``-key`` to sort in descending order.
@@ -2033,7 +2034,7 b' def orphan(repo, subset, x):'
2033 return subset & orphan
2034 return subset & orphan
2034
2035
2035
2036
2036 @predicate('user(string)', safe=True)
2037 @predicate('user(string)', safe=True, weight=10)
2037 def user(repo, subset, x):
2038 def user(repo, subset, x):
2038 """User name contains string. The match is case-insensitive.
2039 """User name contains string. The match is case-insensitive.
2039
2040
@@ -2042,7 +2043,7 b' def user(repo, subset, x):'
2042 """
2043 """
2043 return author(repo, subset, x)
2044 return author(repo, subset, x)
2044
2045
2045 @predicate('wdir()', safe=True)
2046 @predicate('wdir()', safe=True, weight=0)
2046 def wdir(repo, subset, x):
2047 def wdir(repo, subset, x):
2047 """Working directory. (EXPERIMENTAL)"""
2048 """Working directory. (EXPERIMENTAL)"""
2048 # i18n: "wdir" is a keyword
2049 # i18n: "wdir" is a keyword
@@ -2097,7 +2098,7 b' def _orderedintlist(repo, subset, x):'
2097 return baseset([r for r in ls if r in s])
2098 return baseset([r for r in ls if r in s])
2098
2099
2099 # for internal use
2100 # for internal use
2100 @predicate('_intlist', safe=True, takeorder=True)
2101 @predicate('_intlist', safe=True, takeorder=True, weight=0)
2101 def _intlist(repo, subset, x, order):
2102 def _intlist(repo, subset, x, order):
2102 if order == followorder:
2103 if order == followorder:
2103 # slow path to take the subset order
2104 # slow path to take the subset order
@@ -49,6 +49,8 b' elements = {'
49
49
50 keywords = {'and', 'or', 'not'}
50 keywords = {'and', 'or', 'not'}
51
51
52 symbols = {}
53
52 _quoteletters = {'"', "'"}
54 _quoteletters = {'"', "'"}
53 _simpleopletters = set(pycompat.iterbytestr("()[]#:=,-|&+!~^%"))
55 _simpleopletters = set(pycompat.iterbytestr("()[]#:=,-|&+!~^%"))
54
56
@@ -441,21 +443,7 b' def _optimize(x):'
441 elif op == 'func':
443 elif op == 'func':
442 f = getsymbol(x[1])
444 f = getsymbol(x[1])
443 wa, ta = _optimize(x[2])
445 wa, ta = _optimize(x[2])
444 if f in ('author', 'branch', 'closed', 'date', 'desc', 'file', 'grep',
446 w = getattr(symbols.get(f), '_weight', 1)
445 'keyword', 'outgoing', 'user', 'destination'):
446 w = 10 # slow
447 elif f in ('modifies', 'adds', 'removes'):
448 w = 30 # slower
449 elif f == "contains":
450 w = 100 # very slow
451 elif f == "ancestor":
452 w = 0.5
453 elif f in ('reverse', 'limit', 'first', 'wdir', '_intlist'):
454 w = 0
455 elif f == "sort":
456 w = 10 # assume most sorts look at changelog
457 else:
458 w = 1
459 return w + wa, (op, x[1], ta)
447 return w + wa, (op, x[1], ta)
460 raise ValueError('invalid operator %r' % op)
448 raise ValueError('invalid operator %r' % op)
461
449
General Comments 0
You need to be logged in to leave comments. Login now