comparison mercurial/context.py @ 50130: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 1f369ca9e34c
children e5f5f1c1c452
comparison
equal deleted inserted replaced
50129:3c6546b149ed 50130:9e1debbb477e
1852 1852
1853 return modified, deleted, clean, fixup 1853 return modified, deleted, clean, fixup
1854 1854
1855 def _poststatusfixup(self, status, fixup): 1855 def _poststatusfixup(self, status, fixup):
1856 """update dirstate for files that are actually clean""" 1856 """update dirstate for files that are actually clean"""
1857 dirstate = self._repo.dirstate
1857 poststatus = self._repo.postdsstatus() 1858 poststatus = self._repo.postdsstatus()
1858 if fixup or poststatus or self._repo.dirstate._dirty: 1859 if fixup:
1860 if dirstate.is_changing_parents:
1861 normal = lambda f, pfd: dirstate.update_file(
1862 f,
1863 p1_tracked=True,
1864 wc_tracked=True,
1865 )
1866 else:
1867 normal = dirstate.set_clean
1868 for f, pdf in fixup:
1869 normal(f, pdf)
1870 if poststatus or self._repo.dirstate._dirty:
1859 try: 1871 try:
1860 oldid = self._repo.dirstate.identity()
1861
1862 # updating the dirstate is optional 1872 # updating the dirstate is optional
1863 # so we don't wait on the lock 1873 # so we don't wait on the lock
1864 # wlock can invalidate the dirstate, so cache normal _after_ 1874 # wlock can invalidate the dirstate, so cache normal _after_
1865 # taking the lock 1875 # taking the lock
1876 pre_dirty = dirstate._dirty
1866 with self._repo.wlock(False): 1877 with self._repo.wlock(False):
1867 dirstate = self._repo.dirstate 1878 assert self._repo.dirstate is dirstate
1868 if dirstate.identity() == oldid: 1879 post_dirty = dirstate._dirty
1869 if fixup: 1880 if post_dirty:
1870 if dirstate.is_changing_parents:
1871 normal = lambda f, pfd: dirstate.update_file(
1872 f, p1_tracked=True, wc_tracked=True
1873 )
1874 else:
1875 normal = dirstate.set_clean
1876 for f, pdf in fixup:
1877 normal(f, pdf)
1878 # write changes out explicitly, because nesting
1879 # wlock at runtime may prevent 'wlock.release()'
1880 # after this block from doing so for subsequent
1881 # changing files
1882 #
1883 # (This is outside of the (if fixup) block because the
1884 # status operation itself might have updated some cache
1885 # information before.)
1886 tr = self._repo.currenttransaction() 1881 tr = self._repo.currenttransaction()
1887 self._repo.dirstate.write(tr) 1882 dirstate.write(tr)
1888 1883 elif pre_dirty:
1889 if poststatus: 1884 # the wlock grabbing detected that dirtate changes
1890 for ps in poststatus: 1885 # needed to be dropped
1891 ps(self, status) 1886 m = b'skip updating dirstate: identity mismatch\n'
1892 else: 1887 self._repo.ui.debug(m)
1893 # in this case, writing changes out breaks 1888 if poststatus:
1894 # consistency, because .hg/dirstate was 1889 for ps in poststatus:
1895 # already changed simultaneously after last 1890 ps(self, status)
1896 # caching (see also issue5584 for detail)
1897 self._repo.ui.debug(
1898 b'skip updating dirstate: identity mismatch\n'
1899 )
1900 # throw away anything we have.
1901 dirstate.invalidate()
1902 except error.LockError: 1891 except error.LockError:
1903 pass 1892 pass
1904 finally: 1893 finally:
1905 # Even if the wlock couldn't be grabbed, clear out the list. 1894 # Even if the wlock couldn't be grabbed, clear out the list.
1906 self._repo.clearpostdsstatus() 1895 self._repo.clearpostdsstatus()