[PATCH STABLE] log: fix order of revisions filtered by multiple OR options (issue5100)

Yuya Nishihara yuya at tcha.org
Mon Feb 15 14:34:19 UTC 2016


# HG changeset patch
# User Yuya Nishihara <yuya at tcha.org>
# Date 1455543967 -32400
#      Mon Feb 15 22:46:07 2016 +0900
# Branch stable
# Node ID ae36fdcb20ae3b7b0d8b2e7f868a1c3eb104e34e
# Parent  8da94662afe51a836eda500652097772c34002e8
log: fix order of revisions filtered by multiple OR options (issue5100)

This is the simplest workaround for the issue of the ordering of revset, which
is that the expression "x or y" takes over the ordering specified by the input
set (or the left-hand-side expression.) For example, the following expression

  A & (x | y)

will be evaluated as if

  (A & x) | (A & y)

It is wrong because revset has ordering. Ideally, we should fix the revset
computation, but that would require a long patch series. So, for now, this
patch just works around the common log cases.

Since this change might have some impact on performance, it is enabled only
if the expression seems to have ' or ' expression.

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -2139,9 +2139,14 @@ def getlogrevs(repo, pats, opts):
         # Revset matches can reorder revisions. "A or B" typically returns
         # returns the revision matching A then the revision matching B. Sort
         # again to fix that.
+        oldrevs = revs
         revs = matcher(repo, revs)
         if not opts.get('rev'):
             revs.sort(reverse=True)
+        elif ' or ' in expr:
+            # XXX "A or B" is known to change the order; fix it by filtering
+            # matched set again (issue5100)
+            revs = oldrevs & revs
     if limit is not None:
         limitedrevs = []
         for idx, r in enumerate(revs):
diff --git a/tests/test-log.t b/tests/test-log.t
--- a/tests/test-log.t
+++ b/tests/test-log.t
@@ -918,6 +918,44 @@ log -r tip --stat
    1 files changed, 1 insertions(+), 0 deletions(-)
   
 
+Test that log should respect the order of -rREV even if multiple OR conditions
+are specified (issue5100):
+
+ summary of revisions:
+
+  $ hg log -r0:6 -T '{rev} {pad(files, 6)} {desc|firstline}\n'
+  0 base   base
+  1 base   r1
+  2 base   r2
+  3 b1     b1
+  4 b2     b2
+  5        m12
+  6 b1     b1.1
+
+ log FILE in ascending order:
+
+  $ hg log -r0:6 -T '{rev} {files}\n' b1 b2
+  3 b1
+  4 b2
+  6 b1
+  $ hg log -r0:6 -T '{rev} {files}\n' b2 b1
+  3 b1
+  4 b2
+  6 b1
+
+ log -k TEXT in descending order:
+
+  $ hg log -r6:0 -T '{rev} {desc|firstline}\n' -k r1 -k r2 -k b1
+  6 b1.1
+  3 b1
+  2 r2
+  1 r1
+  $ hg log -r6:0 -T '{rev} {desc|firstline}\n' -k r2 -k b1 -k r1
+  6 b1.1
+  3 b1
+  2 r2
+  1 r1
+
   $ cd ..
 
 


More information about the Mercurial-devel mailing list