revset: balance %l or-expressions (issue3129) stable
authorMatt Mackall <mpm@selenic.com>
Wed, 30 Nov 2011 22:43:24 -0600
branchstable
changeset 15595 a585d78e7b2f
parent 15593 f9c6a575baa4
child 15596 2555f441a32f
child 15597 bc0778f5619a
revset: balance %l or-expressions (issue3129)
mercurial/revset.py
--- a/mercurial/revset.py	Wed Nov 30 17:16:43 2011 -0600
+++ b/mercurial/revset.py	Wed Nov 30 22:43:24 2011 -0600
@@ -1073,7 +1073,7 @@
     >>> formatspec('%d:: and not %d::', 10, 20)
     '10:: and not 20::'
     >>> formatspec('%ld or %ld', [], [1])
-    '(0-0) or (1)'
+    '(0-0) or 1'
     >>> formatspec('keyword(%s)', 'foo\\xe9')
     "keyword('foo\\\\xe9')"
     >>> b = lambda: 'default'
@@ -1081,7 +1081,7 @@
     >>> formatspec('branch(%b)', b)
     "branch('default')"
     >>> formatspec('root(%ls)', ['a', 'b', 'c', 'd'])
-    "root(('a' or 'b' or 'c' or 'd'))"
+    "root((('a' or 'b') or ('c' or 'd')))"
     '''
 
     def quote(s):
@@ -1100,6 +1100,16 @@
         elif c == 'b':
             return quote(arg.branch())
 
+    def listexp(s, t):
+        "balance a list s of type t to limit parse tree depth"
+        l = len(s)
+        if l == 0:
+            return '(0-0)' # a minimal way to represent an empty set
+        if l == 1:
+            return argtype(t, s[0])
+        m = l / 2
+        return '(%s or %s)' % (listexp(s[:m], t), listexp(s[m:], t))
+
     ret = ''
     pos = 0
     arg = 0
@@ -1117,11 +1127,7 @@
                 # a list of some type
                 pos += 1
                 d = expr[pos]
-                if args[arg]:
-                    lv = ' or '.join(argtype(d, e) for e in args[arg])
-                else:
-                    lv = '0-0' # a minimal way to represent an empty set
-                ret += '(%s)' % lv
+                ret += listexp(args[arg], d)
                 arg += 1
             else:
                 raise util.Abort('unexpected revspec format character %s' % d)