Patchwork [2,of,3] revsetlang: check arguments passed to ancestors() before optimizing to only()

login
register
mail settings
Submitter Yuya Nishihara
Date June 19, 2017, 2:43 p.m.
Message ID <870d869fd996ee5d8838.1497883416@mimosa>
Download mbox | patch
Permalink /patch/21504/
State Accepted
Headers show

Comments

Yuya Nishihara - June 19, 2017, 2:43 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1497754648 -32400
#      Sun Jun 18 11:57:28 2017 +0900
# Node ID 870d869fd996ee5d8838d378d866ae34d43739a6
# Parent  8785d4150c89c608d598c6ebaa2ca2e57d2e7f9a
revsetlang: check arguments passed to ancestors() before optimizing to only()

Future patches will add depth parameter to ancestors(), which isn't compatible
with only().
via Mercurial-devel - June 20, 2017, 4:31 a.m.
On Mon, Jun 19, 2017 at 7:43 AM, Yuya Nishihara <yuya@tcha.org> wrote:
> # HG changeset patch
> # User Yuya Nishihara <yuya@tcha.org>
> # Date 1497754648 -32400
> #      Sun Jun 18 11:57:28 2017 +0900
> # Node ID 870d869fd996ee5d8838d378d866ae34d43739a6
> # Parent  8785d4150c89c608d598c6ebaa2ca2e57d2e7f9a
> revsetlang: check arguments passed to ancestors() before optimizing to only()

Queued, thanks.

Patch

diff --git a/mercurial/revsetlang.py b/mercurial/revsetlang.py
--- a/mercurial/revsetlang.py
+++ b/mercurial/revsetlang.py
@@ -240,6 +240,11 @@  def _isnamedfunc(x, funcname):
     """Check if given tree matches named function"""
     return x and x[0] == 'func' and getsymbol(x[1]) == funcname
 
+def _isposargs(x, n):
+    """Check if given tree is n-length list of positional arguments"""
+    l = getlist(x)
+    return len(l) == n and all(y and y[0] != 'keyvalue' for y in l)
+
 def _matchnamedfunc(x, funcname):
     """Return args tree if given tree matches named function; otherwise None
 
@@ -302,7 +307,7 @@  def _matchonly(revs, bases):
     """
     ta = _matchnamedfunc(revs, 'ancestors')
     tb = bases and bases[0] == 'not' and _matchnamedfunc(bases[1], 'ancestors')
-    if ta and tb:
+    if _isposargs(ta, 1) and _isposargs(tb, 1):
         return ('list', ta, tb)
 
 def _fixops(x):
diff --git a/tests/test-revset.t b/tests/test-revset.t
--- a/tests/test-revset.t
+++ b/tests/test-revset.t
@@ -2980,6 +2980,65 @@  no crash by empty group "()" while optim
   hg: parse error: missing argument
   [255]
 
+optimization to only() works only if ancestors() takes only one argument
+
+  $ hg debugrevspec -p optimized 'ancestors(6) - ancestors(4, 1)'
+  * optimized:
+  (difference
+    (func
+      ('symbol', 'ancestors')
+      ('symbol', '6')
+      define)
+    (func
+      ('symbol', 'ancestors')
+      (list
+        ('symbol', '4')
+        ('symbol', '1'))
+      any)
+    define)
+  hg: parse error: can't use a list in this context
+  (see hg help "revsets.x or y")
+  [255]
+  $ hg debugrevspec -p optimized 'ancestors(6, 1) - ancestors(4)'
+  * optimized:
+  (difference
+    (func
+      ('symbol', 'ancestors')
+      (list
+        ('symbol', '6')
+        ('symbol', '1'))
+      define)
+    (func
+      ('symbol', 'ancestors')
+      ('symbol', '4')
+      any)
+    define)
+  hg: parse error: can't use a list in this context
+  (see hg help "revsets.x or y")
+  [255]
+
+optimization disabled if keyword arguments passed (because we're too lazy
+to support it)
+
+  $ hg debugrevspec -p optimized 'ancestors(set=6) - ancestors(set=4)'
+  * optimized:
+  (difference
+    (func
+      ('symbol', 'ancestors')
+      (keyvalue
+        ('symbol', 'set')
+        ('symbol', '6'))
+      define)
+    (func
+      ('symbol', 'ancestors')
+      (keyvalue
+        ('symbol', 'set')
+        ('symbol', '4'))
+      any)
+    define)
+  hg: parse error: can't use a key-value pair in this context
+  [255]
+
 invalid function call should not be optimized to only()
 
   $ log '"ancestors"(6) and not ancestors(4)'