Mercurial > public > mercurial-scm > hg-stable
diff mercurial/revset.py @ 34029:1b28525e6698
revset: remove order information from tree (API)
Keeping `order` in tree makes AST operation harder. And there could be
invalid cases if trees could be generated and compounded freely, like:
SetA(order=define) & SetB(order=define)
^^^^^^ couldn't be satisfied
This patch changes the code to calculate order on the fly, during tree
traversal. Optimization of reordering `and` arguments is preserved by
introducing a new internal operation `flipand`.
.. api::
revset.stringset() now takes 'order' as the last argument.
Differential Revision: https://phab.mercurial-scm.org/D451
author | Jun Wu <quark@fb.com> |
---|---|
date | Sun, 20 Aug 2017 10:55:11 -0700 |
parents | 457d1ebf151b |
children | 96f249dce03e |
line wrap: on
line diff
--- a/mercurial/revset.py Mon Aug 28 23:44:47 2017 -0700 +++ b/mercurial/revset.py Sun Aug 20 10:55:11 2017 -0700 @@ -52,10 +52,10 @@ # helpers -def getset(repo, subset, x): +def getset(repo, subset, x, order=defineorder): if not x: raise error.ParseError(_("missing argument")) - return methods[x[0]](repo, subset, *x[1:]) + return methods[x[0]](repo, subset, *x[1:], order=order) def _getrevsource(repo, r): extra = repo[r].extra() @@ -69,7 +69,7 @@ # operator methods -def stringset(repo, subset, x): +def stringset(repo, subset, x, order): x = scmutil.intrev(repo[x]) if (x in subset or x == node.nullrev and isinstance(subset, fullreposet)): @@ -126,30 +126,42 @@ return subset & xs def andset(repo, subset, x, y, order): - return getset(repo, getset(repo, subset, x), y) + if order == anyorder: + yorder = anyorder + else: + yorder = followorder + return getset(repo, getset(repo, subset, x, order), y, yorder) + +def flipandset(repo, subset, y, x, order): + # 'flipand(y, x)' is equivalent to 'and(x, y)', but faster when y is small + if order == anyorder: + yorder = anyorder + else: + yorder = followorder + return getset(repo, getset(repo, subset, y, yorder), x, order) def differenceset(repo, subset, x, y, order): - return getset(repo, subset, x) - getset(repo, subset, y) + return getset(repo, subset, x, order) - getset(repo, subset, y, anyorder) -def _orsetlist(repo, subset, xs): +def _orsetlist(repo, subset, xs, order): assert xs if len(xs) == 1: - return getset(repo, subset, xs[0]) + return getset(repo, subset, xs[0], order) p = len(xs) // 2 - a = _orsetlist(repo, subset, xs[:p]) - b = _orsetlist(repo, subset, xs[p:]) + a = _orsetlist(repo, subset, xs[:p], order) + b = _orsetlist(repo, subset, xs[p:], order) return a + b def orset(repo, subset, x, order): xs = getlist(x) if order == followorder: # slow path to take the subset order - return subset & _orsetlist(repo, fullreposet(repo), xs) + return subset & _orsetlist(repo, fullreposet(repo), xs, anyorder) else: - return _orsetlist(repo, subset, xs) + return _orsetlist(repo, subset, xs, order) def notset(repo, subset, x, order): - return subset - getset(repo, subset, x) + 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")) @@ -176,11 +188,11 @@ def subscriptset(repo, subset, x, y, order): raise error.ParseError(_("can't use a subscript in this context")) -def listset(repo, subset, *xs): +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"')) -def keyvaluepair(repo, subset, k, v): +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): @@ -1508,8 +1520,8 @@ ps.add(parents[1].rev()) return subset & ps -@predicate('present(set)', safe=True) -def present(repo, subset, x): +@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, all revisions in set. @@ -1518,7 +1530,7 @@ to continue even in such cases. """ try: - return getset(repo, subset, x) + return getset(repo, subset, x, order) except error.RepoLookupError: return baseset() @@ -1718,7 +1730,7 @@ def reverse(repo, subset, x, order): """Reverse order of set. """ - l = getset(repo, subset, x) + l = getset(repo, subset, x, order) if order == defineorder: l.reverse() return l @@ -1802,7 +1814,7 @@ """ s, keyflags, opts = _getsortargs(x) - revs = getset(repo, subset, s) + revs = getset(repo, subset, s, order) if not keyflags or order != defineorder: return revs @@ -1988,7 +2000,7 @@ raise ValueError revs = [r] except ValueError: - revs = stringset(repo, subset, t) + revs = stringset(repo, subset, t, defineorder) for r in revs: if r in seen: @@ -2052,6 +2064,7 @@ "string": stringset, "symbol": stringset, "and": andset, + "flipand": flipandset, "or": orset, "not": notset, "difference": differenceset, @@ -2113,17 +2126,17 @@ if aliases: tree = revsetlang.expandaliases(tree, aliases, warn=warn) tree = revsetlang.foldconcat(tree) - tree = revsetlang.analyze(tree, order) + tree = revsetlang.analyze(tree) tree = revsetlang.optimize(tree) posttreebuilthook(tree, repo) - return makematcher(tree) + return makematcher(tree, order) -def makematcher(tree): +def makematcher(tree, order=defineorder): """Create a matcher from an evaluatable tree""" def mfunc(repo, subset=None): if subset is None: subset = fullreposet(repo) - return getset(repo, subset, tree) + return getset(repo, subset, tree, order) return mfunc def loadpredicate(ui, extname, registrarobj):