changeset 51352:7083b33a2699

delta-find: explicitly deal with usage of the cached revision We can remove this from the general logic path and directly deal with this corner case early. This result in a small change in test-generaldelta.t as it turns out that: - at commit time we (sometimes) precompute a delta against p1 and pass it as the cached delta. - since cached delta where going through the same filtering as everything, we could "optimize" the base if it applied to an empty delta, resulting in not using the pre-computed delta. The simpler logic fix the second item, making the cached delta base always actually tested when requested. Note that the computation of a fast delta against p1 only is questionable, but looking into that is out of scope for this series.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Sun, 07 Jan 2024 03:08:46 +0100
parents bbbfa00d1e67
children 5cc04a6da19d
files mercurial/revlogutils/deltas.py tests/test-generaldelta.t
diffstat 2 files changed, 27 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/revlogutils/deltas.py	Sun Jan 07 03:02:30 2024 +0100
+++ b/mercurial/revlogutils/deltas.py	Sun Jan 07 03:08:46 2024 +0100
@@ -840,7 +840,24 @@
         assert self.revlog.delta_config.general_delta
         self._candidates_iterator = self._refined_groups()
         self._last_good = None
-        self._next_internal_group()
+        if (
+            self.cachedelta is not None
+            and self.cachedelta[2] > DELTA_BASE_REUSE_NO
+            and self._pre_filter_rev(self.cachedelta[0])
+        ):
+            # First we try to reuse a the delta contained in the bundle.  (or from
+            # the source revlog)
+            #
+            # This logic only applies to general delta repositories and can be
+            # disabled through configuration. Disabling reuse source delta is
+            # useful when we want to make sure we recomputed "optimal" deltas.
+            self.current_stage = _STAGE_CACHED
+            self._internal_group = (self.cachedelta[0],)
+            self._internal_idx = 0
+            self.current_group = self._internal_group
+            self.tested.update(self.current_group)
+        else:
+            self._next_internal_group()
 
     def _next_internal_group(self):
         # self._internal_group can be larger than self.current_group
@@ -868,6 +885,14 @@
         old_good = self._last_good
         if good_delta is not None:
             self._last_good = good_delta.base
+        if self.current_stage == _STAGE_CACHED and good_delta is not None:
+            # the cache is good, let us use the cache as requested
+            self._candidates_iterator = None
+            self._internal_group = None
+            self._internal_idx = None
+            self.current_group = None
+            return
+
         if (self._internal_idx < len(self._internal_group)) and (
             old_good != good_delta
         ):
@@ -1032,23 +1057,6 @@
 
     def _refined_groups(self):
         good = None
-        # First we try to reuse a the delta contained in the bundle.  (or from
-        # the source revlog)
-        #
-        # This logic only applies to general delta repositories and can be
-        # disabled through configuration. Disabling reuse source delta is
-        # useful when we want to make sure we recomputed "optimal" deltas.
-        if (
-            self.cachedelta is not None
-            and self.cachedelta[2] > DELTA_BASE_REUSE_NO
-        ):
-            # Assume what we received from the server is a good choice
-            # build delta will reuse the cache
-            self.current_stage = _STAGE_CACHED
-            good = yield (self.cachedelta[0],)
-            if good is not None:
-                yield None
-                return
         groups = self._raw_groups()
         for candidates in groups:
             good = yield candidates
--- a/tests/test-generaldelta.t	Sun Jan 07 03:02:30 2024 +0100
+++ b/tests/test-generaldelta.t	Sun Jan 07 03:08:46 2024 +0100
@@ -271,7 +271,7 @@
        51      17      -1       4        3       50    prev        3??        5??        6??   1.0????       6??         0    0.00000 (glob)
        52      51      -1       4        4       51      p1         58        640        6??   1.0????       6??         0    0.00000 (glob)
        53      52      -1       5        1       -1    base          0          0          0   0.00000         0         0    0.00000
-       54      53      -1       6        1       -1    base        3??        640        3??   0.5????       3??         0    0.00000 (glob)
+       54      53      -1       5        2       53      p1        3??        640        3??   0.5????       3??         0    0.00000 (glob)
   $ hg clone --pull source-repo --config experimental.maxdeltachainspan=2800 relax-chain --config format.generaldelta=yes
   requesting all changes
   adding changesets