Patchwork [3,of,3] revset: add experimental ancestors/descendants relation subscript

login
register
mail settings
Submitter Yuya Nishihara
Date July 13, 2017, 4:16 p.m.
Message ID <660613df4ea547c78b4a.1499962579@mimosa>
Download mbox | patch
Permalink /patch/22296/
State Accepted
Headers show

Comments

Yuya Nishihara - July 13, 2017, 4:16 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1499487317 -32400
#      Sat Jul 08 13:15:17 2017 +0900
# Node ID 660613df4ea547c78b4ae06e20e4af46399dc02f
# Parent  eed6cd6aa792698d0535f276e150f88500943866
revset: add experimental ancestors/descendants relation subscript

The relation name is 'generations' now, which may be changed in future.
Sean Farley - July 13, 2017, 6:15 p.m.
Yuya Nishihara <yuya@tcha.org> writes:

> # HG changeset patch
> # User Yuya Nishihara <yuya@tcha.org>
> # Date 1499487317 -32400
> #      Sat Jul 08 13:15:17 2017 +0900
> # Node ID 660613df4ea547c78b4ae06e20e4af46399dc02f
> # Parent  eed6cd6aa792698d0535f276e150f88500943866
> revset: add experimental ancestors/descendants relation subscript
>
> The relation name is 'generations' now, which may be changed in future.

Thanks for adding this, Yuya! Queued!

Patch

diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -155,7 +155,23 @@  def relationset(repo, subset, x, y, orde
     raise error.ParseError(_("can't use a relation in this context"))
 
 def relsubscriptset(repo, subset, x, y, z, order):
-    raise error.ParseError(_("can't use a relation in this context"))
+    # this is pretty basic implementation of 'x#y[z]' operator, still
+    # experimental so undocumented. see the wiki for further ideas.
+    # https://www.mercurial-scm.org/wiki/RevsetOperatorPlan
+    rel = getsymbol(y)
+    n = getinteger(z, _("relation subscript must be an integer"))
+
+    # TODO: perhaps this should be a table of relation functions
+    if rel in ('g', 'generations'):
+        # TODO: support range, rewrite tests, and drop startdepth argument
+        # from ancestors() and descendants() predicates
+        if n <= 0:
+            n = -n
+            return _ancestors(repo, subset, x, startdepth=n, stopdepth=n + 1)
+        else:
+            return _descendants(repo, subset, x, startdepth=n, stopdepth=n + 1)
+
+    raise error.UnknownIdentifier(rel, ['generations'])
 
 def subscriptset(repo, subset, x, y, order):
     raise error.ParseError(_("can't use a subscript in this context"))
diff --git a/tests/test-revset.t b/tests/test-revset.t
--- a/tests/test-revset.t
+++ b/tests/test-revset.t
@@ -512,8 +512,12 @@  relation-subscript operator has the high
       ('symbol', 'generations')
       (negate
         ('symbol', '1'))))
-  hg: parse error: can't use a relation in this context
-  [255]
+  9
+  8
+  7
+  6
+  5
+  4
 
   $ hg debugrevspec -p parsed --no-show-revs 'not public()#generations[0]'
   * parsed:
@@ -524,8 +528,6 @@  relation-subscript operator has the high
         None)
       ('symbol', 'generations')
       ('symbol', '0')))
-  hg: parse error: can't use a relation in this context
-  [255]
 
 left-hand side of relation-subscript operator should be optimized recursively:
 
@@ -551,8 +553,6 @@  left-hand side of relation-subscript ope
     ('symbol', 'generations')
     ('symbol', '0')
     define)
-  hg: parse error: can't use a relation in this context
-  [255]
 
 resolution of subscript and relation-subscript ternary operators:
 
@@ -572,7 +572,7 @@  resolution of subscript and relation-sub
     ('symbol', 'rel')
     ('symbol', '0')
     define)
-  hg: parse error: can't use a relation in this context
+  hg: parse error: unknown identifier: rel
   [255]
 
   $ hg debugrevspec -p analyzed '(tip#rel)[0]'
@@ -610,7 +610,7 @@  resolution of subscript and relation-sub
     ('symbol', 'rel1')
     ('symbol', '1')
     define)
-  hg: parse error: can't use a relation in this context
+  hg: parse error: unknown identifier: rel1
   [255]
 
   $ hg debugrevspec -p analyzed 'tip#rel0[0]#rel1[1]'
@@ -624,7 +624,7 @@  resolution of subscript and relation-sub
     ('symbol', 'rel1')
     ('symbol', '1')
     define)
-  hg: parse error: can't use a relation in this context
+  hg: parse error: unknown identifier: rel1
   [255]
 
 parse errors of relation, subscript and relation-subscript operators:
@@ -645,6 +645,13 @@  parse errors of relation, subscript and 
   hg: parse error at 1: invalid token
   [255]
 
+  $ hg debugrevspec '.#generations[a]'
+  hg: parse error: relation subscript must be an integer
+  [255]
+  $ hg debugrevspec '.#generations[1-2]'
+  hg: parse error: relation subscript must be an integer
+  [255]
+
 parsed tree at stages:
 
   $ hg debugrevspec -p all '()'
@@ -1180,6 +1187,27 @@  test descendants with depth limit
   5
   7
 
+test ancestors/descendants relation subscript:
+
+  $ log 'tip#generations[0]'
+  9
+  $ log '.#generations[-1]'
+  8
+  $ log '.#g[(-1)]'
+  8
+
+  $ hg debugrevspec -p parsed 'roots(:)#g[2]'
+  * parsed:
+  (relsubscript
+    (func
+      ('symbol', 'roots')
+      (rangeall
+        None))
+    ('symbol', 'g')
+    ('symbol', '2'))
+  2
+  3
+
 test author
 
   $ log 'author(bob)'