Bug 4289 - -M changes order of records in hg log
Summary: -M changes order of records in hg log
Status: RESOLVED FIXED
Alias: None
Product: Mercurial
Classification: Unclassified
Component: Mercurial (show other bugs)
Version: 3.0.1
Hardware: All All
: urgent bug
Assignee: Bugzilla
URL:
Keywords:
Depends on:
Blocks: 4313
  Show dependency tree
 
Reported: 2014-06-24 04:12 UTC by Peter Hull
Modified: 2014-08-01 13:50 UTC (History)
3 users (show)

See Also:
Python Version: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Peter Hull 2014-06-24 04:12 UTC
If the -M flag and an explicit revision range is given to hg log, the order can be reversed compared to what is expected.
Reported to the mailing list http://www.selenic.com/pipermail/mercurial/2014-June/047249.html

Example: (taken from Matt Mackall's reply to the list)

Observed: 
$ hg log -M -q -r 10:9
9:b4d0c3786ad3
10:e76ed1e480ef

Expected:
$ hg log -M -q -r 10:9
10:e76ed1e480ef
9:b4d0c3786ad3

Further information:

# Correct on version 2.9 (i.e. this is a regression from previous)
$ hg29 log -q -M -r 10:9
10:e76ed1e480ef
9:b4d0c3786ad3

# Correct on current version without -M
$ hg log -q -r 10:9
10:e76ed1e480ef
9:b4d0c3786ad3

# Correct on current version with a revset
$ hg log -M -q -r "(10:9)"
10:e76ed1e480ef
9:b4d0c3786ad3

# Correct on current version with -M in revset
$ hg log -q -r 'not merge() and 10:9'
10:e76ed1e480ef
9:b4d0c3786ad3

Work around:
Use a revset, i.e.
$ hg log -M -q -r "(10:9)"
Comment 1 Prabhu Gnana Sundar 2014-07-03 02:12 UTC
I have submitted a patch to the dev mailing list.
Comment 2 Peter Hull 2014-07-03 05:49 UTC
Thanks for the swift response.

I downloaded a tip snapshot (at rev 61b333b982ea) and I applied your patch 'by hand' to cmdutil.py. 

I don't believe this fixes the problem completely.

# Without -M
$ hg log  -q -r 1:0
1:6b37d498935b
0:1a6eb00afbdc
$ hg log  -q -r 0:1
0:1a6eb00afbdc
1:6b37d498935b

# With -M
$ hg log -M -q -r 1:0
1:6b37d498935b
0:1a6eb00afbdc
$ hg log -M -q -r 0:1
1:6b37d498935b
0:1a6eb00afbdc

The last one is now wrong (or at least doesn't match the case without -M)

Also now even with a revset it is wrong:
$ hg log -M -q -r "(0:1)"
1:6b37d498935b
0:1a6eb00afbdc
Comment 3 Peter Hull 2014-07-03 07:11 UTC
I've been stepping through with a debugger, looking at the difference between -M and no -M, '-r 1:0' and '-r "(1:0)"' etc.

(all based on 3.0.1)

Specifically looking at cmdutil.getlogrevs() I see that scmutil.revrange() returns a mercurial.revset.orderedlazyset for '-r "(1:0)"' and a mercurial.revset.baseset for '-r 1:0'

Then _makelogrevset is used to get 'expr' which is None for no -M and and a filter (not merge()) for -M.

The 'not' filter works by using the __sub__ operator of the revision set, and for a mercurial.revset.baseset (I think) this can alter the order of elements (fair enough since sets aren't supposed to be ordered). For a mercurial.revset.orderedlazyset the order is maintained.

So I think maybe if scmutil.revrange() always returned an ordered set this might work, however there are quite a few lines in cmdutil.getlogrevs() devoted to re-ordering the sets and I don't quite understand them all.

Hope that helps?
Comment 4 Prabhu Gnana Sundar 2014-07-08 15:17 UTC
That really did help :)
I have sent another patch to the dev mailing list which I hope has fixed the issue. Added a test case too. Please let me know your thoughts on the same.

Instead of using an orderedlazyset I have removed just the merged-rev entry from the list of rev ranges.
Comment 5 HG Bot 2014-07-14 20:00 UTC
Fixed by http://selenic.com/repo/hg/rev/dd716807fd23
Matt Mackall <mpm@selenic.com>
revset: maintain ordering when subtracting from a baseset (issue4289)

(please test the fix)
Comment 6 Peter Hull 2014-07-15 01:42 UTC
This works for me. Thank you for your help.