hgext/fsmonitor/state.py
changeset 43077 687b865b95ad
parent 43076 2372284d9457
child 43392 8a9e53b974ee
equal deleted inserted replaced
43076:2372284d9457 43077:687b865b95ad
    17     pathutil,
    17     pathutil,
    18     util,
    18     util,
    19 )
    19 )
    20 
    20 
    21 _version = 4
    21 _version = 4
    22 _versionformat = ">I"
    22 _versionformat = b">I"
    23 
    23 
    24 
    24 
    25 class state(object):
    25 class state(object):
    26     def __init__(self, repo):
    26     def __init__(self, repo):
    27         self._vfs = repo.vfs
    27         self._vfs = repo.vfs
    28         self._ui = repo.ui
    28         self._ui = repo.ui
    29         self._rootdir = pathutil.normasprefix(repo.root)
    29         self._rootdir = pathutil.normasprefix(repo.root)
    30         self._lastclock = None
    30         self._lastclock = None
    31         self._identity = util.filestat(None)
    31         self._identity = util.filestat(None)
    32 
    32 
    33         self.mode = self._ui.config('fsmonitor', 'mode')
    33         self.mode = self._ui.config(b'fsmonitor', b'mode')
    34         self.walk_on_invalidate = self._ui.configbool(
    34         self.walk_on_invalidate = self._ui.configbool(
    35             'fsmonitor', 'walk_on_invalidate'
    35             b'fsmonitor', b'walk_on_invalidate'
    36         )
    36         )
    37         self.timeout = float(self._ui.config('fsmonitor', 'timeout'))
    37         self.timeout = float(self._ui.config(b'fsmonitor', b'timeout'))
    38 
    38 
    39     def get(self):
    39     def get(self):
    40         try:
    40         try:
    41             file = self._vfs('fsmonitor.state', 'rb')
    41             file = self._vfs(b'fsmonitor.state', b'rb')
    42         except IOError as inst:
    42         except IOError as inst:
    43             self._identity = util.filestat(None)
    43             self._identity = util.filestat(None)
    44             if inst.errno != errno.ENOENT:
    44             if inst.errno != errno.ENOENT:
    45                 raise
    45                 raise
    46             return None, None, None
    46             return None, None, None
    48         self._identity = util.filestat.fromfp(file)
    48         self._identity = util.filestat.fromfp(file)
    49 
    49 
    50         versionbytes = file.read(4)
    50         versionbytes = file.read(4)
    51         if len(versionbytes) < 4:
    51         if len(versionbytes) < 4:
    52             self._ui.log(
    52             self._ui.log(
    53                 'fsmonitor',
    53                 b'fsmonitor',
    54                 'fsmonitor: state file only has %d bytes, '
    54                 b'fsmonitor: state file only has %d bytes, '
    55                 'nuking state\n' % len(versionbytes),
    55                 b'nuking state\n' % len(versionbytes),
    56             )
    56             )
    57             self.invalidate()
    57             self.invalidate()
    58             return None, None, None
    58             return None, None, None
    59         try:
    59         try:
    60             diskversion = struct.unpack(_versionformat, versionbytes)[0]
    60             diskversion = struct.unpack(_versionformat, versionbytes)[0]
    61             if diskversion != _version:
    61             if diskversion != _version:
    62                 # different version, nuke state and start over
    62                 # different version, nuke state and start over
    63                 self._ui.log(
    63                 self._ui.log(
    64                     'fsmonitor',
    64                     b'fsmonitor',
    65                     'fsmonitor: version switch from %d to '
    65                     b'fsmonitor: version switch from %d to '
    66                     '%d, nuking state\n' % (diskversion, _version),
    66                     b'%d, nuking state\n' % (diskversion, _version),
    67                 )
    67                 )
    68                 self.invalidate()
    68                 self.invalidate()
    69                 return None, None, None
    69                 return None, None, None
    70 
    70 
    71             state = file.read().split('\0')
    71             state = file.read().split(b'\0')
    72             # state = hostname\0clock\0ignorehash\0 + list of files, each
    72             # state = hostname\0clock\0ignorehash\0 + list of files, each
    73             # followed by a \0
    73             # followed by a \0
    74             if len(state) < 3:
    74             if len(state) < 3:
    75                 self._ui.log(
    75                 self._ui.log(
    76                     'fsmonitor',
    76                     b'fsmonitor',
    77                     'fsmonitor: state file truncated (expected '
    77                     b'fsmonitor: state file truncated (expected '
    78                     '3 chunks, found %d), nuking state\n',
    78                     b'3 chunks, found %d), nuking state\n',
    79                     len(state),
    79                     len(state),
    80                 )
    80                 )
    81                 self.invalidate()
    81                 self.invalidate()
    82                 return None, None, None
    82                 return None, None, None
    83             diskhostname = state[0]
    83             diskhostname = state[0]
    84             hostname = socket.gethostname()
    84             hostname = socket.gethostname()
    85             if diskhostname != hostname:
    85             if diskhostname != hostname:
    86                 # file got moved to a different host
    86                 # file got moved to a different host
    87                 self._ui.log(
    87                 self._ui.log(
    88                     'fsmonitor',
    88                     b'fsmonitor',
    89                     'fsmonitor: stored hostname "%s" '
    89                     b'fsmonitor: stored hostname "%s" '
    90                     'different from current "%s", nuking state\n'
    90                     b'different from current "%s", nuking state\n'
    91                     % (diskhostname, hostname),
    91                     % (diskhostname, hostname),
    92                 )
    92                 )
    93                 self.invalidate()
    93                 self.invalidate()
    94                 return None, None, None
    94                 return None, None, None
    95 
    95 
   108             self.invalidate()
   108             self.invalidate()
   109             return
   109             return
   110 
   110 
   111         # Read the identity from the file on disk rather than from the open file
   111         # Read the identity from the file on disk rather than from the open file
   112         # pointer below, because the latter is actually a brand new file.
   112         # pointer below, because the latter is actually a brand new file.
   113         identity = util.filestat.frompath(self._vfs.join('fsmonitor.state'))
   113         identity = util.filestat.frompath(self._vfs.join(b'fsmonitor.state'))
   114         if identity != self._identity:
   114         if identity != self._identity:
   115             self._ui.debug('skip updating fsmonitor.state: identity mismatch\n')
   115             self._ui.debug(
       
   116                 b'skip updating fsmonitor.state: identity mismatch\n'
       
   117             )
   116             return
   118             return
   117 
   119 
   118         try:
   120         try:
   119             file = self._vfs(
   121             file = self._vfs(
   120                 'fsmonitor.state', 'wb', atomictemp=True, checkambig=True
   122                 b'fsmonitor.state', b'wb', atomictemp=True, checkambig=True
   121             )
   123             )
   122         except (IOError, OSError):
   124         except (IOError, OSError):
   123             self._ui.warn(_("warning: unable to write out fsmonitor state\n"))
   125             self._ui.warn(_(b"warning: unable to write out fsmonitor state\n"))
   124             return
   126             return
   125 
   127 
   126         with file:
   128         with file:
   127             file.write(struct.pack(_versionformat, _version))
   129             file.write(struct.pack(_versionformat, _version))
   128             file.write(socket.gethostname() + '\0')
   130             file.write(socket.gethostname() + b'\0')
   129             file.write(clock + '\0')
   131             file.write(clock + b'\0')
   130             file.write(ignorehash + '\0')
   132             file.write(ignorehash + b'\0')
   131             if notefiles:
   133             if notefiles:
   132                 file.write('\0'.join(notefiles))
   134                 file.write(b'\0'.join(notefiles))
   133                 file.write('\0')
   135                 file.write(b'\0')
   134 
   136 
   135     def invalidate(self):
   137     def invalidate(self):
   136         try:
   138         try:
   137             os.unlink(os.path.join(self._rootdir, '.hg', 'fsmonitor.state'))
   139             os.unlink(os.path.join(self._rootdir, b'.hg', b'fsmonitor.state'))
   138         except OSError as inst:
   140         except OSError as inst:
   139             if inst.errno != errno.ENOENT:
   141             if inst.errno != errno.ENOENT:
   140                 raise
   142                 raise
   141         self._identity = util.filestat(None)
   143         self._identity = util.filestat(None)
   142 
   144