[PATCH 18 of 21 RFC] changegroup: produce correct deltas when revisions are tombstoned

michaeljedgar at gmail.com michaeljedgar at gmail.com
Wed Sep 10 19:26:19 CDT 2014


# HG changeset patch
# User Mike Edgar <adgar at google.com>
# Date 1409797442 14400
#      Wed Sep 03 22:24:02 2014 -0400
# Node ID bb822c8a38958cc78b039463efa59ac9b0556af3
# Parent  a6272d4ba78bbc579ef868ca188ee8e8f3e9e0c6
changegroup: produce correct deltas when revisions are tombstoned

When creating a delta between old and new revisions of a file using
revlog.revdiff, either the old or new (or both) could be tombstoned. Since the
bundle10 format expects each changegroup to be based on the previous, we must
produce a delta between each successive revision.

This change uses the new filelog method censormeta(rev) to safely obtain the
censorship metadata if and only if the given revision is censored. The content
of the metadata is not relevant for creating a valid delta.

diff -r a6272d4ba78b -r bb822c8a3895 mercurial/changegroup.py
--- a/mercurial/changegroup.py	Mon Sep 01 14:38:29 2014 +0200
+++ b/mercurial/changegroup.py	Wed Sep 03 22:24:02 2014 -0400
@@ -423,7 +423,11 @@
                 delta = e.metadata
             prefix = mdiff.trivialdiffheader(len(delta))
         else:
-            delta = revlog.revdiff(base, rev)
+            try:
+                delta = revlog.revdiff(base, rev)
+            except error.CensoredNodeError:
+                delta = _tombstonedelta(revlog, base, rev)
+
         p1n, p2n = revlog.parents(node)
         meta = struct.pack(self.deltaheader, node, p1n, p2n, linknode)
         meta += prefix
@@ -432,6 +436,19 @@
         yield meta
         yield delta
 
+def _tombstonedelta(revlog, base, rev):
+    basec = revlog.censormeta(base)
+    revc = revlog.censormeta(rev)
+    if basec:
+        deleted = len(basec)
+    else:
+        deleted = revlog.rawsize(base)
+    if revc:
+        delta = revc
+    else:
+        delta = revlog.revision(rev)
+    return struct.pack(">lll", 0, deleted, len(delta)) + delta
+
 def _changegroupinfo(repo, nodes, source):
     if repo.ui.verbose or source == 'bundle':
         repo.ui.status(_("%d changesets found\n") % len(nodes))


More information about the Mercurial-devel mailing list