Show More
@@ -1431,3 +1431,34 b' class backgroundfilecloser(object):' | |||||
1431 | return |
|
1431 | return | |
1432 |
|
1432 | |||
1433 | self._queue.put(fh, block=True, timeout=None) |
|
1433 | self._queue.put(fh, block=True, timeout=None) | |
|
1434 | ||||
|
1435 | class checkambigatclosing(closewrapbase): | |||
|
1436 | """Proxy for a file object, to avoid ambiguity of file stat | |||
|
1437 | ||||
|
1438 | See also util.filestat for detail about "ambiguity of file stat". | |||
|
1439 | ||||
|
1440 | This proxy is useful only if the target file is guarded by any | |||
|
1441 | lock (e.g. repo.lock or repo.wlock) | |||
|
1442 | ||||
|
1443 | Do not instantiate outside of the vfs layer. | |||
|
1444 | """ | |||
|
1445 | def __init__(self, fh): | |||
|
1446 | super(checkambigatclosing, self).__init__(fh) | |||
|
1447 | object.__setattr__(self, '_oldstat', util.filestat(fh.name)) | |||
|
1448 | ||||
|
1449 | def _checkambig(self): | |||
|
1450 | oldstat = self._oldstat | |||
|
1451 | if oldstat.stat: | |||
|
1452 | newstat = util.filestat(self._origfh.name) | |||
|
1453 | if newstat.isambig(oldstat): | |||
|
1454 | # stat of changed file is ambiguous to original one | |||
|
1455 | advanced = (oldstat.stat.st_mtime + 1) & 0x7fffffff | |||
|
1456 | os.utime(self._origfh.name, (advanced, advanced)) | |||
|
1457 | ||||
|
1458 | def __exit__(self, exc_type, exc_value, exc_tb): | |||
|
1459 | self._origfh.__exit__(exc_type, exc_value, exc_tb) | |||
|
1460 | self._checkambig() | |||
|
1461 | ||||
|
1462 | def close(self): | |||
|
1463 | self._origfh.close() | |||
|
1464 | self._checkambig() |
@@ -179,6 +179,56 b' def setbeforeget(repo):' | |||||
179 | print("* file y created") |
|
179 | print("* file y created") | |
180 | print(repo.cached) |
|
180 | print(repo.cached) | |
181 |
|
181 | |||
|
182 | def antiambiguity(): | |||
|
183 | filename = 'ambigcheck' | |||
|
184 | ||||
|
185 | # try some times, because reproduction of ambiguity depends on | |||
|
186 | # "filesystem time" | |||
|
187 | for i in xrange(5): | |||
|
188 | fp = open(filename, 'w') | |||
|
189 | fp.write('FOO') | |||
|
190 | fp.close() | |||
|
191 | ||||
|
192 | oldstat = os.stat(filename) | |||
|
193 | if oldstat.st_ctime != oldstat.st_mtime: | |||
|
194 | # subsequent changing never causes ambiguity | |||
|
195 | continue | |||
|
196 | ||||
|
197 | repetition = 3 | |||
|
198 | ||||
|
199 | # repeat changing via checkambigatclosing, to examine whether | |||
|
200 | # st_mtime is advanced multiple times as expecetd | |||
|
201 | for i in xrange(repetition): | |||
|
202 | # explicit closing | |||
|
203 | fp = scmutil.checkambigatclosing(open(filename, 'a')) | |||
|
204 | fp.write('FOO') | |||
|
205 | fp.close() | |||
|
206 | ||||
|
207 | # implicit closing by "with" statement | |||
|
208 | with scmutil.checkambigatclosing(open(filename, 'a')) as fp: | |||
|
209 | fp.write('BAR') | |||
|
210 | ||||
|
211 | newstat = os.stat(filename) | |||
|
212 | if oldstat.st_ctime != newstat.st_ctime: | |||
|
213 | # timestamp ambiguity was naturally avoided while repetition | |||
|
214 | continue | |||
|
215 | ||||
|
216 | # st_mtime should be advanced "repetition * 2" times, because | |||
|
217 | # all changes occured at same time (in sec) | |||
|
218 | expected = (oldstat.st_mtime + repetition * 2) & 0x7fffffff | |||
|
219 | if newstat.st_mtime != expected: | |||
|
220 | print("'newstat.st_mtime %s is not %s (as %s + %s * 2)" % | |||
|
221 | (newstat.st_mtime, expected, oldstat.st_mtime, repetition)) | |||
|
222 | ||||
|
223 | # no more examination is needed regardless of result | |||
|
224 | break | |||
|
225 | else: | |||
|
226 | # This platform seems too slow to examine anti-ambiguity | |||
|
227 | # of file timestamp (or test happened to be executed at | |||
|
228 | # bad timing). Exit silently in this case, because running | |||
|
229 | # on other faster platforms can detect problems | |||
|
230 | pass | |||
|
231 | ||||
182 | print('basic:') |
|
232 | print('basic:') | |
183 | print() |
|
233 | print() | |
184 | basic(fakerepo()) |
|
234 | basic(fakerepo()) | |
@@ -191,3 +241,7 b' print()' | |||||
191 | print('setbeforeget:') |
|
241 | print('setbeforeget:') | |
192 | print() |
|
242 | print() | |
193 | setbeforeget(fakerepo()) |
|
243 | setbeforeget(fakerepo()) | |
|
244 | print() | |||
|
245 | print('antiambiguity:') | |||
|
246 | print() | |||
|
247 | antiambiguity() |
General Comments 0
You need to be logged in to leave comments.
Login now