changeset 24122:da14b8eba806

revlog: special case expanding full-replacement deltas received by exchange When a delta received through exchange is added to a revlog, it will very often be expanded to a full text by applying the delta to its base. If that delta is of a particular form, we can avoid decoding the base revision. This avoids an exception if the base revision is censored. For background and broader design of the censorship feature, see: http://mercurial.selenic.com/wiki/CensorPlan
author Mike Edgar <adgar@google.com>
date Fri, 06 Feb 2015 01:38:16 +0000
parents 9d0b6ef92eb2
children eb2d41c6ec37
files mercurial/revlog.py
diffstat 1 files changed, 12 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/revlog.py	Tue Feb 10 16:17:15 2015 -0800
+++ b/mercurial/revlog.py	Fri Feb 06 01:38:16 2015 +0000
@@ -1233,8 +1233,18 @@
             if dfh:
                 dfh.flush()
             ifh.flush()
-            basetext = self.revision(self.node(cachedelta[0]))
-            btext[0] = mdiff.patch(basetext, cachedelta[1])
+            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(self.rawsize(baserev),
+                                                       len(delta) - hlen):
+                btext[0] = delta[hlen:]
+            else:
+                basetext = self.revision(self.node(baserev))
+                btext[0] = mdiff.patch(basetext, delta)
             try:
                 self.checkhash(btext[0], p1, p2, node)
                 if flags & REVIDX_ISCENSORED: