changeset 50134:acd2a0267660

dirstate: simplify the shelve hack to not go through the disk We already have the data in memory, so why not simply keep the data in memory? This avoid abusing the `savebackup/restorebackup` logic and will make our life easier.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Thu, 16 Feb 2023 03:08:00 +0100
parents 605f0ccffb43
children 2a46555c5522
files mercurial/shelve.py
diffstat 1 files changed, 20 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/shelve.py	Thu Feb 16 02:44:07 2023 +0100
+++ b/mercurial/shelve.py	Thu Feb 16 03:08:00 2023 +0100
@@ -432,10 +432,26 @@
 
 def _aborttransaction(repo, tr):
     """Abort current transaction for shelve/unshelve, but keep dirstate"""
-    dirstatebackupname = b'dirstate.shelve'
-    repo.dirstate.savebackup(None, dirstatebackupname)
-    tr.abort()
-    repo.dirstate.restorebackup(None, dirstatebackupname)
+    # disable the transaction invalidation of the dirstate, to preserve the
+    # current change in memory.
+    ds = repo.dirstate
+    # The assert below check that nobody else did such wrapping.
+    #
+    # These is not such other wrapping currently, but if someone try to
+    # implement one in the future, this will explicitly break here instead of
+    # misbehaving in subtle ways.
+    assert 'invalidate' not in vars(ds)
+    try:
+        # note : we could simply disable the transaction abort callback, but
+        # other code also tries to rollback and invalidate this.
+        ds.invalidate = lambda: None
+        tr.abort()
+    finally:
+        del ds.invalidate
+    # manually write the change in memory since we can no longer rely on the
+    # transaction to do so.
+    assert repo.currenttransaction() is None
+    repo.dirstate.write(None)
 
 
 def getshelvename(repo, parent, opts):