# HG changeset patch # User Arseniy Alekseyev # Date 2023-06-26 10:21:43 # Node ID bfbd84c57bda1d3f1d9be3da848ad921d99a0536 # Parent 42f761e97decbd95b5c3171ba83701828d60db24 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. diff --git a/mercurial/dirstatemap.py b/mercurial/dirstatemap.py --- a/mercurial/dirstatemap.py +++ b/mercurial/dirstatemap.py @@ -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 @@ class _dirstatemapcommon: 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): diff --git a/tests/test-dirstate-version-fallback.t b/tests/test-dirstate-version-fallback.t --- a/tests/test-dirstate-version-fallback.t +++ b/tests/test-dirstate-version-fallback.t @@ -10,8 +10,8 @@ Set up a v1 repo $ 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*