revlogdeltas: always return a delta info object in finddeltainfo
authorBoris Feld <boris.feld@octobus.net>
Thu, 16 Aug 2018 04:38:57 +0200
changeset 39360 5d343a24bff5
parent 39359 6f4b8f607a31
child 39361 507f5b1dd7c8
revlogdeltas: always return a delta info object in finddeltainfo Previously, the method returned `None` when a full snapshot was needed. The caller had to determine how to produce one itself. In practice, building a `_deltainfo` object for a full snapshot is simple. So we build it at the `finddeltainfo` level and always return a `_deltainfo` object. The caller can now simply process the `_deltainfo` return in all cases.
mercurial/revlog.py
mercurial/revlogutils/deltas.py
--- a/mercurial/revlog.py	Thu Aug 16 04:20:34 2018 +0200
+++ b/mercurial/revlog.py	Thu Aug 16 04:38:57 2018 +0200
@@ -1967,31 +1967,23 @@
 
         deltainfo = deltacomputer.finddeltainfo(revinfo, fh)
 
-        if deltainfo is not None:
-            base = deltainfo.base
-            chainbase = deltainfo.chainbase
-            data = deltainfo.data
-            l = deltainfo.deltalen
-        else:
-            rawtext = deltacomputer.buildtext(revinfo, fh)
-            data = self.compress(rawtext)
-            l = len(data[1]) + len(data[0])
-            base = chainbase = curr
-
-        e = (offset_type(offset, flags), l, textlen,
-             base, link, p1r, p2r, node)
+        e = (offset_type(offset, flags), deltainfo.deltalen, textlen,
+             deltainfo.base, link, p1r, p2r, node)
         self.index.append(e)
         self.nodemap[node] = curr
 
         entry = self._io.packentry(e, self.node, self.version, curr)
-        self._writeentry(transaction, ifh, dfh, entry, data, link, offset)
+        self._writeentry(transaction, ifh, dfh, entry, deltainfo.data,
+                         link, offset)
+
+        rawtext = btext[0]
 
         if alwayscache and rawtext is None:
             rawtext = deltacomputer.buildtext(revinfo, fh)
 
         if type(rawtext) == bytes: # only accept immutable objects
             self._cache = (node, curr, rawtext)
-        self._chainbasecache[curr] = chainbase
+        self._chainbasecache[curr] = deltainfo.chainbase
         return node
 
     def _writeentry(self, transaction, ifh, dfh, entry, data, link, offset):
--- a/mercurial/revlogutils/deltas.py	Thu Aug 16 04:20:34 2018 +0200
+++ b/mercurial/revlogutils/deltas.py	Thu Aug 16 04:38:57 2018 +0200
@@ -690,6 +690,19 @@
                           chainbase, chainlen, compresseddeltalen,
                           snapshotdepth)
 
+    def _fullsnapshotinfo(self, fh, revinfo):
+        curr = len(self.revlog)
+        rawtext = self.buildtext(revinfo, fh)
+        data = self.revlog.compress(rawtext)
+        compresseddeltalen = deltalen = dist = len(data[1]) + len(data[0])
+        deltabase = chainbase = curr
+        snapshotdepth = 0
+        chainlen = 1
+
+        return _deltainfo(dist, deltalen, data, deltabase,
+                          chainbase, chainlen, compresseddeltalen,
+                          snapshotdepth)
+
     def finddeltainfo(self, revinfo, fh):
         """Find an acceptable delta against a candidate revision
 
@@ -699,15 +712,18 @@
 
         Returns the first acceptable candidate revision, as ordered by
         _getcandidaterevs
+
+        If no suitable deltabase is found, we return delta info for a full
+        snapshot.
         """
         if not revinfo.textlen:
-            return None # empty file do not need delta
+            return self._fullsnapshotinfo(fh, revinfo)
 
         # no delta for flag processor revision (see "candelta" for why)
         # not calling candelta since only one revision needs test, also to
         # avoid overhead fetching flags again.
         if revinfo.flags & REVIDX_RAWTEXT_CHANGING_FLAGS:
-            return None
+            return self._fullsnapshotinfo(fh, revinfo)
 
         cachedelta = revinfo.cachedelta
         p1 = revinfo.p1
@@ -742,4 +758,6 @@
                 deltainfo = min(nominateddeltas, key=lambda x: x.deltalen)
                 break
 
+        if deltainfo is None:
+            deltainfo = self._fullsnapshotinfo(fh, revinfo)
         return deltainfo