Mercurial > hg
diff mercurial/context.py @ 32814: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 |
line wrap: on
line diff
--- a/mercurial/context.py Mon Jun 12 13:56:43 2017 -0700 +++ b/mercurial/context.py Mon Jun 12 13:56:50 2017 -0700 @@ -1742,7 +1742,8 @@ def _poststatusfixup(self, status, fixup): """update dirstate for files that are actually clean""" - if fixup: + poststatus = self._repo.postdsstatus() + if fixup or poststatus: try: oldid = self._repo.dirstate.identity() @@ -1752,15 +1753,20 @@ # taking the lock with self._repo.wlock(False): if self._repo.dirstate.identity() == oldid: - normal = self._repo.dirstate.normal - for f in fixup: - normal(f) - # write changes out explicitly, because nesting - # wlock at runtime may prevent 'wlock.release()' - # after this block from doing so for subsequent - # changing files - tr = self._repo.currenttransaction() - self._repo.dirstate.write(tr) + if fixup: + normal = self._repo.dirstate.normal + for f in fixup: + normal(f) + # write changes out explicitly, because nesting + # wlock at runtime may prevent 'wlock.release()' + # after this block from doing so for subsequent + # changing files + 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 @@ -1770,6 +1776,9 @@ 'identity mismatch\n') except error.LockError: pass + finally: + # Even if the wlock couldn't be grabbed, clear out the list. + self._repo.clearpostdsstatus() def _dirstatestatus(self, match=None, ignored=False, clean=False, unknown=False):