revset: balance %l or-expressions (
issue3129)
--- 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)