undo-files: have the transaction directly tracks and manages journal rename stable
authorPierre-Yves David <pierre-yves.david@octobus.net>
Mon, 06 Mar 2023 19:22:34 +0100
branchstable
changeset 50297 a43f0562220c
parent 50296 dda43856ef96
child 50298 473103758373
undo-files: have the transaction directly tracks and manages journal rename This is much simpler this way.
mercurial/localrepo.py
mercurial/transaction.py
--- a/mercurial/localrepo.py	Mon Mar 06 19:19:27 2023 +0100
+++ b/mercurial/localrepo.py	Mon Mar 06 19:22:34 2023 +0100
@@ -2583,6 +2583,8 @@
             checkambigfiles=_cachedfiles,
             name=desc,
         )
+        for vfs_id, path in self._journalfiles():
+            tr.add_journal(vfs_id, path)
         tr.changes[b'origrepolen'] = len(self)
         tr.changes[b'obsmarkers'] = set()
         tr.changes[b'phases'] = []
--- a/mercurial/transaction.py	Mon Mar 06 19:19:27 2023 +0100
+++ b/mercurial/transaction.py	Mon Mar 06 19:22:34 2023 +0100
@@ -153,6 +153,7 @@
         self._offsetmap = {}
         self._newfiles = set()
         self._journal = journalname
+        self._journal_files = []
         self._undoname = undoname
         self._queue = []
         # A callback to do something just after releasing transaction.
@@ -633,6 +634,10 @@
         scope)"""
         self._abort()
 
+    @active
+    def add_journal(self, vfs_id, path):
+        self._journal_files.append((vfs_id, path))
+
     def _writeundo(self):
         """write transaction data for possible future undo call"""
         if self._undoname is None:
@@ -664,6 +669,16 @@
                 util.copyfile(vfs.join(b), vfs.join(u), hardlink=True)
             undobackupfile.write(b"%s\0%s\0%s\0%d\n" % (l, f, u, c))
         undobackupfile.close()
+        for vfs, src in self._journal_files:
+            dest = undoname(src)
+            # if src and dest refer to a same file, vfs.rename is a no-op,
+            # leaving both src and dest on disk. delete dest to make sure
+            # the rename couldn't be such a no-op.
+            vfs.tryunlink(dest)
+            try:
+                vfs.rename(src, dest)
+            except FileNotFoundError:  # journal file does not yet exist
+                pass
 
     def _abort(self):
         entries = self.readjournal()