[PATCH censor RFC] changegroup: emit full-replacement deltas if either revision is censored

Mike Edgar adgar at google.com
Wed Feb 11 20:51:56 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 a770441a605cfcbdc757a02d3847c1e8880e29e4
# Parent  1b3b6d629d6c1f8544db349707e47293965b94c0
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 1b3b6d629d6c -r a770441a605c mercurial/changegroup.py
--- a/mercurial/changegroup.py	Wed Jan 21 17:11:37 2015 -0500
+++ b/mercurial/changegroup.py	Wed Jan 21 22:09:32 2015 -0500
@@ -481,7 +481,17 @@
         base = self.deltaparent(revlog, rev, p1, p2, prev)
 
         prefix = ''
-        if base == nullrev:
+        if revlog.iscensored(base) or revlog.iscensored(rev):
+            try:
+                delta = revlog.revision(rev)
+            except error.CensoredNodeError, e:
+                delta = e.metadata
+            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 -r 1b3b6d629d6c -r a770441a605c mercurial/error.py
--- a/mercurial/error.py	Wed Jan 21 17:11:37 2015 -0500
+++ b/mercurial/error.py	Wed Jan 21 22:09:32 2015 -0500
@@ -138,9 +138,10 @@
 class CensoredNodeError(RevlogError):
     """error raised when content verification fails on a censored node"""
 
-    def __init__(self, filename, node):
+    def __init__(self, filename, node, metadata):
         from node import short
         RevlogError.__init__(self, '%s:%s' % (filename, short(node)))
+        self.metadata = metadata
 
 class CensoredBaseError(RevlogError):
     """error raised when a delta is rejected because its base is censored
diff -r 1b3b6d629d6c -r a770441a605c mercurial/filelog.py
--- a/mercurial/filelog.py	Wed Jan 21 17:11:37 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