Mercurial > hg-stable
changeset 39358:fd0150a3c2fe
revlogdeltas: extra fulltext building in its own function
The process of building a full text from a delta is complex enough to deserve
isolation. The previous function mixed cache management and computation, we
now have clearer boundaries and simpler functions/methods.
author | Boris Feld <boris.feld@octobus.net> |
---|---|
date | Wed, 29 Aug 2018 09:41:04 -0700 |
parents | 655b5b465953 |
children | 6f4b8f607a31 |
files | mercurial/revlogutils/deltas.py |
diffstat | 1 files changed, 32 insertions(+), 27 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/revlogutils/deltas.py Thu Aug 16 02:53:42 2018 +0200 +++ b/mercurial/revlogutils/deltas.py Wed Aug 29 09:41:04 2018 -0700 @@ -438,6 +438,34 @@ end = revlog.end(revs[-1]) return end - revlog.start(revs[0]) +def _textfromdelta(fh, revlog, baserev, delta, p1, p2, flags, expectednode): + """build full text from a (base, delta) pair and other metadata""" + # special case deltas which replace entire base; no need to decode + # base revision. this neatly avoids censored bases, which throw when + # they're decoded. + hlen = struct.calcsize(">lll") + if delta[:hlen] == mdiff.replacediffheader(revlog.rawsize(baserev), + len(delta) - hlen): + fulltext = delta[hlen:] + else: + # deltabase is rawtext before changed by flag processors, which is + # equivalent to non-raw text + basetext = revlog.revision(baserev, _df=fh, raw=False) + fulltext = mdiff.patch(basetext, delta) + + try: + res = revlog._processflags(fulltext, flags, 'read', raw=True) + fulltext, validatehash = res + if validatehash: + revlog.checkhash(fulltext, expectednode, p1=p1, p2=p2) + if flags & REVIDX_ISCENSORED: + raise RevlogError(_('node %s is not censored') % expectednode) + except CensoredNodeError: + # must pass the censored index flag to add censored revisions + if not flags & REVIDX_ISCENSORED: + raise + return fulltext + @attr.s(slots=True, frozen=True) class _deltainfo(object): distance = attr.ib() @@ -605,36 +633,13 @@ revlog = self.revlog cachedelta = revinfo.cachedelta - flags = revinfo.flags - node = revinfo.node - baserev = cachedelta[0] delta = cachedelta[1] - # special case deltas which replace entire base; no need to decode - # base revision. this neatly avoids censored bases, which throw when - # they're decoded. - hlen = struct.calcsize(">lll") - if delta[:hlen] == mdiff.replacediffheader(revlog.rawsize(baserev), - len(delta) - hlen): - btext[0] = delta[hlen:] - else: - # deltabase is rawtext before changed by flag processors, which is - # equivalent to non-raw text - basetext = revlog.revision(baserev, _df=fh, raw=False) - btext[0] = mdiff.patch(basetext, delta) - try: - res = revlog._processflags(btext[0], flags, 'read', raw=True) - btext[0], validatehash = res - if validatehash: - revlog.checkhash(btext[0], node, p1=revinfo.p1, p2=revinfo.p2) - if flags & REVIDX_ISCENSORED: - raise RevlogError(_('node %s is not censored') % node) - except CensoredNodeError: - # must pass the censored index flag to add censored revisions - if not flags & REVIDX_ISCENSORED: - raise - return btext[0] + fulltext = btext[0] = _textfromdelta(fh, revlog, baserev, delta, + revinfo.p1, revinfo.p2, + revinfo.flags, revinfo.node) + return fulltext def _builddeltadiff(self, base, revinfo, fh): revlog = self.revlog