# HG changeset patch # User Pierre-Yves David # Date 1638781684 -3600 # Node ID 6e4999cb085e5597e1dd19cda42b1b21664876cf # Parent 25c352b58b4e54c6892695e9948b3a6d5da4a122 dirstate-v2: fix upgrade on an empty repository This used to crash as the dirstate file does not exist in this case. Differential Revision: https://phab.mercurial-scm.org/D11866 diff -r 25c352b58b4e -r 6e4999cb085e mercurial/upgrade_utils/engine.py --- a/mercurial/upgrade_utils/engine.py Mon Dec 06 10:52:40 2021 +0100 +++ b/mercurial/upgrade_utils/engine.py Mon Dec 06 10:08:04 2021 +0100 @@ -7,6 +7,7 @@ from __future__ import absolute_import +import errno import stat from ..i18n import _ @@ -633,16 +634,29 @@ util.copyfile( srcrepo.vfs.join(b'requires'), backupvfs.join(b'requires') ) - util.copyfile( - srcrepo.vfs.join(b'dirstate'), backupvfs.join(b'dirstate') - ) + try: + util.copyfile( + srcrepo.vfs.join(b'dirstate'), backupvfs.join(b'dirstate') + ) + except (IOError, OSError) as e: + # The dirstate does not exist on an empty repo or a repo with no + # revision checked out + if e.errno != errno.ENOENT: + raise assert srcrepo.dirstate._use_dirstate_v2 == (old == b'v2') srcrepo.dirstate._map.preload() srcrepo.dirstate._use_dirstate_v2 = new == b'v2' srcrepo.dirstate._map._use_dirstate_v2 = srcrepo.dirstate._use_dirstate_v2 srcrepo.dirstate._dirty = True - srcrepo.vfs.unlink(b'dirstate') + try: + srcrepo.vfs.unlink(b'dirstate') + except (IOError, OSError) as e: + # The dirstate does not exist on an empty repo or a repo with no + # revision checked out + if e.errno != errno.ENOENT: + raise + srcrepo.dirstate.write(None) scmutil.writereporequirements(srcrepo, upgrade_op.new_requirements) diff -r 25c352b58b4e -r 6e4999cb085e tests/test-upgrade-repo.t --- a/tests/test-upgrade-repo.t Mon Dec 06 10:52:40 2021 +0100 +++ b/tests/test-upgrade-repo.t Mon Dec 06 10:08:04 2021 +0100 @@ -1701,3 +1701,66 @@ $ hg debugformat -v | grep dirstate-v2 dirstate-v2: no no no $ hg status + + $ cd .. + +dirstate-v2: upgrade and downgrade from and empty repository: +------------------------------------------------------------- + + $ hg init --config format.exp-rc-dirstate-v2=no dirstate-v2-empty + $ cd dirstate-v2-empty + $ hg debugformat | grep dirstate-v2 + dirstate-v2: no + +upgrade + + $ hg debugupgraderepo --run --config format.exp-rc-dirstate-v2=yes + upgrade will perform the following actions: + + requirements + preserved: * (glob) + added: dirstate-v2 + + dirstate-v2 + "hg status" will be faster + + processed revlogs: + - all-filelogs + - changelog + - manifest + + beginning upgrade... + repository locked and read-only + creating temporary repository to stage upgraded data: $TESTTMP/dirstate-v2-empty/.hg/upgrade.* (glob) + (it is safe to interrupt this process any time before data migration completes) + upgrading to dirstate-v2 from v1 + replaced files will be backed up at $TESTTMP/dirstate-v2-empty/.hg/upgradebackup.* (glob) + removing temporary repository $TESTTMP/dirstate-v2-empty/.hg/upgrade.* (glob) + $ hg debugformat | grep dirstate-v2 + dirstate-v2: yes + +downgrade + + $ hg debugupgraderepo --run --config format.exp-rc-dirstate-v2=no + upgrade will perform the following actions: + + requirements + preserved: * (glob) + removed: dirstate-v2 + + processed revlogs: + - all-filelogs + - changelog + - manifest + + beginning upgrade... + repository locked and read-only + creating temporary repository to stage upgraded data: $TESTTMP/dirstate-v2-empty/.hg/upgrade.* (glob) + (it is safe to interrupt this process any time before data migration completes) + downgrading from dirstate-v2 to v1 + replaced files will be backed up at $TESTTMP/dirstate-v2-empty/.hg/upgradebackup.* (glob) + removing temporary repository $TESTTMP/dirstate-v2-empty/.hg/upgrade.* (glob) + $ hg debugformat | grep dirstate-v2 + dirstate-v2: no + + $ cd ..