Patchwork [3,of,5,RFC] revlog: allow building deltas against local tombstones in _addrevision

login
register
mail settings
Submitter adgar@google.com
Date Oct. 15, 2014, 8:05 p.m.
Message ID <bda2ddd8d3d9f4f5cd24.1413403513@adgar.nyc.corp.google.com>
Download mbox | patch
Permalink /patch/6294/
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 1409572170 -7200
#      Mon Sep 01 13:49:30 2014 +0200
# Node ID bda2ddd8d3d9f4f5cd24b74560dc2bd2eaaeb236
# Parent  4416e2cfe289eb64d6d6b1907723c2860e45e79c
revlog: allow building deltas against local tombstones in _addrevision

When appending a revision of an existing file, via unbundle/pull/commit/etc,
the revlog will consider storing a delta for that revision (by comparing the
size of the delta chain against the fulltext of the revision). This requires
materializing the file at the delta base revision unless the delta cache hits.

That materialization will fail if the chosen delta base is a censor tombstone;
this change permits delta construction to proceed in this case.

In practice, this is required for three major scenarios:

1. Building/importing a generaldelta can always miss the delta cache.
2. Unbundling a new revision of a file whose last stored revision is censored
   AND the bundle's delta base is not the tombstoned last revision.
3. Committing a new revision of a file whose last stored revision is censored.
   This is possible purely locally with 1 head at all times:
   r0) commit file
   r1) delete file
   r1) censor file at r0
   r2) commit file

Patch

diff -r 4416e2cfe289 -r bda2ddd8d3d9 mercurial/revlog.py
--- a/mercurial/revlog.py	Wed Sep 03 16:34:59 2014 -0400
+++ b/mercurial/revlog.py	Mon Sep 01 13:49:30 2014 +0200
@@ -1192,7 +1192,11 @@ 
                 delta = cachedelta[1]
             else:
                 t = buildtext()
-                ptext = self.revision(self.node(rev))
+                try:
+                    ptext = self.revision(self.node(rev))
+                except CensoredNodeError, e:
+                    # building a new delta against a local tombstone is allowed
+                    ptext = e.metadata
                 delta = mdiff.textdiff(ptext, t)
             data = self.compress(delta)
             l = len(data[1]) + len(data[0])