changeset 44516:64e2f603de9d

nodemap: make sure hooks have access to an up-to-date version We make sure hooks can read persistent nodemap data and that they access something up-to-date with the pending transaction. Differential Revision: https://phab.mercurial-scm.org/D8187
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Fri, 28 Feb 2020 00:29:18 +0100
parents 6c906eaedd0d
children 448d700e0d27
files mercurial/configitems.py mercurial/revlog.py mercurial/revlogutils/nodemap.py tests/test-persistent-nodemap.t
diffstat 4 files changed, 56 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/configitems.py	Thu Feb 27 16:32:43 2020 +0100
+++ b/mercurial/configitems.py	Fri Feb 28 00:29:18 2020 +0100
@@ -408,7 +408,6 @@
 # TODO before getting `persistent-nodemap` out of experimental
 #
 # * code/tests around aborted transaction
-# * code/tests around pending data for hooks
 # * regenerate a new nodemap when the unused/total ration is to high
 # * decide for a "status" of the persistent nodemap and associated location
 #   - part of the store next the revlog itself (new requirements)
--- a/mercurial/revlog.py	Thu Feb 27 16:32:43 2020 +0100
+++ b/mercurial/revlog.py	Fri Feb 28 00:29:18 2020 +0100
@@ -436,7 +436,14 @@
         self.datafile = datafile or (indexfile[:-2] + b".d")
         self.nodemap_file = None
         if persistentnodemap:
-            self.nodemap_file = indexfile[:-2] + b".n"
+            if indexfile.endswith(b'.a'):
+                pending_path = indexfile[:-4] + b".n.a"
+                if opener.exists(pending_path):
+                    self.nodemap_file = pending_path
+                else:
+                    self.nodemap_file = indexfile[:-4] + b".n"
+            else:
+                self.nodemap_file = indexfile[:-2] + b".n"
 
         self.opener = opener
         #  When True, indexfile is opened with checkambig=True at writing, to
--- a/mercurial/revlogutils/nodemap.py	Thu Feb 27 16:32:43 2020 +0100
+++ b/mercurial/revlogutils/nodemap.py	Fri Feb 28 00:29:18 2020 +0100
@@ -75,6 +75,9 @@
     callback_id = b"revlog-persistent-nodemap-%s" % revlog.nodemap_file
     if tr.hasfinalize(callback_id):
         return  # no need to register again
+    tr.addpending(
+        callback_id, lambda tr: _persist_nodemap(tr, revlog, pending=True)
+    )
     tr.addfinalize(callback_id, lambda tr: _persist_nodemap(tr, revlog))
 
 
@@ -101,7 +104,7 @@
         notr._postclose[k](None)
 
 
-def _persist_nodemap(tr, revlog):
+def _persist_nodemap(tr, revlog, pending=False):
     """Write nodemap data on disk for a given revlog
     """
     if getattr(revlog, 'filteredrevs', ()):
@@ -169,7 +172,10 @@
     target_docket.tip_node = revlog.node(target_docket.tip_rev)
     # EXP-TODO: if this is a cache, this should use a cache vfs, not a
     # store vfs
-    with revlog.opener(revlog.nodemap_file, b'w', atomictemp=True) as fp:
+    file_path = revlog.nodemap_file
+    if pending:
+        file_path += b'.a'
+    with revlog.opener(file_path, b'w', atomictemp=True) as fp:
         fp.write(target_docket.serialize())
     revlog._nodemap_docket = target_docket
     if feed_data:
@@ -304,7 +310,10 @@
 
 def _rawdata_filepath(revlog, docket):
     """The (vfs relative) nodemap's rawdata file for a given uid"""
-    prefix = revlog.nodemap_file[:-2]
+    if revlog.nodemap_file.endswith(b'.n.a'):
+        prefix = revlog.nodemap_file[:-4]
+    else:
+        prefix = revlog.nodemap_file[:-2]
     return b"%s-%s.nd" % (prefix, docket.uid)
 
 
--- a/tests/test-persistent-nodemap.t	Thu Feb 27 16:32:43 2020 +0100
+++ b/tests/test-persistent-nodemap.t	Fri Feb 28 00:29:18 2020 +0100
@@ -281,3 +281,39 @@
   data-unused: 0
   $ hg log -r "$OTHERNODE" -T '{rev}\n'
   5002
+
+Check transaction related property
+==================================
+
+An up to date nodemap should be available to shell hooks,
+
+  $ echo dsljfl > a
+  $ hg add a
+  $ hg ci -m a
+  $ hg debugnodemap --metadata
+  uid: ???????????????? (glob)
+  tip-rev: 5003
+  tip-node: c91af76d172f1053cca41b83f7c2e4e514fe2bcf
+  data-length: 123008
+  data-unused: 0
+  $ echo babar2 > babar
+  $ hg ci -m 'babar2' --config "hooks.pretxnclose.nodemap-test=hg debugnodemap --metadata"
+  uid: ???????????????? (glob)
+  tip-rev: 5004
+  tip-node: ba87cd9559559e4b91b28cb140d003985315e031
+  data-length: 123328 (pure !)
+  data-length: 123328 (rust !)
+  data-length: 123136 (no-pure no-rust !)
+  data-unused: 192 (pure !)
+  data-unused: 192 (rust !)
+  data-unused: 0 (no-pure no-rust !)
+  $ hg debugnodemap --metadata
+  uid: ???????????????? (glob)
+  tip-rev: 5004
+  tip-node: ba87cd9559559e4b91b28cb140d003985315e031
+  data-length: 123328 (pure !)
+  data-length: 123328 (rust !)
+  data-length: 123136 (no-pure no-rust !)
+  data-unused: 192 (pure !)
+  data-unused: 192 (rust !)
+  data-unused: 0 (no-pure no-rust !)