comparison mercurial/util.py @ 29201:a109bf7e0dc2

util: make atomictempfile avoid ambiguity of file stat if needed Ambiguity check is executed at close(), only if: - atomictempfile is created with checkambig=True, and - target file exists before renaming This restriction avoids performance decrement by needless examination of file stat (for example, filelog doesn't need exact cache validation, even though it uses atomictempfile to write changes out). See description of filestat class for detail about why the logic in this patch works as expected. This patch is a part of preparation for "Exact Cache Validation Plan": https://www.mercurial-scm.org/wiki/ExactCacheValidationPlan
author FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
date Thu, 19 May 2016 00:20:38 +0900
parents ca4065028e00
children ce2d81aafbae
comparison
equal deleted inserted replaced
29200:ca4065028e00 29201:a109bf7e0dc2
1451 close() when you are done writing, and atomictempfile will rename 1451 close() when you are done writing, and atomictempfile will rename
1452 the temporary copy to the original name, making the changes 1452 the temporary copy to the original name, making the changes
1453 visible. If the object is destroyed without being closed, all your 1453 visible. If the object is destroyed without being closed, all your
1454 writes are discarded. 1454 writes are discarded.
1455 ''' 1455 '''
1456 def __init__(self, name, mode='w+b', createmode=None): 1456 def __init__(self, name, mode='w+b', createmode=None, checkambig=False):
1457 self.__name = name # permanent name 1457 self.__name = name # permanent name
1458 self._tempname = mktempcopy(name, emptyok=('w' in mode), 1458 self._tempname = mktempcopy(name, emptyok=('w' in mode),
1459 createmode=createmode) 1459 createmode=createmode)
1460 self._fp = posixfile(self._tempname, mode) 1460 self._fp = posixfile(self._tempname, mode)
1461 self._checkambig = checkambig
1461 1462
1462 # delegated methods 1463 # delegated methods
1463 self.write = self._fp.write 1464 self.write = self._fp.write
1464 self.seek = self._fp.seek 1465 self.seek = self._fp.seek
1465 self.tell = self._fp.tell 1466 self.tell = self._fp.tell
1466 self.fileno = self._fp.fileno 1467 self.fileno = self._fp.fileno
1467 1468
1468 def close(self): 1469 def close(self):
1469 if not self._fp.closed: 1470 if not self._fp.closed:
1470 self._fp.close() 1471 self._fp.close()
1471 rename(self._tempname, localpath(self.__name)) 1472 filename = localpath(self.__name)
1473 oldstat = self._checkambig and filestat(filename)
1474 if oldstat and oldstat.stat:
1475 rename(self._tempname, filename)
1476 newstat = filestat(filename)
1477 if newstat.isambig(oldstat):
1478 # stat of changed file is ambiguous to original one
1479 advanced = (oldstat.stat.st_mtime + 1) & 0x7fffffff
1480 os.utime(filename, (advanced, advanced))
1481 else:
1482 rename(self._tempname, filename)
1472 1483
1473 def discard(self): 1484 def discard(self):
1474 if not self._fp.closed: 1485 if not self._fp.closed:
1475 try: 1486 try:
1476 os.unlink(self._tempname) 1487 os.unlink(self._tempname)