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

login
register
mail settings
Submitter Yuya Nishihara
Date May 12, 2015, 10:59 p.m.
Message ID <144ed132beea8d9e77a1.1431471580@mimosa>
Download mbox | patch
Permalink /patch/9035/
State Accepted
Headers show

Comments

Yuya Nishihara - May 12, 2015, 10:59 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@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.

Patch

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