[PATCH] revset: allow negative integers to list child revs

Sean Farley sean.michael.farley at gmail.com
Sat Oct 4 11:57:59 CDT 2014


# HG changeset patch
# User Sean Farley <sean.michael.farley at gmail.com>
# Date 1412441841 25200
#      Sat Oct 04 09:57:21 2014 -0700
# Node ID c3bd6d6457bf42d2fbcaba89cf0418a0d0604239
# Parent  78c916f24dd99a56e4c29153a5df3bd7d1c40edd
revset: allow negative integers to list child revs

With the heavy use of changeset evolution, it often becomes convenient (read:
necessary) to refer to a child revset easily. This patch introduces ^-1 as a
way to do that.

RFC: This syntax was the most appropriate that I could find: ^{0,1,2} refers to
a changeset's zeroth (meaning itself), first, or second parent. Therefore,
^{-1,-2,-3,...} refers to the nth child of a changeset.

TODO:
 - If accepted we'd have to change the error message away from just saying "0,
   1, or 2"

 - Allow or disallow .~-N

 - Add documentation / examples

diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -1250,11 +1250,11 @@ def parentspec(repo, subset, x, n):
     ``set^1`` (or ``set^``), ``set^2``
     First or second parent, respectively, of all changesets in set.
     """
     try:
         n = int(n[1])
-        if n not in (0, 1, 2):
+        if n > 2:
             raise ValueError
     except (TypeError, ValueError):
         raise error.ParseError(_("^ expects a number 0, 1, or 2"))
     ps = set()
     cl = repo.changelog
@@ -1265,10 +1265,16 @@ def parentspec(repo, subset, x, n):
             ps.add(cl.parentrevs(r)[0])
         elif n == 2:
             parents = cl.parentrevs(r)
             if len(parents) > 1:
                 ps.add(parents[1])
+        else: # negative number means the nth-child
+            children = cl.children(repo[r].node())
+            idx = -n-1
+            if children and idx < len(children):
+                ps.add(repo[children[idx]].rev())
+
     return subset & ps
 
 def present(repo, subset, x):
     """``present(set)``
     An empty set, if any revision in set isn't found; otherwise,
diff --git a/tests/test-revset.t b/tests/test-revset.t
--- a/tests/test-revset.t
+++ b/tests/test-revset.t
@@ -778,10 +778,18 @@ multiple revspecs
   4
   5
   6
   7
 
+test getting child revs
+
+  $ log 'merge()~3^-1'
+  2
+  $ log 'merge()~3^-2'
+  3
+
+
 test usage in revpair (with "+")
 
 (real pair)
 
   $ hg diff -r 'tip^^' -r 'tip'


More information about the Mercurial-devel mailing list