changegroup: emit full-replacement deltas if either revision is censored
authorMike Edgar <adgar@google.com>
Wed, 21 Jan 2015 22:09:32 -0500
changeset 24190 903c7e8c97ad
parent 24189 8b4b9ee6001a
child 24191 8fe5fc8d7b8e
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
mercurial/changegroup.py
mercurial/error.py
mercurial/filelog.py
--- a/mercurial/changegroup.py	Fri Feb 06 11:04:55 2015 -0800
+++ b/mercurial/changegroup.py	Wed Jan 21 22:09:32 2015 -0500
@@ -482,7 +482,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:
--- a/mercurial/error.py	Fri Feb 06 11:04:55 2015 -0800
+++ b/mercurial/error.py	Wed Jan 21 22:09:32 2015 -0500
@@ -138,11 +138,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
--- a/mercurial/filelog.py	Fri Feb 06 11:04:55 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):