changeset 50179:9e1debbb477e

status: simplify the post status fixup phases With the wlock automatically discarding changes when applicable, we can simplify the code a bit. * we perform the fixup operation before trying to grab the lock to narrow the `try/except` * we no longer need to explicitly complare dirstate identities. We can trust the dirstate internal refresh for that. It would invalidate dirty data when needed. * detect still data invalidation by checking the dirty flag before and after taking the lock. Doing this is actually only necessary to issue the debug message, we could blindy trust the dirstate internal to ignore the `write` call on a non-dirty dirstate.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Tue, 21 Feb 2023 16:20:11 +0100
parents 3c6546b149ed
children e5f5f1c1c452
files mercurial/context.py
diffstat 1 files changed, 26 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/context.py	Tue Feb 21 15:35:31 2023 +0100
+++ b/mercurial/context.py	Tue Feb 21 16:20:11 2023 +0100
@@ -1854,51 +1854,40 @@
 
     def _poststatusfixup(self, status, fixup):
         """update dirstate for files that are actually clean"""
+        dirstate = self._repo.dirstate
         poststatus = self._repo.postdsstatus()
-        if fixup or poststatus or self._repo.dirstate._dirty:
+        if fixup:
+            if dirstate.is_changing_parents:
+                normal = lambda f, pfd: dirstate.update_file(
+                    f,
+                    p1_tracked=True,
+                    wc_tracked=True,
+                )
+            else:
+                normal = dirstate.set_clean
+            for f, pdf in fixup:
+                normal(f, pdf)
+        if poststatus or self._repo.dirstate._dirty:
             try:
-                oldid = self._repo.dirstate.identity()
-
                 # updating the dirstate is optional
                 # so we don't wait on the lock
                 # wlock can invalidate the dirstate, so cache normal _after_
                 # taking the lock
+                pre_dirty = dirstate._dirty
                 with self._repo.wlock(False):
-                    dirstate = self._repo.dirstate
-                    if dirstate.identity() == oldid:
-                        if fixup:
-                            if dirstate.is_changing_parents:
-                                normal = lambda f, pfd: dirstate.update_file(
-                                    f, p1_tracked=True, wc_tracked=True
-                                )
-                            else:
-                                normal = dirstate.set_clean
-                            for f, pdf in fixup:
-                                normal(f, pdf)
-                        # write changes out explicitly, because nesting
-                        # wlock at runtime may prevent 'wlock.release()'
-                        # after this block from doing so for subsequent
-                        # changing files
-                        #
-                        # (This is outside of the (if fixup) block because the
-                        # status operation itself might have updated some cache
-                        # information before.)
+                    assert self._repo.dirstate is dirstate
+                    post_dirty = dirstate._dirty
+                    if post_dirty:
                         tr = self._repo.currenttransaction()
-                        self._repo.dirstate.write(tr)
-
-                        if poststatus:
-                            for ps in poststatus:
-                                ps(self, status)
-                    else:
-                        # in this case, writing changes out breaks
-                        # consistency, because .hg/dirstate was
-                        # already changed simultaneously after last
-                        # caching (see also issue5584 for detail)
-                        self._repo.ui.debug(
-                            b'skip updating dirstate: identity mismatch\n'
-                        )
-                        # throw away anything we have.
-                        dirstate.invalidate()
+                        dirstate.write(tr)
+                    elif pre_dirty:
+                        # the wlock grabbing detected that dirtate changes
+                        # needed to be dropped
+                        m = b'skip updating dirstate: identity mismatch\n'
+                        self._repo.ui.debug(m)
+                    if poststatus:
+                        for ps in poststatus:
+                            ps(self, status)
             except error.LockError:
                 pass
             finally: