mercurial/util.py
changeset 29200 ca4065028e00
parent 29017 07be86828e79
child 29201 a109bf7e0dc2
equal deleted inserted replaced
29199:daff05dcd184 29200:ca4065028e00
  1379         try: os.unlink(temp)
  1379         try: os.unlink(temp)
  1380         except OSError: pass
  1380         except OSError: pass
  1381         raise
  1381         raise
  1382     return temp
  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 class atomictempfile(object):
  1447 class atomictempfile(object):
  1385     '''writable file object that atomically updates a file
  1448     '''writable file object that atomically updates a file
  1386 
  1449 
  1387     All writes will go to a temporary copy of the original file. Call
  1450     All writes will go to a temporary copy of the original file. Call
  1388     close() when you are done writing, and atomictempfile will rename
  1451     close() when you are done writing, and atomictempfile will rename