delta-find: fix pulled-delta-reuse-policy=forced behavior
The code that select delta still has too many oportunity to discard the delta
is has been forcibly asked to reuse. However is is fairly easy to use a
dedicated fastpath for this case. So we do so.
Cleaning other code that tries to enforce that policy will be done on default.
--- a/mercurial/revlogutils/deltas.py Thu Jun 08 03:49:44 2023 +0200
+++ b/mercurial/revlogutils/deltas.py Mon Jun 05 03:11:26 2023 +0200
@@ -1262,8 +1262,10 @@
gather_debug = self._gather_debug
cachedelta = revinfo.cachedelta
revlog = self.revlog
+ p1r = p2r = None
- p1r = p2r = None
+ if excluded_bases is None:
+ excluded_bases = set()
if gather_debug:
start = util.timer()
@@ -1310,15 +1312,80 @@
'delta-base'
] = deltainfo.base # pytype: disable=attribute-error
dbg['search_round_count'] = 0
- dbg['using-cached-base'] = True
+ dbg['using-cached-base'] = False
dbg['delta_try_count'] = 0
dbg['type'] = b"full"
dbg['snapshot-depth'] = 0
self._dbg_process_data(dbg)
return deltainfo
- if excluded_bases is None:
- excluded_bases = set()
+ deltainfo = None
+
+ # If this source delta are to be forcibly reuse, let us comply early.
+ if (
+ revlog._generaldelta
+ and revinfo.cachedelta is not None
+ and revinfo.cachedelta[2] == DELTA_BASE_REUSE_FORCE
+ ):
+ base = revinfo.cachedelta[0]
+ if base == nullrev:
+ dbg_type = b"full"
+ deltainfo = self._fullsnapshotinfo(fh, revinfo, target_rev)
+ if gather_debug:
+ snapshotdepth = 0
+ elif base not in excluded_bases:
+ delta = revinfo.cachedelta[1]
+ header, data = revlog.compress(delta)
+ deltalen = len(header) + len(data)
+ if gather_debug:
+ offset = revlog.end(len(revlog) - 1)
+ chainbase = revlog.chainbase(base)
+ distance = deltalen + offset - revlog.start(chainbase)
+ chainlen, compresseddeltalen = revlog._chaininfo(base)
+ chainlen += 1
+ compresseddeltalen += deltalen
+ if base == p1r or base == p2r:
+ dbg_type = b"delta"
+ snapshotdepth = None
+ elif not revlog.issnapshot(base):
+ snapshotdepth = None
+ else:
+ dbg_type = b"snapshot"
+ snapshotdepth = revlog.snapshotdepth(base) + 1
+ else:
+ distance = None
+ chainbase = None
+ chainlen = None
+ compresseddeltalen = None
+ snapshotdepth = None
+ deltainfo = _deltainfo(
+ distance=distance,
+ deltalen=deltalen,
+ data=(header, data),
+ base=base,
+ chainbase=chainbase,
+ chainlen=chainlen,
+ compresseddeltalen=compresseddeltalen,
+ snapshotdepth=snapshotdepth,
+ )
+
+ if deltainfo is not None:
+ if gather_debug:
+ end = util.timer()
+ dbg['duration'] = end - start
+ dbg[
+ 'delta-base'
+ ] = deltainfo.base # pytype: disable=attribute-error
+ dbg['search_round_count'] = 0
+ dbg['using-cached-base'] = True
+ dbg['delta_try_count'] = 0
+ dbg['type'] = b"full"
+ if snapshotdepth is None:
+ dbg['snapshot-depth'] = 0
+ else:
+ dbg['snapshot-depth'] = snapshotdepth
+ self._dbg_process_data(dbg)
+ return deltainfo
# count the number of different delta we tried (for debug purpose)
dbg_try_count = 0
@@ -1326,7 +1393,6 @@
dbg_try_rounds = 0
dbg_type = b'unknown'
- deltainfo = None
if p1r is None:
p1r = revlog.rev(revinfo.p1)
p2r = revlog.rev(revinfo.p2)
--- a/tests/test-revlog-delta-find.t Thu Jun 08 03:49:44 2023 +0200
+++ b/tests/test-revlog-delta-find.t Mon Jun 05 03:11:26 2023 +0200
@@ -329,8 +329,8 @@
DBG-DELTAS: CHANGELOG: * (glob)
DBG-DELTAS: MANIFESTLOG: * (glob)
DBG-DELTAS: MANIFESTLOG: * (glob)
- DBG-DELTAS: FILELOG:my-file.txt: rev=3: delta-base=2 is-cached=1 *search-rounds=1 try-count=1* (glob)
- DBG-DELTAS: FILELOG:my-file.txt: rev=4: delta-base=3 is-cached=1 *search-rounds=1 try-count=1* (glob)
+ DBG-DELTAS: FILELOG:my-file.txt: rev=3: delta-base=2 is-cached=1 *search-rounds=0 try-count=0* (glob)
+ DBG-DELTAS: FILELOG:my-file.txt: rev=4: delta-base=3 is-cached=1 *search-rounds=0 try-count=0* (glob)
Check that running "forced" on a non-general delta repository does not corrupt it
---------------------------------------------------------------------------------