Mercurial > hg
diff hgext/fsmonitor/__init__.py @ 35313:c67fb3bfe3a1
fsmonitor: fsmonitor should send wlock notifications to watchman
The fsmonitor extension should send state-enter and state-leave
notifications to watchman when the wlock is acquired/release, respectively.
This will allow watchman and watchman subscribers to customize behavior based
on whether source control operations are occurring.
Test Plan:
Tested checkout, update and working copy changes with extension enabled.
Differential Revision: https://phab.mercurial-scm.org/D1612
author | Eamonn Kent <ekent@fb.com> |
---|---|
date | Wed, 06 Dec 2017 18:37:49 -0800 |
parents | 73abb81ccb28 |
children | 6b1a8c396b05 |
line wrap: on
line diff
--- a/hgext/fsmonitor/__init__.py Wed Dec 06 18:37:49 2017 -0800 +++ b/hgext/fsmonitor/__init__.py Wed Dec 06 18:37:49 2017 -0800 @@ -161,6 +161,9 @@ configitem('fsmonitor', 'blacklistusers', default=list, ) +configitem('experimental', 'fsmonitor.transaction_notify', + default=False, +) # This extension is incompatible with the following blacklisted extensions # and will disable itself when encountering one of these: @@ -656,14 +659,18 @@ self.enter() def enter(self): - # We explicitly need to take a lock here, before we proceed to update - # watchman about the update operation, so that we don't race with - # some other actor. merge.update is going to take the wlock almost - # immediately anyway, so this is effectively extending the lock - # around a couple of short sanity checks. + # Make sure we have a wlock prior to sending notifications to watchman. + # We don't want to race with other actors. In the update case, + # merge.update is going to take the wlock almost immediately. We are + # effectively extending the lock around several short sanity checks. if self.oldnode is None: self.oldnode = self.repo['.'].node() - self._lock = self.repo.wlock() + + if self.repo.currentwlock() is None: + if util.safehasattr(self.repo, 'wlocknostateupdate'): + self._lock = self.repo.wlocknostateupdate() + else: + self._lock = self.repo.wlock() self.need_leave = self._state( 'state-enter', hex(self.oldnode)) @@ -784,4 +791,34 @@ orig = super(fsmonitorrepo, self).status return overridestatus(orig, self, *args, **kwargs) + def wlocknostateupdate(self, *args, **kwargs): + return super(fsmonitorrepo, self).wlock(*args, **kwargs) + + def wlock(self, *args, **kwargs): + l = super(fsmonitorrepo, self).wlock(*args, **kwargs) + if not ui.configbool( + "experimental", "fsmonitor.transaction_notify"): + return l + if l.held != 1: + return l + origrelease = l.releasefn + + def staterelease(): + if origrelease: + origrelease() + if l.stateupdate: + l.stateupdate.exit() + l.stateupdate = None + + try: + l.stateupdate = None + l.stateupdate = state_update(self, name="hg.transaction") + l.stateupdate.enter() + l.releasefn = staterelease + except Exception as e: + # Swallow any errors; fire and forget + self.ui.log( + 'watchman', 'Exception in state update %s\n', e) + return l + repo.__class__ = fsmonitorrepo