[PATCH 2 of 2 censor RFC v2] changegroup: emit full-replacement deltas if either revision is censored
Mike Edgar
adgar at google.com
Fri Feb 20 21:54:34 UTC 2015
# HG changeset patch
# User Mike Edgar <adgar at google.com>
# Date 1421896172 18000
# Wed Jan 21 22:09:32 2015 -0500
# Node ID 7f6876c8566298d30d73d9b5a2e46d21b01827f9
# Parent 96a3db818b2ec56f420c677ca38ea34dc46af9ff
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 -r 96a3db818b2e -r 7f6876c85662 mercurial/changegroup.py
--- a/mercurial/changegroup.py Fri Feb 20 15:44:17 2015 -0500
+++ b/mercurial/changegroup.py Wed Jan 21 22:09:32 2015 -0500
@@ -480,9 +480,17 @@
p1, p2 = revlog.parentrevs(rev)
base = self.deltaparent(revlog, rev, p1, p2, prev)
+ snapshot = None # if snapshot is not None, produce a trivial delta
+ if base == nullrev or revlog.iscensored(base) or revlog.iscensored(rev):
+ try:
+ snapshot = revlog.revision(rev)
+ except error.CensoredNodeError, e:
+ snapshot = e.tombstone
if base == nullrev:
- snapshot = revlog.revision(node)
delta = mdiff.trivialdiffheader(len(snapshot)) + snapshot
+ elif snapshot is not None:
+ baselen = revlog.rawsize(base)
+ delta = mdiff.replacediffheader(baselen, len(snapshot)) + snapshot
else:
delta = revlog.revdiff(base, rev)
p1n, p2n = revlog.parents(node)
diff -r 96a3db818b2e -r 7f6876c85662 mercurial/error.py
--- a/mercurial/error.py Fri Feb 20 15:44:17 2015 -0500
+++ b/mercurial/error.py Wed Jan 21 22:09:32 2015 -0500
@@ -136,11 +136,15 @@
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 -r 96a3db818b2e -r 7f6876c85662 mercurial/filelog.py
--- a/mercurial/filelog.py Fri Feb 20 15:44:17 2015 -0500
+++ b/mercurial/filelog.py Wed Jan 21 22:09:32 2015 -0500
@@ -101,7 +101,7 @@
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):
More information about the Mercurial-devel
mailing list