delta-find: never do anything fancy when general delta is off stable
authorPierre-Yves David <pierre-yves.david@octobus.net>
Wed, 19 Apr 2023 18:16:19 +0200
branchstable
changeset 50435 0232571255d3
parent 50434 ca1522fe4ec8
child 50436 2a6949ab9d23
delta-find: never do anything fancy when general delta is off Without general delta, the only option is to do a delta against the previous revision in the revlog, or to do a full snapshot. So no need to dive into the more complicated logic. This prevent Mercurial to misbehave when applying remote deltas when `pulled-delta-reuse-policy` was set to "try-base" or "forced" and would produce and store invalid deltas. We add an associated tests to make sure this scenario is covered by tests. There are more code to cleanup after this, but I what to keep the fixing patch simple.
mercurial/revlogutils/deltas.py
tests/test-pullling-to-general-delta.t
--- a/mercurial/revlogutils/deltas.py	Wed Apr 19 16:59:03 2023 +0200
+++ b/mercurial/revlogutils/deltas.py	Wed Apr 19 18:16:19 2023 +0200
@@ -687,6 +687,12 @@
     if target_rev is None:
         target_rev = len(revlog)
 
+    if not revlog._generaldelta:
+        # before general delta, there is only one possible delta base
+        yield (target_rev - 1,)
+        yield None
+        return
+
     if (
         cachedelta is not None
         and nullrev == cachedelta[0]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-pullling-to-general-delta.t	Wed Apr 19 18:16:19 2023 +0200
@@ -0,0 +1,196 @@
+============================================================================
+Pulling from modern to a non-general delta target (and other related checks)
+============================================================================
+
+There is various issue that can arise when we update the code with modern
+storage in mind while working on delta processing. So this file is meant for
+various scenario that might break in the future or have break in the past.
+
+Setup
+=====
+
+Create a modern server with an older clone
+
+  $ cat << EOF >> $HGRCPATH
+  > [command-templates]
+  > log = "{desc} {tags}\n"
+  > EOF
+
+  $ hg init server
+
+  $ hg clone --quiet --pull server client --config format.usegeneraldelta=no
+  $ hg debugformat -R client | grep generaldelta
+  generaldelta:        no
+
+Create some complexe history
+
+  $ cd server
+  $ hg debugbuilddag -n '.+3:a$.+5:b/a:k$.+7:c/b:l$.+6:d/a:m<k+6/l+1/m'
+  $ hg log -G
+  o    r36 tip
+  |\
+  | o  r35
+  | |
+  | o    r34
+  | |\
+  | | o  r33
+  | | |
+  | | o  r32
+  | | |
+  | | o  r31
+  | | |
+  | | o  r30
+  | | |
+  | | o  r29
+  | | |
+  | | o  r28
+  | | |
+  o | |    r27 m
+  |\ \ \
+  | o | |  r26 d
+  | | | |
+  | o | |  r25
+  | | | |
+  | o | |  r24
+  | | | |
+  | o | |  r23
+  | | | |
+  | o | |  r22
+  | | | |
+  | o | |  r21
+  | | | |
+  | o | |  r20
+  |  / /
+  | o |    r19 l
+  | |\ \
+  | | o |  r18 c
+  | | | |
+  | | o |  r17
+  | | | |
+  | | o |  r16
+  | | | |
+  | | o |  r15
+  | | | |
+  | | o |  r14
+  | | | |
+  | | o |  r13
+  | | | |
+  | | o |  r12
+  | | | |
+  | | o |  r11
+  | |  /
+  +---o  r10 k
+  | |/
+  | o  r9 b
+  | |
+  | o  r8
+  | |
+  | o  r7
+  | |
+  | o  r6
+  | |
+  | o  r5
+  | |
+  | o  r4
+  |
+  o  r3 a
+  |
+  o  r2
+  |
+  o  r1
+  |
+  o  r0
+  
+  $ cd ..
+
+
+Pull it in the client
+=====================
+
+
+pull with default value
+-----------------------
+
+  $ cp -R client client-simple-pull
+  $ hg -R client-simple-pull pull
+  pulling from $TESTTMP/server
+  requesting all changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 37 changesets with 37 changes to 37 files
+  new changesets 61246295ee1e:b4b117cbbcf3
+  (run 'hg update' to get a working copy)
+  $ hg -R client-simple-pull verify
+  checking changesets
+  checking manifests
+  crosschecking files in changesets and manifests
+  checking files
+  checking dirstate
+  checked 37 changesets with 37 changes to 37 files
+
+
+pull with "no-reuse" policy
+---------------------------
+
+  $ cp -R client client-no-reuse
+  $ hg -R client-no-reuse pull --config paths.default:pulled-delta-reuse-policy=no-reuse
+  pulling from $TESTTMP/server
+  requesting all changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 37 changesets with 37 changes to 37 files
+  new changesets 61246295ee1e:b4b117cbbcf3
+  (run 'hg update' to get a working copy)
+  $ hg -R client-no-reuse verify
+  checking changesets
+  checking manifests
+  crosschecking files in changesets and manifests
+  checking files
+  checking dirstate
+  checked 37 changesets with 37 changes to 37 files
+
+
+pull with "try-base" policy
+---------------------------
+
+  $ cp -R client client-try-base
+  $ hg -R client-try-base pull --config paths.default:pulled-delta-reuse-policy=try-base
+  pulling from $TESTTMP/server
+  requesting all changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 37 changesets with 37 changes to 37 files
+  new changesets 61246295ee1e:b4b117cbbcf3
+  (run 'hg update' to get a working copy)
+  $ hg -R client-try-base verify
+  checking changesets
+  checking manifests
+  crosschecking files in changesets and manifests
+  checking files
+  checking dirstate
+  checked 37 changesets with 37 changes to 37 files
+
+
+pull with "forced" policy
+-------------------------
+
+  $ cp -R client client-forced
+  $ hg -R client-forced pull --config paths.default:pulled-delta-reuse-policy=forced
+  pulling from $TESTTMP/server
+  requesting all changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 37 changesets with 37 changes to 37 files
+  new changesets 61246295ee1e:b4b117cbbcf3
+  (run 'hg update' to get a working copy)
+  $ hg -R client-forced verify
+  checking changesets
+  checking manifests
+  crosschecking files in changesets and manifests
+  checking files
+  checking dirstate
+  checked 37 changesets with 37 changes to 37 files