Comments
Patch
@@ -13,7 +13,10 @@ import socket
import struct
from mercurial.i18n import _
-from mercurial import pathutil
+from mercurial import (
+ pathutil,
+ util,
+)
_version = 4
_versionformat = ">I"
@@ -24,6 +27,7 @@ class state(object):
self._ui = repo.ui
self._rootdir = pathutil.normasprefix(repo.root)
self._lastclock = None
+ self._identity = util.filestat(None)
self.mode = self._ui.config('fsmonitor', 'mode', default='on')
self.walk_on_invalidate = self._ui.configbool(
@@ -35,10 +39,13 @@ class state(object):
try:
file = self._vfs('fsmonitor.state', 'rb')
except IOError as inst:
+ self._identity = util.filestat(None)
if inst.errno != errno.ENOENT:
raise
return None, None, None
+ self._identity = util.filestat.fromfp(file)
+
versionbytes = file.read(4)
if len(versionbytes) < 4:
self._ui.log(
@@ -90,8 +97,18 @@ class state(object):
self.invalidate()
return
+ # Read the identity from the file on disk rather than from the open file
+ # pointer below, because the latter is actually a brand new file.
+ identity = util.filestat.frompath(self._vfs.join('fsmonitor.state'))
+ if identity != self._identity:
+ self._ui.debug('skip updating fsmonitor.state: identity mismatch\n')
+ return
+ else:
+ self._ui.debug('identity new: %s %s old: %s %s' % (identity, identity.stat, self._identity, self._identity.stat))
+
try:
- file = self._vfs('fsmonitor.state', 'wb', atomictemp=True)
+ file = self._vfs('fsmonitor.state', 'wb', atomictemp=True,
+ checkambig=True)
except (IOError, OSError):
self._ui.warn(_("warning: unable to write out fsmonitor state\n"))
return
@@ -111,6 +128,7 @@ class state(object):
except OSError as inst:
if inst.errno != errno.ENOENT:
raise
+ self._identity = util.filestat(None)
def setlastclock(self, clock):
self._lastclock = clock
@@ -1519,6 +1519,11 @@ class filestat(object):
stat = None
return cls(stat)
+ @classmethod
+ def fromfp(cls, fp):
+ stat = os.fstat(fp.fileno())
+ return cls(stat)
+
__hash__ = object.__hash__
def __eq__(self, old):
@@ -160,6 +160,34 @@ treated differently in _checklookup() ac
$ rm b
+#if fsmonitor
+
+Create fsmonitor state.
+
+ $ hg status
+ $ f --type .hg/fsmonitor.state
+ .hg/fsmonitor.state: file
+
+Test that invalidating fsmonitor state in the middle (which doesn't require the
+wlock) causes the fsmonitor update to be skipped.
+hg debugrebuilddirstate ensures that the dirstaterace hook will be called, but
+it also invalidates the fsmonitor state. So back it up and restore it.
+
+ $ mv .hg/fsmonitor.state .hg/fsmonitor.state.tmp
+ $ hg debugrebuilddirstate
+ $ mv .hg/fsmonitor.state.tmp .hg/fsmonitor.state
+
+ $ cat > $TESTTMP/dirstaterace.sh <<EOF
+ > rm .hg/fsmonitor.state
+ > EOF
+
+ $ hg status --config extensions.dirstaterace=$TESTTMP/dirstaterace.py --debug
+ skip updating fsmonitor.state: identity mismatch
+ $ f .hg/fsmonitor.state
+ .hg/fsmonitor.state: file not found
+
+#endif
+
Set up a rebase situation for issue5581.
$ echo c2 > a