- Fix WhereIs() to return normalized paths.
+ From Jeff Petkau:
+
+ - Don't copy a built file to a CacheDir() if it's already there.
+
+ - Avoid partial copies of built files in a CacheDir() by copying
+ to a temporary file and renaming.
+
RELEASE 0.11 - Tue, 11 Feb 2003 05:24:33 -0600
def CachePushFunc(target, source, env):
t = target[0]
cachedir, cachefile = t.cachepath()
+ if os.path.exists(cachefile):
+ # Don't bother copying it if it's already there.
+ return
+
if not os.path.isdir(cachedir):
os.mkdir(cachedir)
- shutil.copy2(t.path, cachefile)
- st = os.stat(t.path)
- os.chmod(cachefile, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
+
+ tempfile = cachefile+'.tmp'
+ try:
+ shutil.copy2(t.path, tempfile)
+ os.rename(tempfile, cachefile)
+ st = os.stat(t.path)
+ os.chmod(cachefile, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
+ except OSError:
+ # It's possible someone else tried writing the file at the same
+ # time we did. Print a warning but don't stop the build, since
+ # it doesn't affect the correctness of the build.
+ SCons.Warnings.warn(SCons.Warnings.CacheWriteErrorWarning,
+ "Unable to copy %s to cache. Cache file is %s"
+ % (str(target), cachefile))
+ return
CachePush = SCons.Action.Action(CachePushFunc, None)
import sys
import time
import unittest
-import SCons.Node.FS
from TestCmd import TestCmd
-import SCons.Errors
import shutil
import stat
+import SCons.Errors
+import SCons.Node.FS
+import SCons.Warnings
+
built_it = None
# This will be built-in in 2.3. For now fake it.
class CacheDirTestCase(unittest.TestCase):
def runTest(self):
"""Test CacheDir functionality"""
+ test = TestCmd(workdir='')
+
global built_it
fs = SCons.Node.FS.FS()
SCons.Node.FS.CachePush = push
try:
- test = TestCmd(workdir='')
-
self.pushed = []
cd_f3 = test.workpath("cd.f3")
finally:
SCons.Node.FS.CachePush = save_CachePush
+ # Verify how the cachepath() method determines the name
+ # of the file in cache.
f5 = fs.File("cd.f5")
f5.set_bsig('a_fake_bsig')
cp = f5.cachepath()
filename = os.path.join(dirname, 'a_fake_bsig')
assert cp == (dirname, filename), cp
+ # Verify that no bsig raises an InternalERror
f6 = fs.File("cd.f6")
- f5.set_bsig(None)
+ f6.set_bsig(None)
exc_caught = 0
try:
- cp = f5.cachepath()
+ cp = f6.cachepath()
except SCons.Errors.InternalError:
exc_caught = 1
assert exc_caught
+ # Verify that we raise a warning if we can't copy a file to cache.
+ save_copy2 = shutil.copy2
+ def copy2(src, dst):
+ raise OSError
+ shutil.copy2 = copy2
+ save_mkdir = os.mkdir
+ def mkdir(dir):
+ pass
+ os.mkdir = mkdir
+ old_warn_exceptions = SCons.Warnings.warningAsException(1)
+ SCons.Warnings.enableWarningClass(SCons.Warnings.CacheWriteErrorWarning)
+
+ try:
+ cd_f7 = test.workpath("cd.f7")
+ test.write(cd_f7, "cd.f7\n")
+ f7 = fs.File(cd_f7)
+ f7.set_bsig('f7_bsig')
+
+ warn_caught = 0
+ try:
+ f7.built()
+ except SCons.Warnings.CacheWriteErrorWarning:
+ warn_caught = 1
+ assert warn_caught
+ finally:
+ shutil.copy2 = save_copy2
+ os.mkdir = save_mkdir
+ SCons.Warnings.warningAsException(old_warn_exceptions)
+ SCons.Warnings.suppressWarningClass(SCons.Warnings.CacheWriteErrorWarning)
+
if __name__ == "__main__":
class ReservedVariableWarning(Warning):
pass
+class CacheWriteErrorWarning(Warning):
+ pass
+
_warningAsException = 0
# The below is a list of 2-tuples. The first element is a class object.