revlog: support reading generaldelta revlogs
authorSune Foldager <cryo@cyanite.org>
Sat, 07 May 2011 22:40:17 +0200
changeset 14253 c28d5200374c
parent 14252 19067884c5f5
child 14254 d6a762d93b77
revlog: support reading generaldelta revlogs Generaldelta is a new revlog global flag. When it's turned on, the base field of each revision entry holds the deltaparent instead of the base revision of the current delta chain. This allows for great potential flexibility when generating deltas, as any revision can serve as deltaparent. Previously, the deltaparent for revision r was hardcoded to be r - 1. The base revision of the delta chain can still be accessed as before, since it is now computed in an iterative fashion, following the deltaparents backwards.
mercurial/revlog.py
--- a/mercurial/revlog.py	Sat May 07 22:40:14 2011 +0200
+++ b/mercurial/revlog.py	Sat May 07 22:40:17 2011 +0200
@@ -27,10 +27,11 @@
 REVLOGV0 = 0
 REVLOGNG = 1
 REVLOGNGINLINEDATA = (1 << 16)
+REVLOGGENERALDELTA = (1 << 17)
 REVLOG_DEFAULT_FLAGS = REVLOGNGINLINEDATA
 REVLOG_DEFAULT_FORMAT = REVLOGNG
 REVLOG_DEFAULT_VERSION = REVLOG_DEFAULT_FORMAT | REVLOG_DEFAULT_FLAGS
-REVLOGNG_FLAGS = REVLOGNGINLINEDATA
+REVLOGNG_FLAGS = REVLOGNGINLINEDATA | REVLOGGENERALDELTA
 
 # revlog index flags
 REVIDX_KNOWN_FLAGS = 0
@@ -243,6 +244,7 @@
 
         self.version = v
         self._inline = v & REVLOGNGINLINEDATA
+        self._generaldelta = v & REVLOGGENERALDELTA
         flags = v & ~0xFFFF
         fmt = v & 0xFFFF
         if fmt == REVLOGV0 and flags:
@@ -830,8 +832,11 @@
 
     def deltaparent(self, rev):
         """return deltaparent of the given revision"""
-        if self.index[rev][3] == rev:
+        base = self.index[rev][3]
+        if base == rev:
             return nullrev
+        elif self._generaldelta:
+            return base
         else:
             return rev - 1
 
@@ -865,11 +870,15 @@
         # build delta chain
         chain = []
         index = self.index # for performance
+        generaldelta = self._generaldelta
         iterrev = rev
         e = index[iterrev]
         while iterrev != e[3] and iterrev != cachedrev:
             chain.append(iterrev)
-            iterrev -= 1
+            if generaldelta:
+                iterrev = e[3]
+            else:
+                iterrev -= 1
             e = index[iterrev]
         chain.reverse()
         base = iterrev