# HG changeset patch # User Mike Edgar # Date 2015-01-22 03:09:32 # Node ID 903c7e8c97ad97dd579de976d4e62dd7af4965b4 # Parent 8b4b9ee6001ab1818463ecc242bf3989524aea42 changegroup: emit full-replacement deltas if either revision is censored To ensure that exchanged deltas in the presence of censored revisions can always be applied to the recipient repository, the deltas must replace the entire base text. To make this restriction reasonably enforceable, the delta must do so with a single patch operation. For background and broader design of the censorship feature, see: http://mercurial.selenic.com/wiki/CensorPlan diff --git a/mercurial/changegroup.py b/mercurial/changegroup.py --- a/mercurial/changegroup.py +++ b/mercurial/changegroup.py @@ -482,7 +482,17 @@ class cg1packer(object): base = self.deltaparent(revlog, rev, p1, p2, prev) prefix = '' - if base == nullrev: + if revlog.iscensored(base) or revlog.iscensored(rev): + try: + delta = revlog.revision(node) + except error.CensoredNodeError, e: + delta = e.tombstone + if base == nullrev: + prefix = mdiff.trivialdiffheader(len(delta)) + else: + baselen = revlog.rawsize(base) + prefix = mdiff.replacediffheader(baselen, len(delta)) + elif base == nullrev: delta = revlog.revision(node) prefix = mdiff.trivialdiffheader(len(delta)) else: diff --git a/mercurial/error.py b/mercurial/error.py --- a/mercurial/error.py +++ b/mercurial/error.py @@ -138,11 +138,15 @@ class ReadOnlyPartError(RuntimeError): pass class CensoredNodeError(RevlogError): - """error raised when content verification fails on a censored node""" + """error raised when content verification fails on a censored node - def __init__(self, filename, node): + Also contains the tombstone data substituted for the uncensored data. + """ + + def __init__(self, filename, node, tombstone): from node import short RevlogError.__init__(self, '%s:%s' % (filename, short(node))) + self.tombstone = tombstone class CensoredBaseError(RevlogError): """error raised when a delta is rejected because its base is censored diff --git a/mercurial/filelog.py b/mercurial/filelog.py --- a/mercurial/filelog.py +++ b/mercurial/filelog.py @@ -101,7 +101,7 @@ class filelog(revlog.revlog): super(filelog, self).checkhash(text, p1, p2, node, rev=rev) except error.RevlogError: if _censoredtext(text): - raise error.CensoredNodeError(self.indexfile, node) + raise error.CensoredNodeError(self.indexfile, node, text) raise def iscensored(self, rev):