revlog: refactor out the selection of candidate revisions
authorPaul Morelle <paul.morelle@octobus.net>
Sun, 14 Jan 2018 12:46:03 -0800
changeset 35634 b43578ec483a
parent 35633 a981ab2a1b4c
child 35635 0b52c0ecbc23
revlog: refactor out the selection of candidate revisions The new function will be useful to retrieve all the revisions which will be needed to determine the best delta, and parallelize the computation of the necessary diffs.
mercurial/revlog.py
--- a/mercurial/revlog.py	Sat Dec 30 00:13:56 2017 +0530
+++ b/mercurial/revlog.py	Sun Jan 14 12:46:03 2018 -0800
@@ -1844,6 +1844,44 @@
 
         return True
 
+    def _getcandidaterevs(self, p1, p2, cachedelta):
+        """
+        Provides revisions that present an interest to be diffed against,
+        grouped by level of easiness.
+        """
+        curr = len(self)
+        prev = curr - 1
+        p1r, p2r = self.rev(p1), self.rev(p2)
+
+        # should we try to build a delta?
+        if prev != nullrev and self.storedeltachains:
+            tested = set()
+            # This condition is true most of the time when processing
+            # changegroup data into a generaldelta repo. The only time it
+            # isn't true is if this is the first revision in a delta chain
+            # or if ``format.generaldelta=true`` disabled ``lazydeltabase``.
+            if cachedelta and self._generaldelta and self._lazydeltabase:
+                # Assume what we received from the server is a good choice
+                # build delta will reuse the cache
+                yield (cachedelta[0],)
+                tested.add(cachedelta[0])
+
+            if self._generaldelta:
+                # exclude already lazy tested base if any
+                parents = [p for p in (p1r, p2r)
+                           if p != nullrev and p not in tested]
+                if parents and not self._aggressivemergedeltas:
+                    # Pick whichever parent is closer to us (to minimize the
+                    # chance of having to build a fulltext).
+                    parents = [max(parents)]
+                tested.update(parents)
+                yield parents
+
+            if prev not in tested:
+                # other approach failed try against prev to hopefully save us a
+                # fulltext.
+                yield (prev,)
+
     def _addrevision(self, node, rawtext, transaction, link, p1, p2, flags,
                      cachedelta, ifh, dfh, alwayscache=False):
         """internal function to add revisions to the log
@@ -1943,42 +1981,16 @@
         else:
             textlen = len(rawtext)
 
-        # should we try to build a delta?
-        if prev != nullrev and self.storedeltachains:
-            tested = set()
-            # This condition is true most of the time when processing
-            # changegroup data into a generaldelta repo. The only time it
-            # isn't true is if this is the first revision in a delta chain
-            # or if ``format.generaldelta=true`` disabled ``lazydeltabase``.
-            if cachedelta and self._generaldelta and self._lazydeltabase:
-                # Assume what we received from the server is a good choice
-                # build delta will reuse the cache
-                candidatedelta = builddelta(cachedelta[0])
-                tested.add(cachedelta[0])
+        for candidaterevs in self._getcandidaterevs(p1, p2, cachedelta):
+            nominateddeltas = []
+            for candidaterev in candidaterevs:
+                candidatedelta = builddelta(candidaterev)
                 if self._isgooddelta(candidatedelta, textlen):
-                    delta = candidatedelta
-            if delta is None and self._generaldelta:
-                # exclude already lazy tested base if any
-                parents = [p for p in (p1r, p2r)
-                           if p != nullrev and p not in tested]
-                if parents and not self._aggressivemergedeltas:
-                    # Pick whichever parent is closer to us (to minimize the
-                    # chance of having to build a fulltext).
-                    parents = [max(parents)]
-                tested.update(parents)
-                pdeltas = []
-                for p in parents:
-                    pd = builddelta(p)
-                    if self._isgooddelta(pd, textlen):
-                        pdeltas.append(pd)
-                if pdeltas:
-                    delta = min(pdeltas, key=lambda x: x[1])
-            if delta is None and prev not in tested:
-                # other approach failed try against prev to hopefully save us a
-                # fulltext.
-                candidatedelta = builddelta(prev)
-                if self._isgooddelta(candidatedelta, textlen):
-                    delta = candidatedelta
+                    nominateddeltas.append(candidatedelta)
+            if nominateddeltas:
+                delta = min(nominateddeltas, key=lambda x: x[1])
+                break
+
         if delta is not None:
             dist, l, data, base, chainbase, chainlen, compresseddeltalen = delta
         else: