comparison mercurial/context.py @ 32772:dc7efa2826e4

context: avoid writing outdated dirstate out (issue5584) Before this patch, workingctx.status() may cause writing outdated dirstate out, if: - .hg/dirstate is changed simultaneously after last loading it, - there is any file, which should be dirstate.normal()-ed Typical issue case is: - the working directory is updated by "hg update" - .hg/dirstate is updated in background (e.g. fsmonitor) This patch compares identities of dirstate before and after acquisition of wlock, and avoids writing outdated dirstate out, if change of .hg/dirstate is detected.
author FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
date Fri, 09 Jun 2017 13:07:49 +0900
parents 3e8eb6d84a5c
children 34be21aa2b26
comparison
equal deleted inserted replaced
32771:627eaab1ad07 32772:dc7efa2826e4
1757 deleted.append(f) 1757 deleted.append(f)
1758 1758
1759 # update dirstate for files that are actually clean 1759 # update dirstate for files that are actually clean
1760 if fixup: 1760 if fixup:
1761 try: 1761 try:
1762 oldid = self._repo.dirstate.identity()
1763
1762 # updating the dirstate is optional 1764 # updating the dirstate is optional
1763 # so we don't wait on the lock 1765 # so we don't wait on the lock
1764 # wlock can invalidate the dirstate, so cache normal _after_ 1766 # wlock can invalidate the dirstate, so cache normal _after_
1765 # taking the lock 1767 # taking the lock
1766 with self._repo.wlock(False): 1768 with self._repo.wlock(False):
1767 normal = self._repo.dirstate.normal 1769 if self._repo.dirstate.identity() == oldid:
1768 for f in fixup: 1770 normal = self._repo.dirstate.normal
1769 normal(f) 1771 for f in fixup:
1770 # write changes out explicitly, because nesting 1772 normal(f)
1771 # wlock at runtime may prevent 'wlock.release()' 1773 # write changes out explicitly, because nesting
1772 # after this block from doing so for subsequent 1774 # wlock at runtime may prevent 'wlock.release()'
1773 # changing files 1775 # after this block from doing so for subsequent
1774 self._repo.dirstate.write(self._repo.currenttransaction()) 1776 # changing files
1777 tr = self._repo.currenttransaction()
1778 self._repo.dirstate.write(tr)
1779 else:
1780 # in this case, writing changes out breaks
1781 # consistency, because .hg/dirstate was
1782 # already changed simultaneously after last
1783 # caching (see also issue5584 for detail)
1784 self._repo.ui.debug('skip updating dirstate: '
1785 'identity mismatch\n')
1775 except error.LockError: 1786 except error.LockError:
1776 pass 1787 pass
1777 return modified, deleted, fixup 1788 return modified, deleted, fixup
1778 1789
1779 def _dirstatestatus(self, match=None, ignored=False, clean=False, 1790 def _dirstatestatus(self, match=None, ignored=False, clean=False,