changeset 50256:a6e0b7d4ae9d

dirstate: write the `branch` as part of the transaction if any Bypassing the transaction means we could get out of sync with the dirstatemap content. The branch is stil written right away if no transaction is around, but at least it no longer bypass the transaction. Actual caller of this still need to be updated.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Thu, 02 Mar 2023 11:47:18 +0100
parents fa04407bda7a
children a301f0fad046
files hgext/git/dirstate.py mercurial/dirstate.py mercurial/interfaces/dirstate.py
diffstat 3 files changed, 29 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/git/dirstate.py	Thu Mar 02 11:46:51 2023 +0100
+++ b/hgext/git/dirstate.py	Thu Mar 02 11:47:18 2023 +0100
@@ -389,7 +389,7 @@
         # TODO: should this be added to the dirstate interface?
         self._plchangecallbacks[category] = callback
 
-    def setbranch(self, branch):
+    def setbranch(self, branch, transaction=None):
         raise error.Abort(
             b'git repos do not support branches. try using bookmarks'
         )
--- a/mercurial/dirstate.py	Thu Mar 02 11:46:51 2023 +0100
+++ b/mercurial/dirstate.py	Thu Mar 02 11:47:18 2023 +0100
@@ -27,6 +27,7 @@
     policy,
     pycompat,
     scmutil,
+    txnutil,
     util,
 )
 
@@ -416,10 +417,19 @@
 
     @repocache(b'branch')
     def _branch(self):
+        f = None
+        data = b''
         try:
-            return self._opener.read(b"branch").strip() or b"default"
+            f, mode = txnutil.trypending(self._root, self._opener, b'branch')
+            data = f.read().strip()
         except FileNotFoundError:
+            pass
+        finally:
+            if f is not None:
+                f.close()
+        if not data:
             return b"default"
+        return data
 
     @property
     def _pl(self):
@@ -611,11 +621,22 @@
         fold_p2 = oldp2 != nullid and p2 == nullid
         return self._map.setparents(p1, p2, fold_p2=fold_p2)
 
-    def setbranch(self, branch):
+    def setbranch(self, branch, transaction=None):
         self.__class__._branch.set(self, encoding.fromlocal(branch))
+        if transaction is not None:
+            self._setup_tr_abort(transaction)
+            transaction.addfilegenerator(
+                b'dirstate-3-branch%s' % self._tr_key_suffix,
+                (b'branch',),
+                self._write_branch,
+                location=b'plain',
+                post_finalize=True,
+            )
+            return
+
         vfs = self._opener
         with vfs(b'branch', b'w', atomictemp=True, checkambig=True) as f:
-            f.write(self._branch + b'\n')
+            self._write_branch(f)
             # make sure filecache has the correct stat info for _branch after
             # replacing the underlying file
             #
@@ -625,6 +646,9 @@
             if ce:
                 ce.refresh()
 
+    def _write_branch(self, file_obj):
+        file_obj.write(self._branch + b'\n')
+
     def invalidate(self):
         """Causes the next access to reread the dirstate.
 
--- a/mercurial/interfaces/dirstate.py	Thu Mar 02 11:46:51 2023 +0100
+++ b/mercurial/interfaces/dirstate.py	Thu Mar 02 11:47:18 2023 +0100
@@ -123,7 +123,7 @@
         See localrepo.setparents()
         """
 
-    def setbranch(branch):
+    def setbranch(branch, transaction=None):
         pass
 
     def invalidate():