Patchwork [5,of,5,RFC] changegroup: produce correct deltas when revisions are tombstoned

login
register
mail settings
Submitter adgar@google.com
Date Oct. 15, 2014, 8:05 p.m.
Message ID <d8e87ade304886cbbef7.1413403515@adgar.nyc.corp.google.com>
Download mbox | patch
Permalink /patch/6296/
State Deferred
Headers show

Comments

adgar@google.com - Oct. 15, 2014, 8:05 p.m.
# HG changeset patch
# User Mike Edgar <adgar@google.com>
# Date 1409797442 14400
#      Wed Sep 03 22:24:02 2014 -0400
# Node ID d8e87ade304886cbbef70bb9ab576f95ac9b5430
# Parent  c03f1d585d0987fa6c7657b26230471c7eebc1f3
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.

Patch

diff -r c03f1d585d09 -r d8e87ade3048 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)
         basenode = revlog.node(base)
         meta = self.builddeltaheader(node, p1n, p2n, basenode, linknode)
@@ -436,6 +440,17 @@ 
         # do nothing with basenode, it is implicitly the previous one in HG10
         return struct.pack(self.deltaheader, node, p1n, p2n, linknode)
 
+def _tombstonedelta(revlog, base, rev):
+    try:
+        basedata = revlog.revision(base)
+    except error.CensoredNodeError, e:
+        basedata = e.metadata
+    try:
+        revdata = revlog.revision(rev)
+    except error.CensoredNodeError, e:
+        revdata = e.metadata
+    return struct.pack(">lll", 0, len(basedata), len(revdata)) + revdata
+
 def _changegroupinfo(repo, nodes, source):
     if repo.ui.verbose or source == 'bundle':
         repo.ui.status(_("%d changesets found\n") % len(nodes))