mirror of
https://github.com/facebook/sapling.git
synced 2024-10-11 17:27:53 +03:00
bc1dfb1ac9
The usual contract is that close() makes your writes permanent, so atomictempfile's use of close() to *discard* writes (and rename() to keep them) is rather unexpected. Thus, change it so close() makes things permanent and add a new discard() method to throw them away. discard() is only used internally, in __del__(), to ensure that writes are discarded when an atomictempfile object goes out of scope. I audited mercurial.*, hgext.*, and ~80 third-party extensions, and found no one using the existing semantics of close() to discard writes, so this should be safe.
95 lines
2.0 KiB
Python
95 lines
2.0 KiB
Python
import sys, os, subprocess
|
|
|
|
if subprocess.call(['%s/hghave' % os.environ['TESTDIR'], 'cacheable']):
|
|
sys.exit(80)
|
|
|
|
from mercurial import util, scmutil, extensions
|
|
|
|
filecache = scmutil.filecache
|
|
|
|
class fakerepo(object):
|
|
def __init__(self):
|
|
self._filecache = {}
|
|
|
|
def join(self, p):
|
|
return p
|
|
|
|
def sjoin(self, p):
|
|
return p
|
|
|
|
@filecache('x')
|
|
def cached(self):
|
|
print 'creating'
|
|
|
|
def invalidate(self):
|
|
for k in self._filecache:
|
|
try:
|
|
delattr(self, k)
|
|
except AttributeError:
|
|
pass
|
|
|
|
def basic(repo):
|
|
# file doesn't exist, calls function
|
|
repo.cached
|
|
|
|
repo.invalidate()
|
|
# file still doesn't exist, uses cache
|
|
repo.cached
|
|
|
|
# create empty file
|
|
f = open('x', 'w')
|
|
f.close()
|
|
repo.invalidate()
|
|
# should recreate the object
|
|
repo.cached
|
|
|
|
f = open('x', 'w')
|
|
f.write('a')
|
|
f.close()
|
|
repo.invalidate()
|
|
# should recreate the object
|
|
repo.cached
|
|
|
|
repo.invalidate()
|
|
# stats file again, nothing changed, reuses object
|
|
repo.cached
|
|
|
|
# atomic replace file, size doesn't change
|
|
# hopefully st_mtime doesn't change as well so this doesn't use the cache
|
|
# because of inode change
|
|
f = scmutil.opener('.')('x', 'w', atomictemp=True)
|
|
f.write('b')
|
|
f.close()
|
|
|
|
repo.invalidate()
|
|
repo.cached
|
|
|
|
def fakeuncacheable():
|
|
def wrapcacheable(orig, *args, **kwargs):
|
|
return False
|
|
|
|
def wrapinit(orig, *args, **kwargs):
|
|
pass
|
|
|
|
originit = extensions.wrapfunction(util.cachestat, '__init__', wrapinit)
|
|
origcacheable = extensions.wrapfunction(util.cachestat, 'cacheable',
|
|
wrapcacheable)
|
|
|
|
try:
|
|
os.remove('x')
|
|
except:
|
|
pass
|
|
|
|
basic(fakerepo())
|
|
|
|
util.cachestat.cacheable = origcacheable
|
|
util.cachestat.__init__ = originit
|
|
|
|
print 'basic:'
|
|
print
|
|
basic(fakerepo())
|
|
print
|
|
print 'fakeuncacheable:'
|
|
print
|
|
fakeuncacheable()
|