Mercurial > hg
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) |