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

Mike Edgar adgar at google.com
Mon Mar 2 15:23:58 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 cc212f6b74f2d281babc1f4ec6ab057548a1c0ea
# Parent  75f94dcf76fdfeaebeaaea279ca5b88e3bc8a20b
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 75f94dcf76fd -r cc212f6b74f2 mercurial/changegroup.py
--- a/mercurial/changegroup.py	Thu Feb 19 19:32:06 2015 +0800
+++ 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(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 -r 75f94dcf76fd -r cc212f6b74f2 mercurial/error.py
--- a/mercurial/error.py	Thu Feb 19 19:32:06 2015 +0800
+++ 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 75f94dcf76fd -r cc212f6b74f2 mercurial/filelog.py
--- a/mercurial/filelog.py	Thu Feb 19 19:32:06 2015 +0800
+++ 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