try:
func(src,dest)
break
- except OSError:
+ except (IOError, OSError):
+ # An OSError indicates something happened like a permissions
+ # problem or an attempt to symlink across file-system
+ # boundaries. An IOError indicates something like the file
+ # not existing. In either case, keeping trying additional
+ # functions in the list and only raise an error if the last
+ # one failed.
if func == Link_Funcs[-1]:
# exception of the last link method (copy) are fatal
raise
fs.rename(tempfile, cachefile)
st = fs.stat(t.path)
fs.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.
+ except (IOError, OSError):
+ # It's possible someone else tried writing the file at the
+ # same time we did, or else that there was some problem like
+ # the CacheDir being on a separate file system that's full.
+ # In any case, inability to push a file to cache doesn't affect
+ # the correctness of the build, so just print a warning.
SCons.Warnings.warn(SCons.Warnings.CacheWriteErrorWarning,
"Unable to copy %s to cache. Cache file is %s"
% (str(target), cachefile))
mode = os.stat(self.sconsign)[0]
os.chmod(self.sconsign, 0666)
os.unlink(self.sconsign)
- except OSError:
+ except (IOError, OSError):
+ # Try to carry on in the face of either OSError
+ # (things like permission issues) or IOError (disk
+ # or network issues). If there's a really dangerous
+ # issue, it should get re-raised by the calls below.
pass
try:
os.rename(fname, self.sconsign)
except OSError:
+ # An OSError failure to rename may indicate something
+ # like the directory has no write permission, but
+ # the .sconsign file itself might still be writable,
+ # so try writing on top of it directly. An IOError
+ # here, or in any of the following calls, would get
+ # raised, indicating something like a potentially
+ # serious disk or network issue.
open(self.sconsign, 'wb').write(open(fname, 'rb').read())
os.chmod(self.sconsign, mode)
try:
os.unlink(temp)
- except OSError:
+ except (IOError, OSError):
pass
ForDirectory = DB
"""
try:
flist = node.fs.listdir(node.abspath)
- except OSError:
+ except (IOError, OSError):
return []
dont_scan = lambda k: not skip_entry.has_key(k)
flist = filter(dont_scan, flist)
class CleanTask(SCons.Taskmaster.Task):
"""An SCons clean task."""
+ def dir_index(self, directory):
+ dirname = lambda f, d=directory: os.path.join(d, f)
+ files = map(dirname, os.listdir(directory))
+
+ # os.listdir() isn't guaranteed to return files in any specific order,
+ # but some of the test code expects sorted output.
+ files.sort()
+ return files
+
+ def fs_delete(self, path, remove=1):
+ try:
+ if os.path.exists(path):
+ if os.path.isfile(path):
+ if remove: os.unlink(path)
+ display("Removed " + path)
+ elif os.path.isdir(path) and not os.path.islink(path):
+ # delete everything in the dir
+ for p in self.dir_index(path):
+ if os.path.isfile(p):
+ if remove: os.unlink(p)
+ display("Removed " + p)
+ else:
+ self.fs_delete(p, remove)
+ # then delete dir itself
+ if remove: os.rmdir(path)
+ display("Removed directory " + path)
+ except (IOError, OSError), e:
+ print "scons: Could not remove '%s':" % str(path), e.strerror
+
def show(self):
target = self.targets[0]
if (target.has_builder() or target.side_effect) and not target.isdir():
if SCons.Environment.CleanTargets.has_key(target):
files = SCons.Environment.CleanTargets[target]
for f in files:
- SCons.Util.fs_delete(str(f), 0)
+ self.fs_delete(str(f), 0)
def remove(self):
target = self.targets[0]
try:
removed = t.remove()
except OSError, e:
+ # An OSError may indicate something like a permissions
+ # issue, an IOError would indicate something like
+ # the file not existing. In either case, print a
+ # message and keep going to try to remove as many
+ # targets aa possible.
print "scons: Could not remove '%s':" % str(t), e.strerror
else:
if removed:
if SCons.Environment.CleanTargets.has_key(target):
files = SCons.Environment.CleanTargets[target]
for f in files:
- SCons.Util.fs_delete(str(f))
+ self.fs_delete(str(f))
execute = remove
try:
dirs = os.listdir('/opt')
-except OSError:
+except (IOError, OSError):
+ # Not being able to read the directory because it doesn't exist
+ # (IOError) or isn't readable (OSError) is okay.
dirs = []
for dir in dirs:
try:
dirs = os.listdir('/opt')
-except OSError:
+except (IOError, OSError):
+ # Not being able to read the directory because it doesn't exist
+ # (IOError) or isn't readable (OSError) is okay.
dirs = []
for dir in dirs:
try:
dirs = os.listdir('/opt')
-except OSError:
+except (IOError, OSError):
+ # Not being able to read the directory because it doesn't exist
+ # (IOError) or isn't readable (OSError) is okay.
dirs = []
for d in dirs:
try:
st = os.stat(f)
except OSError:
+ # os.stat() raises OSError, not IOError if the file
+ # doesn't exist, so in this case we let IOError get
+ # raised so as to not mask possibly serious disk or
+ # network issues.
continue
if stat.S_IMODE(st[stat.ST_MODE]) & 0111:
try:
else:
return string.join(paths, sep)
-
-def dir_index(directory):
- files = []
- for f in os.listdir(directory):
- fullname = os.path.join(directory, f)
- files.append(fullname)
-
- # os.listdir() isn't guaranteed to return files in any specific order,
- # but some of the test code expects sorted output.
- files.sort()
- return files
-
-def fs_delete(path, remove=1):
- try:
- if os.path.exists(path):
- if os.path.isfile(path):
- if remove: os.unlink(path)
- display("Removed " + path)
- elif os.path.isdir(path) and not os.path.islink(path):
- # delete everything in the dir
- for p in dir_index(path):
- if os.path.isfile(p):
- if remove: os.unlink(p)
- display("Removed " + p)
- else:
- fs_delete(p, remove)
- # then delete dir itself
- if remove: os.rmdir(path)
- display("Removed directory " + path)
- except OSError, e:
- print "scons: Could not remove '%s':" % str(path), e.strerror
-
if sys.platform == 'cygwin':
def get_native_path(path):
"""Transforms an absolute path into a native path for the system. In
assert sys.stdout.buffer == "line1\nline3\nline4\n"
sys.stdout = old_stdout
- def test_fs_delete(self):
- test = TestCmd.TestCmd(workdir = '')
- base = test.workpath('')
- xxx = test.workpath('xxx.xxx')
- ZZZ = test.workpath('ZZZ.ZZZ')
- sub1_yyy = test.workpath('sub1', 'yyy.yyy')
-
- test.subdir('sub1')
- test.write(xxx, "\n")
- test.write(ZZZ, "\n")
- test.write(sub1_yyy, "\n")
-
- old_stdout = sys.stdout
- sys.stdout = OutBuffer()
-
- exp = "Removed " + os.path.join(base, ZZZ) + "\n" + \
- "Removed " + os.path.join(base, sub1_yyy) + '\n' + \
- "Removed directory " + os.path.join(base, 'sub1') + '\n' + \
- "Removed " + os.path.join(base, xxx) + '\n' + \
- "Removed directory " + base + '\n'
-
- fs_delete(base, remove=0)
- assert sys.stdout.buffer == exp, sys.stdout.buffer
- assert os.path.exists(sub1_yyy)
-
- sys.stdout.buffer = ""
- fs_delete(base, remove=1)
- assert sys.stdout.buffer == exp
- assert not os.path.exists(base)
-
- test._dirlist = None
- sys.stdout = old_stdout
-
def test_get_native_path(self):
"""Test the get_native_path() function."""
import tempfile