Bug 4292 - hg log and {files} {file_adds} {file_mods} {file_dels} in template show wrong files on merged revision
Summary: hg log and {files} {file_adds} {file_mods} {file_dels} in template show wrong...
Status: RESOLVED FIXED
Alias: None
Product: Mercurial
Classification: Unclassified
Component: Mercurial (show other bugs)
Version: 3.0.1
Hardware: PC Windows
: normal bug
Assignee: Bugzilla
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-06-27 06:09 UTC by vlad_n
Modified: 2019-06-11 00:00 UTC (History)
4 users (show)

See Also:
Python Version: ---


Attachments
repository (6.08 KB, application/x-zip-compressed)
2014-06-27 06:10 UTC, vlad_n
Details
TortoiseHg Workbench screenshot (53.26 KB, image/png)
2014-07-31 01:42 UTC, vlad_n
Details

Note You need to log in before you can comment on or make changes to this bug.
Description vlad_n 2014-06-27 06:09 UTC
Steps to see the bug:

1. hg init
2. Create 0.txt file that contains text '0.txt'. And create r.txt file that contains text 'r.txt'.
3. hg add
4. hg commit -m "add 0.txt and r.txt"

5. Create 1.txt file that contains text '1.txt'.
6. hg add 1.txt
7. Add to file 0.txt new line '1' after text '0.txt'.
8. hg remove r.txt
9. hg commit -m "add 1.txt change 0.txt remove r.txt"

10. hg update -c -r0
11. Create 2.txt file that contains text '2.txt'.
12. hg add 1.txt
13. hg commit -m "add 2.txt"

14. hg merge
15. hg commit -m "merge with rev 1"

Now try to see what files changed in revision 3:
hg log -r3 --template="  {files}\nM {file_mods}\nA {file_adds}\nR {file_dels}"
  r.txt
M 0.txt
A 1.txt
R r.txt

{file_mods}, {file_adds} and {file_dels} lists contains files changes from 1st parent don't by this changeset: 

Now try to see what files changed in revision 3 from revision 2 (1st parent):
hg status --rev 2 --rev 3
M 0.txt
A 1.txt
R r.txt

Now try to see what files changed in revision 3 from revision 1 (2nd parent):
hg status --rev 1 --rev 3
A 2.txt

Why {file_mods} list contains file 0.txt and {file_adds} list contains file 0.txt. But {files} list don't contains this files?

Repository in attachment.
Comment 1 vlad_n 2014-06-27 06:10 UTC
Created attachment 1776 [details]
repository
Comment 2 Matt Mackall 2014-07-28 15:38 UTC
Classic "how do I compare three items" problem. This can't be meaningfully fixed.
Comment 3 vlad_n 2014-07-29 02:24 UTC
Yes, I agree that it is impossible to compare the three elements. But why {files} does not contain all the files that are in {file_mods}, {file_adds}, {file_dels}?
Comment 4 Matt Mackall 2014-07-29 13:54 UTC
The first is an intersection of two sets and appeared first as a feature (roughly on day 2). The others came much later and can't be unions or intersections of sets without creating more of the same sort of inconsistencies you're complaining about. So they were implemented differently.
Comment 5 vlad_n 2014-07-30 01:31 UTC
OK. How from set {files} I can determine that the file has been modified, added, or deleted using command log?

For example, command:
hg log -r3 --template="{files}\n"

only show changed files on revision 3. What attribute I need add to template to get status of this files?
Comment 6 Matt Mackall 2014-07-30 15:26 UTC
Status.. relative to what?

You might want to instead use the status command:

hg status -r "p1(3)" -r 3

This discussion would be better on the mailing list or IRC where there'll be an audience of more than 3.
Comment 7 vlad_n 2014-07-31 01:42 UTC
Created attachment 1782 [details]
TortoiseHg Workbench screenshot
Comment 8 vlad_n 2014-07-31 01:46 UTC
TortoiseHg Workbench has menu item "Changed by This commit". When I was select this menu - file r.txt displayed with status deleted. See TortoiseHg Workbench screenshot in attachments. How TortoiseHg is determined this status?
Comment 9 Martin von Zweigbergk 2019-04-18 17:12 UTC
I think a reasonable definition for {file_adds} would be "file exists in this commit, but it didn't exist in any of the parents". {file_dels} would be "file does not exist in this commit, but it existed in at least one parent". {file_mods} would be the remainder (i.e. {files}-{file_adds}-{file_dels}). Another way of defining {file_mods} is "file is not equal to file in either of the parents". I believe that's an equivalent definition.
Comment 10 Martin von Zweigbergk 2019-05-11 03:14 UTC
I'll send a patch to fix this according to the definitions I provided in comment #9.
Comment 11 HG Bot 2019-06-03 17:45 UTC
Fixed by https://mercurial-scm.org/repo/hg/rev/0c72eddb4be5
Martin von Zweigbergk <martinvonz@google.com>
templatekw: make {file_*} compare to both merge parents (issue4292)

This redefines the {file_adds}, {file_dels}, {file_mods} template
keywords by getting the lists from the recently introduced context
methods instead of getting them from status compared to p1. As
mentioned before, these are better defined on merge commits. The total
number of files from the three lists now always add up to the number
of files in {files}.

I timed this command:

  hg log -r 4.0::5.0 -T '{rev}\n {file_mods}\n {file_adds}\n {file_dels}\n'

It went from 7.6s to 5.6s with this patch. So it's actually faster
than before.

Note that the "files:" field in the bazaar test log output was using
"{file_mods}" (not "{files}" as one might think based on the label).

Differential Revision: https://phab.mercurial-scm.org/D6369

(please test the fix)
Comment 12 Bugzilla 2019-06-11 00:00 UTC
Bug was set to TESTING for 7 days, resolving