revset: prevent crash caused by empty group expression while optimizing "or"
An empty group expression "()" generates None in AST, so it should be tested
before destructuring a tuple.
"A | ()" is still evaluated to an error because I'm not sure whether "()"
represents an empty set or an empty expression (= a unit value). They are
identical in "or" operation, but they should be evaluated differently in
"and" operation.
expression empty set unit value
---------- --------- ----------
() {} A
A & () {} A
A | () A A
--- a/mercurial/revset.py Sun Aug 09 16:06:36 2015 +0900
+++ b/mercurial/revset.py Sun Aug 09 16:09:41 2015 +0900
@@ -2280,7 +2280,7 @@
del ss[:]
for y in x[1:]:
w, t = optimize(y, False)
- if t[0] == 'string' or t[0] == 'symbol':
+ if t is not None and (t[0] == 'string' or t[0] == 'symbol'):
ss.append((w, t))
continue
flushss()
--- a/tests/test-revset.t Sun Aug 09 16:06:36 2015 +0900
+++ b/tests/test-revset.t Sun Aug 09 16:09:41 2015 +0900
@@ -1144,6 +1144,20 @@
4
5
+no crash by empty group "()" while optimizing `or` operations
+
+ $ try --optimize '0|()'
+ (or
+ ('symbol', '0')
+ (group
+ None))
+ * optimized:
+ (or
+ ('symbol', '0')
+ None)
+ hg: parse error: missing argument
+ [255]
+
test that chained `or` operations never eat up stack (issue4624)
(uses `0:1` instead of `0` to avoid future optimization of trivial revisions)