Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/context.py @ 32833:2083d1643d69
workingctx: add a way for extensions to run code at status fixup time
Some extensions like fsmonitor need to run code after dirstate.status is
called, but while the wlock is held. The extensions could grab the wlock again,
but that has its own peculiar race issues. For example, fsmonitor would not
like its state to be written out if the dirstate has changed underneath (see
issue5581 for what can go wrong in that sort of case).
To protect against these sorts of issues, allow extensions to declare that they
would like to run some code to run at fixup time.
fsmonitor will switch to using this in the next patch in the series.
author | Siddharth Agarwal <sid0@fb.com> |
---|---|
date | Mon, 12 Jun 2017 13:56:50 -0700 |
parents | 6d73b7ff8f92 |
children | 582080a4a812 |
comparison
equal
deleted
inserted
replaced
32832:6d73b7ff8f92 | 32833:2083d1643d69 |
---|---|
1740 | 1740 |
1741 return modified, deleted, fixup | 1741 return modified, deleted, fixup |
1742 | 1742 |
1743 def _poststatusfixup(self, status, fixup): | 1743 def _poststatusfixup(self, status, fixup): |
1744 """update dirstate for files that are actually clean""" | 1744 """update dirstate for files that are actually clean""" |
1745 if fixup: | 1745 poststatus = self._repo.postdsstatus() |
1746 if fixup or poststatus: | |
1746 try: | 1747 try: |
1747 oldid = self._repo.dirstate.identity() | 1748 oldid = self._repo.dirstate.identity() |
1748 | 1749 |
1749 # updating the dirstate is optional | 1750 # updating the dirstate is optional |
1750 # so we don't wait on the lock | 1751 # so we don't wait on the lock |
1751 # wlock can invalidate the dirstate, so cache normal _after_ | 1752 # wlock can invalidate the dirstate, so cache normal _after_ |
1752 # taking the lock | 1753 # taking the lock |
1753 with self._repo.wlock(False): | 1754 with self._repo.wlock(False): |
1754 if self._repo.dirstate.identity() == oldid: | 1755 if self._repo.dirstate.identity() == oldid: |
1755 normal = self._repo.dirstate.normal | 1756 if fixup: |
1756 for f in fixup: | 1757 normal = self._repo.dirstate.normal |
1757 normal(f) | 1758 for f in fixup: |
1758 # write changes out explicitly, because nesting | 1759 normal(f) |
1759 # wlock at runtime may prevent 'wlock.release()' | 1760 # write changes out explicitly, because nesting |
1760 # after this block from doing so for subsequent | 1761 # wlock at runtime may prevent 'wlock.release()' |
1761 # changing files | 1762 # after this block from doing so for subsequent |
1762 tr = self._repo.currenttransaction() | 1763 # changing files |
1763 self._repo.dirstate.write(tr) | 1764 tr = self._repo.currenttransaction() |
1765 self._repo.dirstate.write(tr) | |
1766 | |
1767 if poststatus: | |
1768 for ps in poststatus: | |
1769 ps(self, status) | |
1764 else: | 1770 else: |
1765 # in this case, writing changes out breaks | 1771 # in this case, writing changes out breaks |
1766 # consistency, because .hg/dirstate was | 1772 # consistency, because .hg/dirstate was |
1767 # already changed simultaneously after last | 1773 # already changed simultaneously after last |
1768 # caching (see also issue5584 for detail) | 1774 # caching (see also issue5584 for detail) |
1769 self._repo.ui.debug('skip updating dirstate: ' | 1775 self._repo.ui.debug('skip updating dirstate: ' |
1770 'identity mismatch\n') | 1776 'identity mismatch\n') |
1771 except error.LockError: | 1777 except error.LockError: |
1772 pass | 1778 pass |
1779 finally: | |
1780 # Even if the wlock couldn't be grabbed, clear out the list. | |
1781 self._repo.clearpostdsstatus() | |
1773 | 1782 |
1774 def _dirstatestatus(self, match=None, ignored=False, clean=False, | 1783 def _dirstatestatus(self, match=None, ignored=False, clean=False, |
1775 unknown=False): | 1784 unknown=False): |
1776 '''Gets the status from the dirstate -- internal use only.''' | 1785 '''Gets the status from the dirstate -- internal use only.''' |
1777 listignored, listclean, listunknown = ignored, clean, unknown | 1786 listignored, listclean, listunknown = ignored, clean, unknown |