From patchwork Sat Aug 18 09:27:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [06,of,12] revlogdeltas: extra fulltext building in its own function From: Boris Feld X-Patchwork-Id: 33871 Message-Id: To: mercurial-devel@mercurial-scm.org Cc: gregory.szorc@gmail.com Date: Sat, 18 Aug 2018 11:27:21 +0200 # HG changeset patch # User Boris Feld # Date 1534385554 -7200 # Thu Aug 16 04:12:34 2018 +0200 # Node ID ff271ee5114d870492da10e625b43b8bf2ee23e4 # Parent 9c7224a86df8f316dbfb006ba8e81fc3ce831303 # EXP-Topic sparse-snapshot # Available At https://bitbucket.org/octobus/mercurial-devel/ # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r ff271ee5114d 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. diff --git a/mercurial/revlogutils/deltas.py b/mercurial/revlogutils/deltas.py --- a/mercurial/revlogutils/deltas.py +++ b/mercurial/revlogutils/deltas.py @@ -438,6 +438,34 @@ def segmentspan(revlog, revs, deltainfo= 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,35 +633,13 @@ class deltacomputer(object): 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 + fulltext = btext[0] = _textfromdelta(fh, revlog, baserev, delta, + revinfo.p1, revinfo.p2, + revinfo.flags, revinfo.node) + return fulltext return btext[0] def _builddeltadiff(self, base, revinfo, fh):