summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2005-05-13 01:44:10 (GMT)
committerSteven Knight <knight@baldmt.com>2005-05-13 01:44:10 (GMT)
commitf82f4ce830289473187299db9962f819ed74c877 (patch)
treef9abe466c67b9ca99adb91b2ff25529ca1096230
parentf431ccfa16fad1d0db1009eacfdace4f80e9195e (diff)
downloadSCons-f82f4ce830289473187299db9962f819ed74c877.zip
SCons-f82f4ce830289473187299db9962f819ed74c877.tar.gz
SCons-f82f4ce830289473187299db9962f819ed74c877.tar.bz2
Eliminate multiple calls to os.stat() to fetch file info.
-rw-r--r--src/engine/SCons/Node/FS.py53
-rw-r--r--src/engine/SCons/Node/FSTests.py78
-rw-r--r--src/engine/SCons/Script/Main.py17
-rw-r--r--src/engine/SCons/Script/SConscript.py5
-rw-r--r--src/engine/SCons/Tool/zip.py2
5 files changed, 128 insertions, 27 deletions
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py
index 9d7086c..f2234f7 100644
--- a/src/engine/SCons/Node/FS.py
+++ b/src/engine/SCons/Node/FS.py
@@ -175,9 +175,8 @@ Unlink = SCons.Action.Action(UnlinkFunc, None)
def MkdirFunc(target, source, env):
t = target[0]
- p = t.abspath
- if not t.fs.exists(p):
- t.fs.mkdir(p)
+ if not t.exists():
+ t.fs.mkdir(t.abspath)
return 0
Mkdir = SCons.Action.Action(MkdirFunc, None, presub=None)
@@ -469,14 +468,39 @@ class Base(SCons.Node.Node):
rstr = __str__
+ def stat(self):
+ "__cacheable__"
+ try: return self.fs.stat(self.abspath)
+ except os.error: return None
+
def exists(self):
"__cacheable__"
- return self.fs.exists(self.abspath)
+ return not self.stat() is None
def rexists(self):
"__cacheable__"
return self.rfile().exists()
+ def getmtime(self):
+ return self.stat()[stat.ST_MTIME]
+
+ def isdir(self):
+ st = self.stat()
+ return not st is None and stat.S_ISDIR(st[stat.ST_MODE])
+
+ def isfile(self):
+ st = self.stat()
+ return not st is None and stat.S_ISREG(st[stat.ST_MODE])
+
+ if hasattr(os, 'symlink'):
+ def islink(self):
+ try: st = self.fs.lstat(self.abspath)
+ except os.error: return 0
+ return stat.S_ISLNK(st[stat.ST_MODE])
+ else:
+ def islink(self):
+ return 0 # no symlinks
+
def is_under(self, dir):
if self is dir:
return 1
@@ -563,7 +587,7 @@ class Entry(Base):
class."""
def disambiguate(self):
- if self.fs.isdir(self.abspath):
+ if self.isdir():
self.__class__ = Dir
self._morph()
else:
@@ -594,15 +618,15 @@ class Entry(Base):
Since this should return the real contents from the file
system, we check to see into what sort of subclass we should
morph this Entry."""
- if self.fs.isfile(self.abspath):
+ if self.isfile():
self.__class__ = File
self._morph()
return self.get_contents()
- if self.fs.isdir(self.abspath):
+ if self.isdir():
self.__class__ = Dir
self._morph()
return self.get_contents()
- if self.fs.islink(self.abspath):
+ if self.islink():
return '' # avoid errors for dangling symlinks
raise AttributeError
@@ -667,6 +691,8 @@ class LocalFS:
return os.path.isfile(path)
def link(self, src, dst):
return os.link(src, dst)
+ def lstat(self, path):
+ return os.lstat(path)
def listdir(self, path):
return os.listdir(path)
def makedirs(self, path):
@@ -687,12 +713,9 @@ class LocalFS:
if hasattr(os, 'symlink'):
def islink(self, path):
return os.path.islink(path)
- def exists_or_islink(self, path):
- return os.path.exists(path) or os.path.islink(path)
else:
def islink(self, path):
return 0 # no symlinks
- exists_or_islink = exists
if not SCons.Memoize.has_metaclass:
_FSBase = LocalFS
@@ -1491,7 +1514,7 @@ class File(Base):
def get_timestamp(self):
if self.rexists():
- return self.fs.getmtime(self.rfile().abspath)
+ return self.rfile().getmtime()
else:
return 0
@@ -1593,13 +1616,13 @@ class File(Base):
# Push this file out to cache before the superclass Node.built()
# method has a chance to clear the build signature, which it
# will do if this file has a source scanner.
- if self.fs.CachePath and self.fs.exists(self.path):
+ if self.fs.CachePath and self.exists():
CachePush(self, [], None)
self.fs.clear_cache()
SCons.Node.Node.built(self)
def visited(self):
- if self.fs.CachePath and self.fs.cache_force and self.fs.exists(self.path):
+ if self.fs.CachePath and self.fs.cache_force and self.exists():
CachePush(self, None, None)
def has_src_builder(self):
@@ -1664,7 +1687,7 @@ class File(Base):
def remove(self):
"""Remove this file."""
- if self.fs.exists_or_islink(self.path):
+ if self.exists() or self.islink():
self.fs.unlink(self.path)
return 1
return None
diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py
index 935f0a2..8626185 100644
--- a/src/engine/SCons/Node/FSTests.py
+++ b/src/engine/SCons/Node/FSTests.py
@@ -605,6 +605,83 @@ class BuildDirTestCase(unittest.TestCase):
self.failIf(errors)
+class BaseTestCase(_tempdirTestCase):
+ def test_stat(self):
+ """Test the Base.stat() method"""
+ test = self.test
+ test.write("e1", "e1\n")
+ fs = SCons.Node.FS.FS()
+
+ e1 = fs.Entry('e1')
+ s = e1.stat()
+ assert not s is None, s
+
+ e2 = fs.Entry('e2')
+ s = e2.stat()
+ assert s is None, s
+
+ def test_getmtime(self):
+ """Test the Base.getmtime() method"""
+ test = self.test
+ test.write("file", "file\n")
+ fs = SCons.Node.FS.FS()
+
+ file = fs.Entry('file')
+ assert file.getmtime()
+
+ def test_isdir(self):
+ """Test the Base.isdir() method"""
+ test = self.test
+ test.subdir('dir')
+ test.write("file", "file\n")
+ fs = SCons.Node.FS.FS()
+
+ dir = fs.Entry('dir')
+ assert dir.isdir()
+
+ file = fs.Entry('file')
+ assert not file.isdir()
+
+ nonexistent = fs.Entry('nonexistent')
+ assert not nonexistent.isdir()
+
+ def test_isfile(self):
+ """Test the Base.isfile() method"""
+ test = self.test
+ test.subdir('dir')
+ test.write("file", "file\n")
+ fs = SCons.Node.FS.FS()
+
+ dir = fs.Entry('dir')
+ assert not dir.isfile()
+
+ file = fs.Entry('file')
+ assert file.isfile()
+
+ nonexistent = fs.Entry('nonexistent')
+ assert not nonexistent.isfile()
+
+ if hasattr(os, 'symlink'):
+ def test_islink(self):
+ """Test the Base.islink() method"""
+ test = self.test
+ test.subdir('dir')
+ test.write("file", "file\n")
+ test.symlink("symlink", "symlink")
+ fs = SCons.Node.FS.FS()
+
+ dir = fs.Entry('dir')
+ assert not dir.islink()
+
+ file = fs.Entry('file')
+ assert not file.islink()
+
+ symlink = fs.Entry('symlink')
+ assert symlink.islink()
+
+ nonexistent = fs.Entry('nonexistent')
+ assert not nonexistent.islink()
+
class FSTestCase(_tempdirTestCase):
def test_runTest(self):
"""Test FS (file system) Node operations
@@ -2625,6 +2702,7 @@ if __name__ == "__main__":
suite.addTest(SpecialAttrTestCase())
suite.addTest(SaveStringsTestCase())
tclasses = [
+ BaseTestCase,
FSTestCase,
DirTestCase,
RepositoryTestCase,
diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py
index fd2a914..7dcb987 100644
--- a/src/engine/SCons/Script/Main.py
+++ b/src/engine/SCons/Script/Main.py
@@ -191,16 +191,17 @@ class BuildTask(SCons.Taskmaster.Task):
class CleanTask(SCons.Taskmaster.Task):
"""An SCons clean task."""
def show(self):
- if (self.targets[0].has_builder() or self.targets[0].side_effect) \
- and not os.path.isdir(str(self.targets[0])):
- display("Removed " + str(self.targets[0]))
- if SCons.Environment.CleanTargets.has_key(self.targets[0]):
- files = SCons.Environment.CleanTargets[self.targets[0]]
+ target = self.targets[0]
+ if (target.has_builder() or target.side_effect) and not target.isdir():
+ display("Removed " + str(target))
+ if SCons.Environment.CleanTargets.has_key(target):
+ files = SCons.Environment.CleanTargets[target]
for f in files:
SCons.Util.fs_delete(str(f), 0)
def remove(self):
- if self.targets[0].has_builder() or self.targets[0].side_effect:
+ target = self.targets[0]
+ if target.has_builder() or target.side_effect:
for t in self.targets:
try:
removed = t.remove()
@@ -209,8 +210,8 @@ class CleanTask(SCons.Taskmaster.Task):
else:
if removed:
display("Removed " + str(t))
- if SCons.Environment.CleanTargets.has_key(self.targets[0]):
- files = SCons.Environment.CleanTargets[self.targets[0]]
+ if SCons.Environment.CleanTargets.has_key(target):
+ files = SCons.Environment.CleanTargets[target]
for f in files:
SCons.Util.fs_delete(str(f))
diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py
index 7ca9993..af9d492 100644
--- a/src/engine/SCons/Script/SConscript.py
+++ b/src/engine/SCons/Script/SConscript.py
@@ -184,9 +184,8 @@ def _SConscript(fs, *files, **kw):
# during the actual build phase.
f.build()
f.builder_set(None)
- s = str(f)
- if os.path.exists(s):
- _file_ = open(s, "r")
+ if f.exists():
+ _file_ = open(str(f), "r")
if _file_:
# Chdir to the SConscript directory. Use a path
# name relative to the SConstruct file so that if
diff --git a/src/engine/SCons/Tool/zip.py b/src/engine/SCons/Tool/zip.py
index fe9ce32..f0d4ed0 100644
--- a/src/engine/SCons/Tool/zip.py
+++ b/src/engine/SCons/Tool/zip.py
@@ -56,7 +56,7 @@ if internal_zip:
compression = env.get('ZIPCOMPRESSION', 0)
zf = zipfile.ZipFile(str(target[0]), 'w', compression)
for s in source:
- if os.path.isdir(str(s)):
+ if s.isdir():
os.path.walk(str(s), visit, zf)
else:
zf.write(str(s))