upgrade: implement partial upgrade for upgrading persistent-nodemap
authorPulkit Goyal <7895pulkit@gmail.com>
Mon, 01 Feb 2021 00:02:00 +0530
changeset 46472 98e39f04d60e
parent 46471 bfaacfa8ebfc
child 46473 d6e73351533b
upgrade: implement partial upgrade for upgrading persistent-nodemap 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. Differential Revision: https://phab.mercurial-scm.org/D9936
mercurial/revlogutils/nodemap.py
mercurial/upgrade_utils/engine.py
tests/test-persistent-nodemap.t
--- a/mercurial/revlogutils/nodemap.py	Mon Feb 01 00:10:27 2021 +0530
+++ b/mercurial/revlogutils/nodemap.py	Mon Feb 01 00:02:00 2021 +0530
@@ -128,15 +128,20 @@
         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
--- a/mercurial/upgrade_utils/engine.py	Mon Feb 01 00:10:27 2021 +0530
+++ b/mercurial/upgrade_utils/engine.py	Mon Feb 01 00:02:00 2021 +0530
@@ -24,6 +24,7 @@
     util,
     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)
     else:
         with dstrepo.transaction(b'upgrade') as tr:
             _clonerevlogs(
--- a/tests/test-persistent-nodemap.t	Mon Feb 01 00:10:27 2021 +0530
+++ b/tests/test-persistent-nodemap.t	Mon Feb 01 00:02:00 2021 +0530
@@ -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)
   00changelog.n
-  00manifest-*.nd (glob)
-  00manifest.n
 
   $ hg debugnodemap --metadata
   uid: * (glob)