Commit f6517e8e authored by Pulkit Goyal's avatar Pulkit Goyal
Browse files

tags: validate nodes in _getfnodes() and update cache in case of unknown nodes

`hgtagsfnodescache` can contain unknown nodes due to cache corruption and this
lead to a traceback on operations like `hg tags` as we don't validate nodes.

This patch validates that all filenodes returned after `hgtagsfnodescache` are
known to the repository. If there exists any unknown filenode, we force
recompute it and update the cache.

The test change demonstrates the fix.

Differential Revision: https://phab.mercurial-scm.org/D10083
parent c95092afc1eb
Pipeline #18860 passed with stages
in 30 minutes and 45 seconds
......@@ -494,11 +494,25 @@ def _getfnodes(ui, repo, nodes):
starttime = util.timer()
fnodescache = hgtagsfnodescache(repo.unfiltered())
cachefnode = {}
validated_fnodes = set()
unknown_entries = set()
for node in nodes:
fnode = fnodescache.getfnode(node)
flog = repo.file(b'.hgtags')
if fnode != nullid:
if fnode not in validated_fnodes:
if flog.hasnode(fnode):
validated_fnodes.add(fnode)
else:
unknown_entries.add(node)
cachefnode[node] = fnode
if unknown_entries:
fixed_nodemap = fnodescache.refresh_invalid_nodes(unknown_entries)
for node, fnode in pycompat.iteritems(fixed_nodemap):
if fnode != nullid:
cachefnode[node] = fnode
fnodescache.write()
duration = util.timer() - starttime
......@@ -826,6 +840,21 @@ class hgtagsfnodescache(object):
self._writeentry(ctx.rev() * _fnodesrecsize, node[0:4], fnode)
def refresh_invalid_nodes(self, nodes):
"""recomputes file nodes for a given set of nodes which has unknown
filenodes for them in the cache
Also updates the in-memory cache with the correct filenode.
Caller needs to take care about calling `.write()` so that updates are
persisted.
Returns a map {node: recomputed fnode}
"""
fixed_nodemap = {}
for node in nodes:
fnode = self._computefnode(node)
fixed_nodemap[node] = fnode
self.setfnode(node, fnode)
return fixed_nodemap
def _writeentry(self, offset, prefix, fnode):
# Slices on array instances only accept other array.
entry = bytearray(prefix + fnode)
......
......@@ -452,8 +452,8 @@ debug command hides the corruption, both with and without tags2-visible.
5 8dbfe60eff306a54259cfe007db9e330e7ecf866 0c04f2a8deadde17fab7422878ee5a2dadbc943d (unknown node)
$ hg tags
abort: data/.hgtags.i@0c04f2a8deadde17fab7422878ee5a2dadbc943d: no match found
[50]
tip 5:8dbfe60eff30
bar 1:78391a272241
BUG: Unless this file is restored, the `hg tags` in the next unix-permissions
conditional will fail: "abort: data/.hgtags.i@0c04f2a8dead: no match found"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment