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

login
register
mail settings
Submitter michaeljedgar@gmail.com
Date Sept. 11, 2014, 12:26 a.m.
Message ID <bb822c8a38958cc78b03.1410395179@adgar-macbookpro3.roam.corp.google.com>
Download mbox | patch
Permalink /patch/5793/
State Changes Requested
Headers show

Comments

michaeljedgar@gmail.com - Sept. 11, 2014, 12:26 a.m.
# HG changeset patch
# User Mike Edgar <adgar@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.

Patch

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))