Patchwork [5,of,6,censor,RFC] changegroup: emit full-replacement deltas if either revision is censored

login
register
mail settings
Submitter adgar@google.com
Date Jan. 23, 2015, 11:53 p.m.
Message ID <a047ca8ca035158ecd9d.1422057205@adgar.nyc.corp.google.com>
Download mbox | patch
Permalink /patch/7547/
State Superseded
Commit 903c7e8c97ad97dd579de976d4e62dd7af4965b4
Headers show

Comments

adgar@google.com - Jan. 23, 2015, 11:53 p.m.
# HG changeset patch
# User Mike Edgar <adgar@google.com>
# Date 1421896172 18000
#      Wed Jan 21 22:09:32 2015 -0500
# Node ID a047ca8ca035158ecd9d034b9b4232be8b8080d4
# Parent  38c9db6fa5d4c6ee6c607278e12daa1bc003a345
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

Patch

diff -r 38c9db6fa5d4 -r a047ca8ca035 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
@@ -447,7 +447,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 38c9db6fa5d4 -r a047ca8ca035 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
@@ -136,9 +136,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(CensoredNodeError):
     """error raised when a delta is rejected because its base is censored
diff -r 38c9db6fa5d4 -r a047ca8ca035 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):