Show More
@@ -1381,6 +1381,69 b' def mktempcopy(name, emptyok=False, crea' | |||
|
1381 | 1381 | raise |
|
1382 | 1382 | return temp |
|
1383 | 1383 | |
|
1384 | class filestat(object): | |
|
1385 | """help to exactly detect change of a file | |
|
1386 | ||
|
1387 | 'stat' attribute is result of 'os.stat()' if specified 'path' | |
|
1388 | exists. Otherwise, it is None. This can avoid preparative | |
|
1389 | 'exists()' examination on client side of this class. | |
|
1390 | """ | |
|
1391 | def __init__(self, path): | |
|
1392 | try: | |
|
1393 | self.stat = os.stat(path) | |
|
1394 | except OSError as err: | |
|
1395 | if err.errno != errno.ENOENT: | |
|
1396 | raise | |
|
1397 | self.stat = None | |
|
1398 | ||
|
1399 | __hash__ = object.__hash__ | |
|
1400 | ||
|
1401 | def __eq__(self, old): | |
|
1402 | try: | |
|
1403 | # if ambiguity between stat of new and old file is | |
|
1404 | # avoided, comparision of size, ctime and mtime is enough | |
|
1405 | # to exactly detect change of a file regardless of platform | |
|
1406 | return (self.stat.st_size == old.stat.st_size and | |
|
1407 | self.stat.st_ctime == old.stat.st_ctime and | |
|
1408 | self.stat.st_mtime == old.stat.st_mtime) | |
|
1409 | except AttributeError: | |
|
1410 | return False | |
|
1411 | ||
|
1412 | def isambig(self, old): | |
|
1413 | """Examine whether new (= self) stat is ambiguous against old one | |
|
1414 | ||
|
1415 | "S[N]" below means stat of a file at N-th change: | |
|
1416 | ||
|
1417 | - S[n-1].ctime < S[n].ctime: can detect change of a file | |
|
1418 | - S[n-1].ctime == S[n].ctime | |
|
1419 | - S[n-1].ctime < S[n].mtime: means natural advancing (*1) | |
|
1420 | - S[n-1].ctime == S[n].mtime: is ambiguous (*2) | |
|
1421 | - S[n-1].ctime > S[n].mtime: never occurs naturally (don't care) | |
|
1422 | - S[n-1].ctime > S[n].ctime: never occurs naturally (don't care) | |
|
1423 | ||
|
1424 | Case (*2) above means that a file was changed twice or more at | |
|
1425 | same time in sec (= S[n-1].ctime), and comparison of timestamp | |
|
1426 | is ambiguous. | |
|
1427 | ||
|
1428 | Base idea to avoid such ambiguity is "advance mtime 1 sec, if | |
|
1429 | timestamp is ambiguous". | |
|
1430 | ||
|
1431 | But advancing mtime only in case (*2) doesn't work as | |
|
1432 | expected, because naturally advanced S[n].mtime in case (*1) | |
|
1433 | might be equal to manually advanced S[n-1 or earlier].mtime. | |
|
1434 | ||
|
1435 | Therefore, all "S[n-1].ctime == S[n].ctime" cases should be | |
|
1436 | treated as ambiguous regardless of mtime, to avoid overlooking | |
|
1437 | by confliction between such mtime. | |
|
1438 | ||
|
1439 | Advancing mtime "if isambig(oldstat)" ensures "S[n-1].mtime != | |
|
1440 | S[n].mtime", even if size of a file isn't changed. | |
|
1441 | """ | |
|
1442 | try: | |
|
1443 | return (self.stat.st_ctime == old.stat.st_ctime) | |
|
1444 | except AttributeError: | |
|
1445 | return False | |
|
1446 | ||
|
1384 | 1447 | class atomictempfile(object): |
|
1385 | 1448 | '''writable file object that atomically updates a file |
|
1386 | 1449 |
General Comments 0
You need to be logged in to leave comments.
Login now