diff --git a/mercurial/revsetlang.py b/mercurial/revsetlang.py --- a/mercurial/revsetlang.py +++ b/mercurial/revsetlang.py @@ -434,9 +434,9 @@ def _optimize(x, small): flushss() if len(ts) == 1: return ws[0], ts[0] # 'or' operation is fully optimized out - # we can't reorder trees by weight because it would change the order. - # ("sort(a + b)" == "sort(b + a)", but "a + b" != "b + a") - # ts = tuple(t for w, t in sorted(zip(ws, ts), key=lambda wt: wt[0])) + if order != defineorder: + # reorder by weight only when f(a + b) == f(b + a) + ts = [wt[1] for wt in sorted(zip(ws, ts), key=lambda wt: wt[0])] return max(ws), (op, ('list',) + tuple(ts), order) elif op == 'not': # Optimize not public() to _notpublic() because we have a fast version diff --git a/tests/test-revset.t b/tests/test-revset.t --- a/tests/test-revset.t +++ b/tests/test-revset.t @@ -1420,19 +1420,19 @@ ordering defined by it. define) (or (list + ('symbol', '2') (range ('symbol', '0') ('symbol', '1') - follow) - ('symbol', '2')) + follow)) follow) define) * set: , , - >> + , + >> 2 1 0 @@ -1917,6 +1917,69 @@ ordering defined by it. 1 0 + 'A + B' can be rewritten to 'B + A' by weight only when the order doesn't + matter (e.g. 'X & (A + B)' can be 'X & (B + A)', but '(A + B) & X' can't): + + $ try -p optimized '0:2 & (reverse(contains("a")) + 2)' + * optimized: + (and + (range + ('symbol', '0') + ('symbol', '2') + define) + (or + (list + ('symbol', '2') + (func + ('symbol', 'reverse') + (func + ('symbol', 'contains') + ('string', 'a') + define) + follow)) + follow) + define) + * set: + , + , + , + >>> + 0 + 1 + 2 + + $ try -p optimized '(reverse(contains("a")) + 2) & 0:2' + * optimized: + (and + (range + ('symbol', '0') + ('symbol', '2') + follow) + (or + (list + (func + ('symbol', 'reverse') + (func + ('symbol', 'contains') + ('string', 'a') + define) + define) + ('symbol', '2')) + define) + define) + * set: + , + >, + > + 1 + 0 + 2 + test sort revset --------------------------------------------