[PATCH 4 of 4] revset: do not nest addset by "addset + other" (issue4565)

Yuya Nishihara yuya at tcha.org
Tue May 19 07:18:21 CDT 2015


# HG changeset patch
# User Yuya Nishihara <yuya at tcha.org>
# Date 1426409247 -32400
#      Sun Mar 15 17:47:27 2015 +0900
# Node ID 72e8a0b846616a92781beda44eab8d6c39c91933
# Parent  9996864f9e14a826ebe20df3a48905a662fe8eba
revset: do not nest addset by "addset + other" (issue4565)

This fixes the crash caused by repeated -rREV options. Still chained OR
operations in single revset expression will exceed the Python stack limit
at the parsing phase.

diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -3074,6 +3074,15 @@ class unionset(abstractsmartset):
     >>> assert rs.fastdesc is None
     >>> [x for x in rs]
     [5, 4, 3, 2, 0, -1]
+
+    add set to existing union:
+    >>> rs = addset(xs, ys) + zs
+    >>> assert isinstance(rs, unionset)
+    >>> [x for x in rs]
+    [0, 3, 2, 5, 4, -1]
+    >>> rs = addset(xs, ys, ascending=True) + zs
+    >>> [x for x in rs]
+    [0, 2, 3, 4, 5, -1]
     """
     def __init__(self, subsets, ascending=None):
         self._subsets = subsets
@@ -3199,6 +3208,11 @@ class unionset(abstractsmartset):
         self.reverse()
         return val
 
+    def __add__(self, other):
+        if self._ascending is not None:
+            return super(unionset, self).__add__(other)
+        return unionset(self._subsets + [other])
+
     def __repr__(self):
         d = {None: '', False: '-', True: '+'}[self._ascending]
         return '<%s%s %s>' % (type(self).__name__, d,
diff --git a/tests/test-revset.t b/tests/test-revset.t
--- a/tests/test-revset.t
+++ b/tests/test-revset.t
@@ -142,10 +142,9 @@ trivial
       ('symbol', '1'))
     ('symbol', '2'))
   * set:
-  <addset
-    <addset
-      <baseset [0]>,
-      <baseset [1]>>,
+  <unionset
+    <baseset [0]>,
+    <baseset [1]>,
     <baseset [2]>>
   0
   1
@@ -919,6 +918,12 @@ test that `or` operation skips duplicate
   4
   5
 
+test that repeated `-r` options never eat up stack (issue4565)
+(uses `-r (0)` instead of `-r 0` to bypass old-style parser)
+
+  $ hg log -T '{rev}\n' `python -c "for i in xrange(200): print '-r (0) ',"`
+  0
+
 check that conversion to only works
   $ try --optimize '::3 - ::1'
   (minus


More information about the Mercurial-devel mailing list