Opened 6 years ago
Last modified 2 years ago
#13092 new defect
Unified diff of changeset sometimes include wrong changes?
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: |
Description (last modified by )
For example the changesets before the merge log:mercurial-plugin@17:
- changeset:16/mercurial-plugin: The Unified Diff there looks correct.
- changeset:15/mercurial-plugin: The Unified Diff there looks correct.
- changeset:14/mercurial-plugin: The Unified Diff includes a lot more changes than it should!
Another example is before the merge log:mercurial-plugin@46:
- changeset:45/mercurial-plugin: The Unified Diff again includes a lot more changes than it should.
Attachments (1)
Change History (9)
comment:1 by , 6 years ago
Component: | version control → plugin/mercurial |
---|---|
Description: | modified (diff) |
Milestone: | → plugin - mercurial |
comment:2 by , 6 years ago
comment:3 by , 6 years ago
Right. Here's a unittest showing the issue:
-
tracext/hg/tests/backend.py
diff -r c9f2efa16762 tracext/hg/tests/backend.py
a b 473 473 self.assertEqual('delete', delete[3]) 474 474 self.assertEqual('lunch/lasagna/pasta.txt', delete[0].path) 475 475 476 def test_get_previous(self): 477 # regression test for #13092 478 self._hg_init(data=False) 479 self._add_repository() 480 repos = self._repomgr.get_repository('hgrepos') 481 self._create_commit('lunch', 'lunch/menu.txt') 482 self._create_commit('pasta', 'lunch/lasagna/pasta.txt') 483 self._hg_update('0') 484 self._create_commit('fish', 'lunch/fish/chips.txt') 485 self._create_commit('coffee', 'lunch/fish/drink.txt', content='coffee') 486 self._hg_update('1') 487 self._create_commit('coke', 'lunch/lasagna/drink.txt', content='coke') 488 repos.repo.invalidate() 489 490 node = repos.get_node('/', 4) 491 prev_rev = node.get_previous()[1] 492 self.assertEqual(repos.display_rev(1), repos.display_rev(prev_rev)) 493 476 494 477 495 def test_suite(): 478 496 suite = unittest.TestSuite()
I assume get_previous() using get_history()
is ok.
So probably get_history() isn't right somehow. I'm guessing %s:0
is a revset x:y
but what is needed is a x::y
, but for some reason it that x>y doesn't work, so reverse(y::x)
must be used instead:
-
tracext/hg/backend.py
diff -r 21f2fa60ca5f tracext/hg/backend.py
a b 1167 1167 pats = [] 1168 1168 if self.str_path: 1169 1169 pats.append('path:' + self.str_path) 1170 opts = {'rev': [' %s:0' % self.changectx.hex()]}1170 opts = {'rev': ['reverse(0::%s)' % self.changectx.hex()]} 1171 1171 if self.isfile and self.repos.version_info < (2, 1, 1): 1172 1172 opts['follow'] = True 1173 1173 if arity(cmdutil.walkchangerevs) == 4:
This makes the unittest above pass at least.
by , 6 years ago
Attachment: | t13092.diff added |
---|
comment:4 by , 6 years ago
I consider the get_history() should walk parents of the commit and your changes are right, but log view for mercurial repository would show only ancestors of the given revision after the changes. Currently, the log view shows all branches.
follow-up: 6 comment:5 by , 6 years ago
Good point! I would not like changing the log to show only ancestors.
(Do Git repositories only show ancestors in the log? Is that intentional?)
comment:6 by , 6 years ago
Replying to Peter Suter:
Good point! I would not like changing the log to show only ancestors.
(Do Git repositories only show ancestors in the log? Is that intentional?)
Yes. That behavior on git repository is intentional. On git repository, determining previous revision is cost too much since no integer revisions.
I think it would be good that the log view shows ancestors of the given revision or branch by default and add an option to show all branches without the given revision.
follow-up: 8 comment:7 by , 6 years ago
Have you considered if the bug is in using repos.get_node(new_path, new).get_previous() for the old_rev
of a changeset, instead of e.g. repos.previous_rev(new, new_path)
? That seems to give the "correct" changeset.
(For Git: Maybe Git 2.18+ commit-graph feature would be useful? It sounds somewhat similar.)
comment:8 by , 6 years ago
Replying to Peter Suter:
Have you considered if the bug is in using repos.get_node(new_path, new).get_previous() for the
old_rev
of a changeset, instead of e.g.repos.previous_rev(new, new_path)
? That seems to give the "correct" changeset.
The Node.get_previous()
for Subversion is absolutely clear and correct. However, it is ambiguous for non-linear repository (e.g. Git, Mercurial). I consider it should always return an ancestor of the node.
(For Git: Maybe Git 2.18+ commit-graph feature would be useful? It sounds somewhat similar.)
Not useful. We cannot read commit-graph cache because it is binary. We still have to construct the graph and sorting of revisions using git rev-list
.
$ file .git/objects/info/commit-graph .git/objects/info/commit-graph: data $ git commit-graph read header: 43475048 1 1 4 0 num_commits: 19368 chunks: oid_fanout oid_lookup commit_metadata large_edges
It seems that
MercurialNode.get_previous()
with @14 wrongly returns 13. It should return 11. Unified diff for 14/mercurial-plugin should be changes between 11 and 14.