Patchwork [1,of,3] addrevision: rework generaldelta computation

login
register
mail settings
Submitter Pierre-Yves David
Date Dec. 2, 2015, 5:32 p.m.
Message ID <36b2104baffa3b37993d.1449077568@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/11761/
State Accepted
Headers show

Comments

Pierre-Yves David - Dec. 2, 2015, 5:32 p.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@fb.com>
# Date 1449024316 28800
#      Tue Dec 01 18:45:16 2015 -0800
# Node ID 36b2104baffa3b37993de698e6957b830bbb42cc
# Parent  b907edfa2c846952ff06a00abd888ce1cdca395c
# EXP-Topic generaldelta
# Available At http://hg.netv6.net/marmoute-wip/mercurial/
#              hg pull http://hg.netv6.net/marmoute-wip/mercurial/ -r 36b2104baffa
addrevision: rework generaldelta computation

The old code have multiple explicit tests and code duplications. This makes it
hard to improve the code. We rewrite the logic in a more generic way, not
changing anything of the computed result.

The final goal here is to eventually be able to:

- factor out the default fallback case "try against 'prev'" in a single place

- allow 'lazydeltabase' case to use the smarter general delta code path when
  the incoming base does not provide us with a good delta.

Patch

diff --git a/mercurial/revlog.py b/mercurial/revlog.py
--- a/mercurial/revlog.py
+++ b/mercurial/revlog.py
@@ -1432,38 +1432,27 @@  class revlog(object):
                     delta = candidatedelta
                 elif prev != candidatedelta[3]:
                     # Try against prev to hopefully save us a fulltext.
                     delta = builddelta(prev)
             elif self._generaldelta:
-                if p2r != nullrev and self._aggressivemergedeltas:
-                    delta = builddelta(p1r)
-                    delta2 = builddelta(p2r)
-                    p1good = self._isgooddelta(delta, textlen)
-                    p2good = self._isgooddelta(delta2, textlen)
-                    if p1good and p2good:
-                        # If both are good deltas, choose the smallest
-                        if delta2[1] < delta[1]:
-                            delta = delta2
-                    elif p2good:
-                        # If only p2 is good, use it
-                        delta = delta2
-                    elif p1good:
-                        pass
-                    else:
-                        # Neither is good, try against prev to hopefully save us
-                        # a fulltext.
-                        delta = builddelta(prev)
-                else:
+                parents = [p1r, p2r]
+                if not self._aggressivemergedeltas:
                     # Pick whichever parent is closer to us (to minimize the
                     # chance of having to build a fulltext). Since
                     # nullrev == -1, any non-merge commit will always pick p1r.
-                    drev = p2r if p2r > p1r else p1r
-                    delta = builddelta(drev)
-                    # If the chosen delta will result in us making a full text,
-                    # give it one last try against prev.
-                    if drev != prev and not self._isgooddelta(delta, textlen):
-                        delta = builddelta(prev)
+                    parents = [max(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])
+                elif prev not in parents:
+                    # Neither is good, try against prev to hopefully save us
+                    # a fulltext.
+                    delta = builddelta(prev)
             else:
                 delta = builddelta(prev)
         if delta is not None:
             dist, l, data, base, chainbase, chainlen, compresseddeltalen = delta