Patchwork D9936: upgrade: implement partial upgrade for upgrading persistent-nodemap

mail settings
Submitter phabricator
Date Jan. 31, 2021, 7:35 p.m.
Message ID <>
Download mbox | patch
Permalink /patch/48247/
State Superseded
Headers show


phabricator - Jan. 31, 2021, 7:35 p.m.
pulkit created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

  Upgrading repositories to use persistent nodemap should be fast and easy as it
  requires only two things:
  1. Updating the requirements
  2. Writing a persistent-nodemap on disk
  For both of the steps above, we don't need to edit existing revlogs.
  This patch makes upgrade only do the above mentioned two steps if we are
  only upgarding to use persistent-nodemap feature.
  Since `nodemap.persist_nodemap()` assumes that there exists a nodemap file for
  the given revlog if we are trying to call it, this patch adds `force` argument
  to create a file if does not exist which is true in our upgrade case.
  The test changes demonstrate that we no longer write nodemap files for manifest
  after upgrade which I think is desirable.

  rHG Mercurial





To: pulkit, #hg-reviewers
Cc: mercurial-patches, mercurial-devel


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 @@ 
   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)
-  00manifest-*.nd (glob)
-  00manifest.n
   $ hg debugnodemap --metadata
   uid: * (glob)
diff --git a/mercurial/upgrade_utils/ b/mercurial/upgrade_utils/
--- a/mercurial/upgrade_utils/
+++ b/mercurial/upgrade_utils/
@@ -24,6 +24,7 @@ 
     vfs as vfsmod,
+from ..revlogutils import nodemap
 def _revlogfrompath(repo, path):
@@ -452,6 +453,22 @@ 
     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)
         with dstrepo.transaction(b'upgrade') as tr:
diff --git a/mercurial/revlogutils/ b/mercurial/revlogutils/
--- a/mercurial/revlogutils/
+++ b/mercurial/revlogutils/
@@ -128,15 +128,20 @@ 
-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