dirstate-v2: actually fix the dirstate-v2 upgrade race stable
authorArseniy Alekseyev <aalekseyev@janestreet.com>
Mon, 26 Jun 2023 11:21:43 +0100
branchstable
changeset 50723 bfbd84c57bda
parent 50722 42f761e97dec
child 50724 a10d823a8e3d
dirstate-v2: actually fix the dirstate-v2 upgrade race It looks like the previous fix for the dirstate-v2 upgrade race didn't work. The problem is that it only recovers in case the size of the v1 `dirstate` file is smaller than the `v2` one, whereas in real life it's always larger. This commit changes the test to be more realistic, which reveals the crash, and changes the code to fix the crash.
mercurial/dirstatemap.py
tests/test-dirstate-version-fallback.t
--- a/mercurial/dirstatemap.py	Thu Jun 22 14:24:45 2023 +0200
+++ b/mercurial/dirstatemap.py	Mon Jun 26 11:21:43 2023 +0100
@@ -4,7 +4,6 @@
 # GNU General Public License version 2 or any later version.
 
 
-import struct
 from .i18n import _
 
 from . import (
@@ -152,15 +151,13 @@
                     b'dirstate only has a docket in v2 format'
                 )
             self._set_identity()
-            try:
+            data = self._readdirstatefile()
+            if data == b'' or data.startswith(docketmod.V2_FORMAT_MARKER):
                 self._docket = docketmod.DirstateDocket.parse(
-                    self._readdirstatefile(), self._nodeconstants
+                    data, self._nodeconstants
                 )
-            except struct.error:
-                self._ui.debug(b"failed to read dirstate-v2 data")
-                raise error.CorruptedDirstate(
-                    b"failed to read dirstate-v2 data"
-                )
+            else:
+                raise error.CorruptedDirstate(b"dirstate is not in v2 format")
         return self._docket
 
     def _read_v2_data(self):
--- a/tests/test-dirstate-version-fallback.t	Thu Jun 22 14:24:45 2023 +0200
+++ b/tests/test-dirstate-version-fallback.t	Mon Jun 26 11:21:43 2023 +0100
@@ -10,8 +10,8 @@
   $ hg init repo
   $ cd repo
   $ echo a > a
-  $ hg add a
-  $ hg commit -m a
+  $ touch file-with-somewhat-long-name-to-make-dirstate-v1-bigger-than-v2
+  $ hg commit -Aqm a
   $ hg debugrequires | grep dirstate
   [1]
   $ ls -1 .hg/dirstate*