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 |