Patchwork [1,of,2,censor,RFC,v2] revlog: special case expanding full-replacement deltas received by exchange

login
register
mail settings
Submitter adgar@google.com
Date Feb. 10, 2015, 11:16 p.m.
Message ID <3a1c2083548586a5ad0a.1423610162@adgar.nyc.corp.google.com>
Download mbox | patch
Permalink /patch/7779/
State Accepted
Headers show

Comments

adgar@google.com - Feb. 10, 2015, 11:16 p.m.
# HG changeset patch
# User Mike Edgar <adgar@google.com>
# Date 1423186696 0
#      Fri Feb 06 01:38:16 2015 +0000
# Node ID 3a1c2083548586a5ad0afe0cfaca2d070984ce61
# Parent  521c330b1ad7af3e9da78750defc534ab981c1ff
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

Patch

diff -r 521c330b1ad7 -r 3a1c20835485 mercurial/revlog.py
--- a/mercurial/revlog.py	Fri Feb 06 00:55:29 2015 +0000
+++ 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: