revlogdeltas: extra fulltext building in its own function
authorBoris Feld <boris.feld@octobus.net>
Wed, 29 Aug 2018 09:41:04 -0700
changeset 39331 fd0150a3c2fe
parent 39330 655b5b465953
child 39332 6f4b8f607a31
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.
mercurial/revlogutils/deltas.py
--- 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