Mercurial > public > mercurial-scm > hg
diff mercurial/revlogutils/rewrite.py @ 47821:c30ca163b45e stable
issue6528: also filter delta on the fly when applying a changegroup
This ensure that corrupted clone does not spread corruption to "fixed" version.
This might come at a performance cost, we will had a config option to control
this behavior in the next changesets.
Differential Revision: https://phab.mercurial-scm.org/D11270
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Sat, 07 Aug 2021 14:12:28 +0200 |
parents | c02ce6def30c |
children | 2174f54aab18 531d26b1390a |
line wrap: on
line diff
--- a/mercurial/revlogutils/rewrite.py Sat Aug 07 14:13:53 2021 +0200 +++ b/mercurial/revlogutils/rewrite.py Sat Aug 07 14:12:28 2021 +0200 @@ -29,6 +29,7 @@ ENTRY_SIDEDATA_COMPRESSED_LENGTH, ENTRY_SIDEDATA_COMPRESSION_MODE, ENTRY_SIDEDATA_OFFSET, + REVIDX_ISCENSORED, REVLOGV0, REVLOGV1, ) @@ -36,6 +37,7 @@ from .. import ( error, + mdiff, pycompat, revlogutils, util, @@ -719,6 +721,88 @@ _reorder_filelog_parents(repo, fl, sorted(to_fix)) +def filter_delta_issue6528(revlog, deltas_iter): + """filter incomind deltas to repaire issue 6528 on the fly""" + metadata_cache = {} + + deltacomputer = deltas.deltacomputer(revlog) + + for rev, d in enumerate(deltas_iter, len(revlog)): + ( + node, + p1_node, + p2_node, + linknode, + deltabase, + delta, + flags, + sidedata, + ) = d + + if not revlog.index.has_node(deltabase): + raise error.LookupError( + deltabase, revlog.radix, _(b'unknown parent') + ) + base_rev = revlog.rev(deltabase) + if not revlog.index.has_node(p1_node): + raise error.LookupError(p1_node, revlog.radix, _(b'unknown parent')) + p1_rev = revlog.rev(p1_node) + if not revlog.index.has_node(p2_node): + raise error.LookupError(p2_node, revlog.radix, _(b'unknown parent')) + p2_rev = revlog.rev(p2_node) + + is_censored = lambda: bool(flags & REVIDX_ISCENSORED) + delta_base = lambda: revlog.rev(delta_base) + delta_base = lambda: base_rev + parent_revs = lambda: (p1_rev, p2_rev) + + def full_text(): + # note: being able to reuse the full text computation in the + # underlying addrevision would be useful however this is a bit too + # intrusive the for the "quick" issue6528 we are writing before the + # 5.8 release + textlen = mdiff.patchedsize(revlog.size(base_rev), delta) + + revinfo = revlogutils.revisioninfo( + node, + p1_node, + p2_node, + [None], + textlen, + (base_rev, delta), + flags, + ) + # cached by the global "writing" context + assert revlog._writinghandles is not None + if revlog._inline: + fh = revlog._writinghandles[0] + else: + fh = revlog._writinghandles[1] + return deltacomputer.buildtext(revinfo, fh) + + is_affected = _is_revision_affected_fast_inner( + is_censored, + delta_base, + lambda: delta, + full_text, + parent_revs, + rev, + metadata_cache, + ) + if is_affected: + d = ( + node, + p2_node, + p1_node, + linknode, + deltabase, + delta, + flags, + sidedata, + ) + yield d + + def repair_issue6528( ui, repo, dry_run=False, to_report=None, from_report=None, paranoid=False ):