##// END OF EJS Templates
branching: merge stable into default
branching: merge stable into default

File last commit:

r50201:2e726c93 default
r52493:ee1b648e merge default
Show More
state.py
148 lines | 4.6 KiB | text/x-python | PythonLexer
Martijn Pieters
fsmonitor: new experimental extension...
r28433 # state.py - fsmonitor persistent state
#
# Copyright 2013-2016 Facebook, Inc.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
import errno
import os
import socket
import struct
Yuya Nishihara
py3: move up symbol imports to enforce import-checker rules...
r29205 from mercurial.i18n import _
Siddharth Agarwal
fsmonitor: don't write out state if identity has changed (issue5581)...
r32816 from mercurial import (
Gregory Szorc
fsmonitor: normalize hostname to bytes...
r43710 encoding,
Siddharth Agarwal
fsmonitor: don't write out state if identity has changed (issue5581)...
r32816 pathutil,
util,
)
Martijn Pieters
fsmonitor: new experimental extension...
r28433
_version = 4
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _versionformat = b">I"
Martijn Pieters
fsmonitor: new experimental extension...
r28433
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
py3: use class X: instead of class X(object):...
r49801 class state:
Martijn Pieters
fsmonitor: new experimental extension...
r28433 def __init__(self, repo):
Durham Goode
fsmonitor: remove use of repo.opener...
r31215 self._vfs = repo.vfs
Martijn Pieters
fsmonitor: new experimental extension...
r28433 self._ui = repo.ui
self._rootdir = pathutil.normasprefix(repo.root)
self._lastclock = None
Siddharth Agarwal
fsmonitor: don't write out state if identity has changed (issue5581)...
r32816 self._identity = util.filestat(None)
Martijn Pieters
fsmonitor: new experimental extension...
r28433
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.mode = self._ui.config(b'fsmonitor', b'mode')
Martijn Pieters
fsmonitor: new experimental extension...
r28433 self.walk_on_invalidate = self._ui.configbool(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'fsmonitor', b'walk_on_invalidate'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.timeout = float(self._ui.config(b'fsmonitor', b'timeout'))
Martijn Pieters
fsmonitor: new experimental extension...
r28433
def get(self):
try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 file = self._vfs(b'fsmonitor.state', b'rb')
Martijn Pieters
fsmonitor: new experimental extension...
r28433 except IOError as inst:
Siddharth Agarwal
fsmonitor: don't write out state if identity has changed (issue5581)...
r32816 self._identity = util.filestat(None)
Martijn Pieters
fsmonitor: new experimental extension...
r28433 if inst.errno != errno.ENOENT:
raise
return None, None, None
Siddharth Agarwal
fsmonitor: don't write out state if identity has changed (issue5581)...
r32816 self._identity = util.filestat.fromfp(file)
Martijn Pieters
fsmonitor: new experimental extension...
r28433 versionbytes = file.read(4)
if len(versionbytes) < 4:
self._ui.log(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'fsmonitor',
b'fsmonitor: state file only has %d bytes, '
b'nuking state\n' % len(versionbytes),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martijn Pieters
fsmonitor: new experimental extension...
r28433 self.invalidate()
return None, None, None
try:
diskversion = struct.unpack(_versionformat, versionbytes)[0]
if diskversion != _version:
# different version, nuke state and start over
self._ui.log(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'fsmonitor',
b'fsmonitor: version switch from %d to '
b'%d, nuking state\n' % (diskversion, _version),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martijn Pieters
fsmonitor: new experimental extension...
r28433 self.invalidate()
return None, None, None
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 state = file.read().split(b'\0')
Martijn Pieters
fsmonitor: new experimental extension...
r28433 # state = hostname\0clock\0ignorehash\0 + list of files, each
# followed by a \0
Simon Farnsworth
fsmonitor: be robust in the face of bad state...
r30539 if len(state) < 3:
self._ui.log(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'fsmonitor',
b'fsmonitor: state file truncated (expected '
b'3 chunks, found %d), nuking state\n',
Augie Fackler
formatting: blacken the codebase...
r43346 len(state),
)
Simon Farnsworth
fsmonitor: be robust in the face of bad state...
r30539 self.invalidate()
return None, None, None
Martijn Pieters
fsmonitor: new experimental extension...
r28433 diskhostname = state[0]
Gregory Szorc
fsmonitor: normalize hostname to bytes...
r43710 hostname = encoding.strtolocal(socket.gethostname())
Martijn Pieters
fsmonitor: new experimental extension...
r28433 if diskhostname != hostname:
# file got moved to a different host
Augie Fackler
formatting: blacken the codebase...
r43346 self._ui.log(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'fsmonitor',
b'fsmonitor: stored hostname "%s" '
b'different from current "%s", nuking state\n'
Augie Fackler
formatting: blacken the codebase...
r43346 % (diskhostname, hostname),
)
Martijn Pieters
fsmonitor: new experimental extension...
r28433 self.invalidate()
return None, None, None
clock = state[1]
ignorehash = state[2]
# discard the value after the last \0
notefiles = state[3:-1]
finally:
file.close()
return clock, ignorehash, notefiles
def set(self, clock, ignorehash, notefiles):
if clock is None:
self.invalidate()
return
Siddharth Agarwal
fsmonitor: don't write out state if identity has changed (issue5581)...
r32816 # 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.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 identity = util.filestat.frompath(self._vfs.join(b'fsmonitor.state'))
Siddharth Agarwal
fsmonitor: don't write out state if identity has changed (issue5581)...
r32816 if identity != self._identity:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._ui.debug(
b'skip updating fsmonitor.state: identity mismatch\n'
)
Siddharth Agarwal
fsmonitor: don't write out state if identity has changed (issue5581)...
r32816 return
Martijn Pieters
fsmonitor: new experimental extension...
r28433 try:
Augie Fackler
formatting: blacken the codebase...
r43346 file = self._vfs(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'fsmonitor.state', b'wb', atomictemp=True, checkambig=True
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martijn Pieters
fsmonitor: new experimental extension...
r28433 except (IOError, OSError):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._ui.warn(_(b"warning: unable to write out fsmonitor state\n"))
Martijn Pieters
fsmonitor: new experimental extension...
r28433 return
Simon Farnsworth
fsmonitor: be robust in the face of bad state...
r30539 with file:
Martijn Pieters
fsmonitor: new experimental extension...
r28433 file.write(struct.pack(_versionformat, _version))
Gregory Szorc
fsmonitor: normalize hostname to bytes...
r43710 file.write(encoding.strtolocal(socket.gethostname()) + b'\0')
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 file.write(clock + b'\0')
file.write(ignorehash + b'\0')
Martijn Pieters
fsmonitor: new experimental extension...
r28433 if notefiles:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 file.write(b'\0'.join(notefiles))
file.write(b'\0')
Martijn Pieters
fsmonitor: new experimental extension...
r28433
def invalidate(self):
try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 os.unlink(os.path.join(self._rootdir, b'.hg', b'fsmonitor.state'))
Manuel Jacob
py3: catch FileNotFoundError instead of checking errno == ENOENT
r50201 except FileNotFoundError:
pass
Siddharth Agarwal
fsmonitor: don't write out state if identity has changed (issue5581)...
r32816 self._identity = util.filestat(None)
Martijn Pieters
fsmonitor: new experimental extension...
r28433
def setlastclock(self, clock):
self._lastclock = clock
def getlastclock(self):
return self._lastclock