# HG changeset patch # User Mike Edgar # Date 2015-02-06 01:38:16 # Node ID da14b8eba806b0391ff2597600cc39e1a4c4c3c5 # Parent 9d0b6ef92eb212bf4945822139dac996c4e1322c 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 diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -1233,8 +1233,18 @@ class revlog(object): 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: