# HG changeset patch # User Matt Mackall # Date 2011-12-01 04:43:24 # Node ID a585d78e7b2f6c3336d757a69c2379f4c26c26b8 # Parent f9c6a575baa4e72e58387e38387ad7611a943138 revset: balance %l or-expressions (issue3129) diff --git a/mercurial/revset.py b/mercurial/revset.py --- a/mercurial/revset.py +++ b/mercurial/revset.py @@ -1073,7 +1073,7 @@ def formatspec(expr, *args): >>> 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 @@ def formatspec(expr, *args): >>> 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 @@ def formatspec(expr, *args): 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 @@ def formatspec(expr, *args): # 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)