summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Node/FS.py
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2005-02-14 03:22:34 (GMT)
committerSteven Knight <knight@baldmt.com>2005-02-14 03:22:34 (GMT)
commit08d7c4cd103fb39b6010b980209a777ceea1ead2 (patch)
tree1fea16d051dcdb1147ced94deefb11fd31b151c5 /src/engine/SCons/Node/FS.py
parent35451af4f3052befef3b41b3a971b3a8025b0577 (diff)
downloadSCons-08d7c4cd103fb39b6010b980209a777ceea1ead2.zip
SCons-08d7c4cd103fb39b6010b980209a777ceea1ead2.tar.gz
SCons-08d7c4cd103fb39b6010b980209a777ceea1ead2.tar.bz2
Don't read up entire directories to decide if an Alias is up-to-date.
Diffstat (limited to 'src/engine/SCons/Node/FS.py')
-rw-r--r--src/engine/SCons/Node/FS.py81
1 files changed, 47 insertions, 34 deletions
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py
index 314faf8..cc0fe95 100644
--- a/src/engine/SCons/Node/FS.py
+++ b/src/engine/SCons/Node/FS.py
@@ -599,6 +599,16 @@ class Entry(Base):
time comes, and then call the same-named method in the transformed
class."""
+ def disambiguate(self):
+ if self.fs.isdir(self.abspath):
+ self.__class__ = Dir
+ self._morph()
+ else:
+ self.__class__ = File
+ self._morph()
+ self.clear()
+ return self
+
def rfile(self):
"""We're a generic Entry, but the caller is actually looking for
a File at this point, so morph into one."""
@@ -610,8 +620,7 @@ class Entry(Base):
def get_found_includes(self, env, scanner, path):
"""If we're looking for included files, it's because this Entry
is really supposed to be a File itself."""
- node = self.rfile()
- return node.get_found_includes(env, scanner, path)
+ return self.disambiguate().get_found_includes(env, scanner, path)
def scanner_key(self):
return self.get_suffix()
@@ -638,29 +647,13 @@ class Entry(Base):
"""Return if the Entry exists. Check the file system to see
what we should turn into first. Assume a file if there's no
directory."""
- if self.fs.isdir(self.abspath):
- self.__class__ = Dir
- self._morph()
- return Dir.exists(self)
- else:
- self.__class__ = File
- self._morph()
- self.clear()
- return File.exists(self)
+ return self.disambiguate().exists()
def calc_signature(self, calc=None):
"""Return the Entry's calculated signature. Check the file
system to see what we should turn into first. Assume a file if
there's no directory."""
- if self.fs.isdir(self.abspath):
- self.__class__ = Dir
- self._morph()
- return Dir.calc_signature(self, calc)
- else:
- self.__class__ = File
- self._morph()
- self.clear()
- return File.calc_signature(self, calc)
+ return self.disambiguate().calc_signature(calc)
def must_be_a_Dir(self):
"""Called to make sure a Node is a Dir. Since we're an
@@ -1180,6 +1173,9 @@ class Dir(Base):
self._sconsign = None
self.build_dirs = []
+ def disambiguate(self):
+ return self
+
def __clearRepositoryCache(self, duplicate=None):
"""Called when we change the repository(ies) for a directory.
This clears any cached information that is invalidated by changing
@@ -1256,19 +1252,33 @@ class Dir(Base):
self.implicit = []
self.implicit_dict = {}
self._children_reset()
- try:
- for filename in self.fs.listdir(self.abspath):
- if filename != '.sconsign':
- self.Entry(filename)
- except OSError:
- # Directory does not exist. No big deal
- pass
- keys = filter(lambda k: k != '.' and k != '..', self.entries.keys())
- kids = map(lambda x, s=self: s.entries[x], keys)
- def c(one, two):
- return cmp(one.abspath, two.abspath)
- kids.sort(c)
- self._add_child(self.implicit, self.implicit_dict, kids)
+
+ dont_scan = lambda k: k not in ['.', '..', '.sconsign']
+ deps = filter(dont_scan, self.entries.keys())
+ # keys() is going to give back the entries in an internal,
+ # unsorted order. Sort 'em so the order is deterministic.
+ deps.sort()
+ entries = map(lambda n, e=self.entries: e[n], deps)
+
+ self._add_child(self.implicit, self.implicit_dict, entries)
+
+ def get_found_includes(self, env, scanner, path):
+ """Return the included implicit dependencies in this file.
+ Cache results so we only scan the file once per path
+ regardless of how many times this information is requested.
+ __cacheable__"""
+ if not scanner:
+ return []
+ # Clear cached info for this Node. If we already visited this
+ # directory on our walk down the tree (because we didn't know at
+ # that point it was being used as the source for another Node)
+ # then we may have calculated build signature before realizing
+ # we had to scan the disk. Now that we have to, though, we need
+ # to invalidate the old calculated signature so that any node
+ # dependent on our directory structure gets one that includes
+ # info about everything on disk.
+ self.clear()
+ return scanner(self, env, path)
def build(self, **kw):
"""A null "builder" for directories."""
@@ -1295,7 +1305,7 @@ class Dir(Base):
for kid in self.children():
contents.write(kid.get_contents())
return contents.getvalue()
-
+
def prepare(self):
pass
@@ -1464,6 +1474,9 @@ class File(Base):
if not hasattr(self, '_local'):
self._local = 0
+ def disambiguate(self):
+ return self
+
def root(self):
return self.dir.root()