summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/CacheDir.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/SCons/CacheDir.py')
-rw-r--r--src/engine/SCons/CacheDir.py89
1 files changed, 74 insertions, 15 deletions
diff --git a/src/engine/SCons/CacheDir.py b/src/engine/SCons/CacheDir.py
index 9dd18e5..1690674 100644
--- a/src/engine/SCons/CacheDir.py
+++ b/src/engine/SCons/CacheDir.py
@@ -27,11 +27,13 @@ __doc__ = """
CacheDir support
"""
-import os.path
+import json
+import os
import stat
import sys
import SCons.Action
+import SCons.Warnings
cache_enabled = True
cache_debug = False
@@ -50,11 +52,11 @@ def CacheRetrieveFunc(target, source, env):
cd.CacheDebug('CacheRetrieve(%s): retrieving from %s\n', t, cachefile)
if SCons.Action.execute_actions:
if fs.islink(cachefile):
- fs.symlink(fs.readlink(cachefile), t.path)
+ fs.symlink(fs.readlink(cachefile), t.get_internal_path())
else:
- env.copy_from_cache(cachefile, t.path)
+ env.copy_from_cache(cachefile, t.get_internal_path())
st = fs.stat(cachefile)
- fs.chmod(t.path, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
+ fs.chmod(t.get_internal_path(), stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
return 0
def CacheRetrieveString(target, source, env):
@@ -63,7 +65,7 @@ def CacheRetrieveString(target, source, env):
cd = env.get_CacheDir()
cachedir, cachefile = cd.cachepath(t)
if t.fs.exists(cachefile):
- return "Retrieved `%s' from cache" % t.path
+ return "Retrieved `%s' from cache" % t.get_internal_path()
return None
CacheRetrieve = SCons.Action.Action(CacheRetrieveFunc, CacheRetrieveString)
@@ -71,7 +73,8 @@ CacheRetrieve = SCons.Action.Action(CacheRetrieveFunc, CacheRetrieveString)
CacheRetrieveSilent = SCons.Action.Action(CacheRetrieveFunc, None)
def CachePushFunc(target, source, env):
- if cache_readonly: return
+ if cache_readonly:
+ return
t = target[0]
if t.nocache:
@@ -106,12 +109,12 @@ def CachePushFunc(target, source, env):
raise SCons.Errors.EnvironmentError(msg)
try:
- if fs.islink(t.path):
- fs.symlink(fs.readlink(t.path), tempfile)
+ if fs.islink(t.get_internal_path()):
+ fs.symlink(fs.readlink(t.get_internal_path()), tempfile)
else:
- fs.copy2(t.path, tempfile)
+ fs.copy2(t.get_internal_path(), tempfile)
fs.rename(tempfile, cachefile)
- st = fs.stat(t.path)
+ st = fs.stat(t.get_internal_path())
fs.chmod(cachefile, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
except EnvironmentError:
# It's possible someone else tried writing the file at the
@@ -124,6 +127,10 @@ def CachePushFunc(target, source, env):
CachePush = SCons.Action.Action(CachePushFunc, None)
+# Nasty hack to cut down to one warning for each cachedir path that needs
+# upgrading.
+warned = dict()
+
class CacheDir(object):
def __init__(self, path):
@@ -132,11 +139,63 @@ class CacheDir(object):
except ImportError:
msg = "No hashlib or MD5 module available, CacheDir() not supported"
SCons.Warnings.warn(SCons.Warnings.NoMD5ModuleWarning, msg)
- self.path = None
- else:
- self.path = path
+ path = None
+ self.path = path
self.current_cache_debug = None
self.debugFP = None
+ self.config = dict()
+ if path is None:
+ return
+ # See if there's a config file in the cache directory. If there is,
+ # use it. If there isn't, and the directory exists and isn't empty,
+ # produce a warning. If the directory doesn't exist or is empty,
+ # write a config file.
+ config_file = os.path.join(path, 'config')
+ if not os.path.exists(config_file):
+ # A note: There is a race hazard here, if two processes start and
+ # attempt to create the cache directory at the same time. However,
+ # python doesn't really give you the option to do exclusive file
+ # creation (it doesn't even give you the option to error on opening
+ # an existing file for writing...). The ordering of events here
+ # as an attempt to alleviate this, on the basis that it's a pretty
+ # unlikely occurence (it'd require two builds with a brand new cache
+ # directory)
+ if os.path.isdir(path) and len(os.listdir(path)) != 0:
+ self.config['prefix_len'] = 1
+ # When building the project I was testing this on, the warning
+ # was output over 20 times. That seems excessive
+ global warned
+ if self.path not in warned:
+ msg = "Please upgrade your cache by running " +\
+ " scons-configure-cache.py " + self.path
+ SCons.Warnings.warn(SCons.Warnings.CacheVersionWarning, msg)
+ warned[self.path] = True
+ else:
+ if not os.path.isdir(path):
+ try:
+ os.makedirs(path)
+ except OSError:
+ # If someone else is trying to create the directory at
+ # the same time as me, bad things will happen
+ msg = "Failed to create cache directory " + path
+ raise SCons.Errors.EnvironmentError(msg)
+
+ self.config['prefix_len'] = 2
+ if not os.path.exists(config_file):
+ try:
+ with open(config_file, 'w') as config:
+ json.dump(self.config, config)
+ except:
+ msg = "Failed to write cache configuration for " + path
+ raise SCons.Errors.EnvironmentError(msg)
+ else:
+ try:
+ with open(config_file) as config:
+ self.config = json.load(config)
+ except ValueError:
+ msg = "Failed to read cache configuration for " + path
+ raise SCons.Errors.EnvironmentError(msg)
+
def CacheDebug(self, fmt, target, cachefile):
if cache_debug != self.current_cache_debug:
@@ -151,7 +210,7 @@ class CacheDir(object):
self.debugFP.write(fmt % (target, os.path.split(cachefile)[1]))
def is_enabled(self):
- return (cache_enabled and not self.path is None)
+ return cache_enabled and not self.path is None
def is_readonly(self):
return cache_readonly
@@ -163,7 +222,7 @@ class CacheDir(object):
return None, None
sig = node.get_cachedir_bsig()
- subdir = sig[0].upper()
+ subdir = sig[:self.config['prefix_len']].upper()
dir = os.path.join(self.path, subdir)
return dir, os.path.join(dir, sig)