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

Yuya Nishihara yuya at tcha.org
Tue May 12 17:59:40 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 144ed132beea8d9e77a16c44887d280079136546
# Parent  d15815ca13aec24b6c62d2ec2eebebea52adc411
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
@@ -3016,6 +3016,14 @@ class addset(abstractsmartset):
     >>> rs = addset([], ascending=True)
     >>> [x for x in rs]
     []
+
+    add set to existing addset:
+    >>> rs = addset([xs, ys]) + zs
+    >>> [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
@@ -3165,6 +3173,11 @@ class addset(abstractsmartset):
         self.reverse()
         return val
 
+    def __add__(self, other):
+        if self._ascending is not None:
+            return super(addset, self).__add__(other)
+        return addset(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
@@ -143,9 +143,8 @@ trivial
     ('symbol', '2'))
   * set:
   <addset
-    <addset
-      <baseset [0]>,
-      <baseset [1]>>,
+    <baseset [0]>,
+    <baseset [1]>,
     <baseset [2]>>
   0
   1
@@ -878,6 +877,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