Edgewall Software

Opened 4 months ago

Last modified 3 months ago

#13318 new defect

Changeset with new file links to a different revision

Reported by: anonymous Owned by:
Priority: normal Milestone: plugin - mercurial
Component: plugin/mercurial Version:
Severity: normal Keywords:
Cc: Branch:
Release Notes:
API Changes:
Internal Changes:


We noticed a changeset that links to the wrong revisions of files in the changeset. It all works correctly for other changesets. I don't know what's special about this changeset.

Trac 1.5.1.dev0 Jinja2 2.11.1 Mercurial 5.3+3-847e582f3cc9 tracmercurial

Any ideas?

Attachments (2)

log.png (225.1 KB ) - added by anonymous 4 months ago.
changeset.png (106.2 KB ) - added by anonymous 4 months ago.

Download all attachments as: .zip

Change History (11)

by anonymous, 4 months ago

Attachment: log.png added

by anonymous, 4 months ago

Attachment: changeset.png added

comment:1 by Ryan J Ollos, 3 months ago

You may want to run a resync.

comment:2 by Ryan J Ollos, 3 months ago

Could you try running the resync?

comment:3 by anonymous, 3 months ago

The linked documentation about resync states:

Cached repositories must be synchronized … The Mercurial plugin does not yet support caching

We use Mercurial, so we assumed resync is not needed and irrelevant, correct?

comment:4 by Ryan J Ollos, 3 months ago

Component: version control/changeset viewplugin/mercurial
Milestone: plugin - mercurial

Yeah, I was thinking TracMercurial used a cache, but looks like that's not the case.

comment:6 by anonymous, 3 months ago

Do you need more information to identify the bug? As shown in the attached screenshots above:

  • The changeset revision is 18515:d098be71aca0
  • The links instead wrongly point to 18451:58203a01030c

The repository itself looks correct:

% hg verify
checking changesets
checking manifests
crosschecking files in changesets and manifests
checking files
checked 18604 changesets with 96797 changes to 25910 files

% hg log --debug -r d098be71aca0 -l 1
changeset:   18515:d098be71aca0d80ef6608120e6291cfde9bc4b5e
phase:       draft
parent:      18514:1869782727927915f227e6f43e63e359634e0340
parent:      -1:0000000000000000000000000000000000000000
manifest:    18468:05145dcdb6a20ca24a004329e1568c8fc80695b6
date:        Thu Jul 09 16:59:34 2020 +0200
files:       x
files+:      y
extra:       branch=default

% hg log --debug -r 58203a01030c -l 1
changeset:   18451:58203a01030cd7aa2e54486936bbd55d488d080b
phase:       draft
parent:      18450:1fdc0197c727aadf0140973a98f1b9807ee3970d
parent:      -1:0000000000000000000000000000000000000000
manifest:    18404:4eb1b514c7c48090b978ddea1611820aeaecfefe
date:        Tue Jun 30 18:32:50 2020 +0200
files:       a b c d x
files+:      e f g y
extra:       branch=default

Also using the Mercurial API looks correct:

>>> from mercurial import hg, ui
>>> repo = hg.repository(ui=ui.ui(), path=".")
>>> ctx = repo[18515]
>>> ctx
<changectx d098be71aca0>
>>> ctx.parents()
[<changectx 186978272792>]
>>> ctx.manifest()
<mercurial.manifest.manifestdict object at 0x0000000004786108>
>>> ctx.files()
['x', 'y']
>>> 'x' in ctx.manifest()
>>> 'y' in ctx.manifest()
>>> 'x' in ctx.parents()[0].manifest()
>>> 'y' in ctx.parents()[0].manifest()

It is difficult for me to see what went wrong. Is this call to the this Mercurial plugin routine the one that returns the wrong information?

Is changes.append(...None)) correct there? Does that lead to orev == None and then maybe some heuristic search in MercurialNode(repos, 'x', changectx(None)) goes wrong somehow?

comment:7 by Ryan J Ollos, 3 months ago

Thanks for the investigation, it is valuable. This is not a part of the code that I'm very familiar with. Any change the affected repository is publicly available?

comment:8 by anonymous, 3 months ago

Unfortunately the repository is not public.

After some debugging I found:

  • The repos.get_node calls have the correct parameters (paths 'x' / 'y' with revs d098be71aca0... / 18514).
  • But the returned nodes are wrong (@18451).
    • So the bug does appear specific to Mercurial.
  • The call to self.filectx.linkrev() is the source of the problem:
>>> from mercurial import hg, ui
>>> repo = hg.repository(ui=ui.ui(), path=".")
>>> ctx = repo[18515]
>>> fctx = ctx.filectx('x')
>>> fctx
<filectx x@d098be71aca0>
>>> fctx.linkrev()
>>> fctx.rev()

I'm not sure what "linkrev" is exactly, why it is used here, why it is wrong (crossed?) in this specific case, and if using "rev" instead be better or worse in general.

(I do know that changeset 18451 was amended / evolved / rebased to create changeset 18515.)

comment:9 by anonymous, 3 months ago

The following steps create a repository that reproduces the scenario:

% hg init repo1 && cd repo1
% echo a>a && hg add a && hg commit -m a
% echo b>b && hg add b && hg commit -m b
% hg update 1
% hg clone . ../repo2
% echo c>c && hg add c && hg commit -m c
% hg rebase -r 1
% hg push ../repo2 -f
% cd ../repo2
% hg log -G
o  changeset:   3
|  summary:     b
o  changeset:   2
|  summary:     c
| @  changeset:   1
|/   summary:     b
o  changeset:   0
   summary:     a
% python
>>> from mercurial import hg, ui
>>> repo = hg.repository(ui=ui.ui(), path=".")
>>> for rev in repo:
...    changectx = repo[rev]
...    for filename in changectx.files():
...        filectx = changectx.filectx(filename)
...        print rev, filename, filectx.linkrev(), filectx.rev()
0 a 0 0
1 b 1 1
2 c 2 2
3 b 1 3

Note the 1 in the last line. Browse to changeset 3 of repo2 in Trac and observe the file b links to revision 1 instead of revision 3.

comment:10 by Ryan J Ollos, 3 months ago

Thank you for investigating and making a reproducible test case. I will try to look at it soon!

Modify Ticket

Change Properties
Set your email in Preferences
as new The ticket will remain with no owner.
The ticket will be disowned.
as The resolution will be set. Next status will be 'closed'.
The owner will be changed from (none) to anonymous. Next status will be 'assigned'.

Add Comment

E-mail address and name can be saved in the Preferences .
Note: See TracTickets for help on using tickets.