diff --git a/mercurial/revlogutils/nodemap.py b/mercurial/revlogutils/nodemap.py --- a/mercurial/revlogutils/nodemap.py +++ b/mercurial/revlogutils/nodemap.py @@ -128,15 +128,20 @@ def update_persistent_nodemap(revlog): notr._postclose[k](None) -def persist_nodemap(tr, revlog, pending=False): +def persist_nodemap(tr, revlog, pending=False, force=False): """Write nodemap data on disk for a given revlog""" if getattr(revlog, 'filteredrevs', ()): raise error.ProgrammingError( "cannot persist nodemap of a filtered changelog" ) if revlog.nodemap_file is None: - msg = "calling persist nodemap on a revlog without the feature enabled" - raise error.ProgrammingError(msg) + if force: + revlog.nodemap_file = get_nodemap_file( + revlog.opener, revlog.indexfile + ) + else: + msg = "calling persist nodemap on a revlog without the feature enabled" + raise error.ProgrammingError(msg) can_incremental = util.safehasattr(revlog.index, "nodemap_data_incremental") ondisk_docket = revlog._nodemap_docket diff --git a/mercurial/upgrade_utils/engine.py b/mercurial/upgrade_utils/engine.py --- a/mercurial/upgrade_utils/engine.py +++ b/mercurial/upgrade_utils/engine.py @@ -24,6 +24,7 @@ from .. import ( util, vfs as vfsmod, ) +from ..revlogutils import nodemap def _revlogfrompath(repo, path): @@ -452,6 +453,22 @@ def upgrade(ui, srcrepo, dstrepo, upgrad if upgrade_op.requirements_only: ui.status(_(b'upgrading repository requirements\n')) scmutil.writereporequirements(srcrepo, upgrade_op.new_requirements) + # if there is only one action and that is persistent nodemap upgrade + # directly write the nodemap file and update requirements instead of going + # through the whole cloning process + elif ( + len(upgrade_op.upgrade_actions) == 1 + and b'persistent-nodemap' in upgrade_op._upgrade_actions_names + and not upgrade_op.removed_actions + ): + ui.status( + _(b'upgrading repository to use persistent nodemap feature\n') + ) + with srcrepo.transaction(b'upgrade') as tr: + unfi = srcrepo.unfiltered() + cl = unfi.changelog + nodemap.persist_nodemap(tr, cl, force=True) + scmutil.writereporequirements(srcrepo, upgrade_op.new_requirements) else: with dstrepo.transaction(b'upgrade') as tr: _clonerevlogs( diff --git a/tests/test-persistent-nodemap.t b/tests/test-persistent-nodemap.t --- a/tests/test-persistent-nodemap.t +++ b/tests/test-persistent-nodemap.t @@ -636,28 +636,11 @@ upgrading repository locked and read-only creating temporary repository to stage upgraded data: $TESTTMP/test-repo/.hg/upgrade.* (glob) (it is safe to interrupt this process any time before data migration completes) - migrating 15018 total revisions (5006 in filelogs, 5006 in manifests, 5006 in changelog) - migrating 1.74 MB in store; 569 MB tracked data - migrating 5004 filelogs containing 5006 revisions (346 KB in store; 28.2 KB tracked data) - finished migrating 5006 filelog revisions across 5004 filelogs; change in size: 0 bytes - migrating 1 manifests containing 5006 revisions (765 KB in store; 569 MB tracked data) - finished migrating 5006 manifest revisions across 1 manifests; change in size: 0 bytes - migrating changelog containing 5006 revisions (673 KB in store; 363 KB tracked data) - finished migrating 5006 changelog revisions; change in size: 0 bytes - finished migrating 15018 total revisions; total change in store size: 0 bytes - copying phaseroots - data fully upgraded in a temporary repository - marking source repository as being upgraded; clients will be unable to read from repository - starting in-place swap of repository data - replacing store... - store replacement complete; repository was inconsistent for *s (glob) - finalizing requirements file and making repository readable again + upgrading repository to use persistent nodemap feature removing temporary repository $TESTTMP/test-repo/.hg/upgrade.* (glob) $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)' 00changelog-*.nd (glob) 00changelog.n - 00manifest-*.nd (glob) - 00manifest.n $ hg debugnodemap --metadata uid: * (glob)