summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathew Robinson <chasinglogic@gmail.com>2019-01-17 11:17:09 -0500
committerMathew Robinson <chasinglogic@gmail.com>2019-01-17 11:17:09 -0500
commit1555206b9b015aca4673886c6d3822cf81a2bc38 (patch)
tree7332d12ce12e8771e0eb9af8ca8e125ec9bba94f
parent33dc565a28292f02b1a304c5c418463226fa7bcb (diff)
downloadmongo-1555206b9b015aca4673886c6d3822cf81a2bc38.tar.gz
WIP add stats collection decorator
-rw-r--r--src/third_party/scons-2.5.0/scons-local-2.5.0/SCons/Node/FS.py603
1 files changed, 339 insertions, 264 deletions
diff --git a/src/third_party/scons-2.5.0/scons-local-2.5.0/SCons/Node/FS.py b/src/third_party/scons-2.5.0/scons-local-2.5.0/SCons/Node/FS.py
index 952be01ca91..168e52f242c 100644
--- a/src/third_party/scons-2.5.0/scons-local-2.5.0/SCons/Node/FS.py
+++ b/src/third_party/scons-2.5.0/scons-local-2.5.0/SCons/Node/FS.py
@@ -71,6 +71,7 @@ print_duplicate = 0
def sconsign_none(node):
raise NotImplementedError
+
def sconsign_dir(node):
"""Return the .sconsign file info for this directory,
creating it first if necessary."""
@@ -79,28 +80,30 @@ def sconsign_dir(node):
node._sconsign = SCons.SConsign.ForDirectory(node)
return node._sconsign
-_sconsign_map = {0 : sconsign_none,
- 1 : sconsign_dir}
+
+_sconsign_map = {0: sconsign_none, 1: sconsign_dir}
+
class EntryProxyAttributeError(AttributeError):
"""
An AttributeError subclass for recording and displaying the name
of the underlying Entry involved in an AttributeError exception.
"""
+
def __init__(self, entry_proxy, attribute):
AttributeError.__init__(self)
self.entry_proxy = entry_proxy
self.attribute = attribute
+
def __str__(self):
entry = self.entry_proxy.get()
fmt = "%s instance %s has no attribute %s"
- return fmt % (entry.__class__.__name__,
- repr(entry.name),
- repr(self.attribute))
+ return fmt % (entry.__class__.__name__, repr(entry.name), repr(self.attribute))
+
# The max_drift value: by default, use a cached signature value for
# any file that's been untouched for more than two days.
-default_max_drift = 2*24*60*60
+default_max_drift = 2 * 24 * 60 * 60
#
# We stringify these file system Nodes a lot. Turning a file system Node
@@ -122,19 +125,22 @@ default_max_drift = 2*24*60*60
#
Save_Strings = None
+
def save_strings(val):
global Save_Strings
Save_Strings = val
+
#
# Avoid unnecessary function calls by recording a Boolean value that
# tells us whether or not os.path.splitdrive() actually does anything
# on this system, and therefore whether we need to bother calling it
# when looking up path names in various methods below.
-#
+#
do_splitdrive = None
-_my_splitdrive =None
+_my_splitdrive = None
+
def initialize_do_splitdrive():
global do_splitdrive
@@ -146,6 +152,7 @@ def initialize_do_splitdrive():
global _my_splitdrive
if has_unc:
+
def splitdrive(p):
if p[1:2] == ':':
return p[:2], p[2:]
@@ -155,10 +162,12 @@ def initialize_do_splitdrive():
return '//', p[1:]
return '', p
else:
+
def splitdrive(p):
if p[1:2] == ':':
return p[:2], p[2:]
return '', p
+
_my_splitdrive = splitdrive
# Keep some commonly used values in global variables to skip to
@@ -166,16 +175,16 @@ def initialize_do_splitdrive():
global OS_SEP
global UNC_PREFIX
global os_sep_is_slash
-
+
OS_SEP = os.sep
UNC_PREFIX = OS_SEP + OS_SEP
os_sep_is_slash = OS_SEP == '/'
+
initialize_do_splitdrive()
# Used to avoid invoking os.path.normpath if not necessary.
-needs_normpath_check = re.compile(
- r'''
+needs_normpath_check = re.compile(r'''
# We need to renormalize the path if it contains any consecutive
# '/' characters.
.*// |
@@ -187,7 +196,7 @@ needs_normpath_check = re.compile(
# b) The path starts with '..'. E.g. '../' or '../moredirs'
# but we not match '..abc/'.
# c) The path ends with '..'. E.g. '/..' or 'dirs/..'
- # d) The path contains a '..' in the middle.
+ # d) The path contains a '..' in the middle.
# E.g. dirs/../moredirs
(.*/)?\.\.(?:/|$) |
@@ -209,9 +218,7 @@ needs_normpath_check = re.compile(
\./|.*/\.(?:/|$)
- ''',
- re.VERBOSE
- )
+ ''', re.VERBOSE)
needs_normpath_match = needs_normpath_check.match
#
@@ -229,6 +236,7 @@ needs_normpath_match = needs_normpath_check.match
#
if hasattr(os, 'link'):
+
def _hardlink_func(fs, src, dst):
# If the source is a symlink, we can't just hard-link to it
# because a relative symlink may point somewhere completely
@@ -245,21 +253,23 @@ else:
_hardlink_func = None
if hasattr(os, 'symlink'):
+
def _softlink_func(fs, src, dst):
fs.symlink(src, dst)
else:
_softlink_func = None
+
def _copy_func(fs, src, dest):
_copy2(src, dest)
st = fs.stat(src)
fs.chmod(dest, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
-Valid_Duplicates = ['hard-soft-copy', 'soft-hard-copy',
- 'hard-copy', 'soft-copy', 'copy']
+Valid_Duplicates = ['hard-soft-copy', 'soft-hard-copy', 'hard-copy', 'soft-copy', 'copy']
+
+Link_Funcs = [] # contains the callables of the specified duplication style
-Link_Funcs = [] # contains the callables of the specified duplication style
def set_duplicate(duplicate):
# Fill in the Link_Funcs list according to the argument
@@ -269,21 +279,18 @@ def set_duplicate(duplicate):
# underlying implementations. We do this inside this function,
# not in the top-level module code, so that we can remap os.link
# and os.symlink for testing purposes.
- link_dict = {
- 'hard' : _hardlink_func,
- 'soft' : _softlink_func,
- 'copy' : _copy_func
- }
+ link_dict = {'hard': _hardlink_func, 'soft': _softlink_func, 'copy': _copy_func}
if not duplicate in Valid_Duplicates:
raise SCons.Errors.InternalError("The argument of set_duplicate "
- "should be in Valid_Duplicates")
+ "should be in Valid_Duplicates")
global Link_Funcs
Link_Funcs = []
for func in duplicate.split('-'):
if link_dict[func]:
Link_Funcs.append(link_dict[func])
+
def LinkFunc(target, source, env):
# Relative paths cause problems with symbolic links, so
# we use absolute paths, which may be a problem for people
@@ -316,29 +323,38 @@ def LinkFunc(target, source, env):
raise
return 0
+
Link = SCons.Action.Action(LinkFunc, None)
+
+
def LocalString(target, source, env):
return 'Local copy of %s from %s' % (target[0], source[0])
+
LocalCopy = SCons.Action.Action(LinkFunc, LocalString)
+
def UnlinkFunc(target, source, env):
t = target[0]
t.fs.unlink(t.get_abspath())
return 0
+
Unlink = SCons.Action.Action(UnlinkFunc, None)
+
def MkdirFunc(target, source, env):
t = target[0]
if not t.exists():
t.fs.mkdir(t.get_abspath())
return 0
+
Mkdir = SCons.Action.Action(MkdirFunc, None, presub=None)
MkdirBuilder = None
+
def get_MkdirBuilder():
global MkdirBuilder
if MkdirBuilder is None:
@@ -346,22 +362,22 @@ def get_MkdirBuilder():
import SCons.Defaults
# "env" will get filled in by Executor.get_build_env()
# calling SCons.Defaults.DefaultEnvironment() when necessary.
- MkdirBuilder = SCons.Builder.Builder(action = Mkdir,
- env = None,
- explain = None,
- is_explicit = None,
- target_scanner = SCons.Defaults.DirEntryScanner,
- name = "MkdirBuilder")
+ MkdirBuilder = SCons.Builder.Builder(action=Mkdir, env=None, explain=None, is_explicit=None,
+ target_scanner=SCons.Defaults.DirEntryScanner,
+ name="MkdirBuilder")
return MkdirBuilder
+
class _Null(object):
pass
+
_null = _Null()
DefaultSCCSBuilder = None
DefaultRCSBuilder = None
+
def get_DefaultSCCSBuilder():
global DefaultSCCSBuilder
if DefaultSCCSBuilder is None:
@@ -369,11 +385,10 @@ def get_DefaultSCCSBuilder():
# "env" will get filled in by Executor.get_build_env()
# calling SCons.Defaults.DefaultEnvironment() when necessary.
act = SCons.Action.Action('$SCCSCOM', '$SCCSCOMSTR')
- DefaultSCCSBuilder = SCons.Builder.Builder(action = act,
- env = None,
- name = "DefaultSCCSBuilder")
+ DefaultSCCSBuilder = SCons.Builder.Builder(action=act, env=None, name="DefaultSCCSBuilder")
return DefaultSCCSBuilder
+
def get_DefaultRCSBuilder():
global DefaultRCSBuilder
if DefaultRCSBuilder is None:
@@ -381,36 +396,39 @@ def get_DefaultRCSBuilder():
# "env" will get filled in by Executor.get_build_env()
# calling SCons.Defaults.DefaultEnvironment() when necessary.
act = SCons.Action.Action('$RCS_COCOM', '$RCS_COCOMSTR')
- DefaultRCSBuilder = SCons.Builder.Builder(action = act,
- env = None,
- name = "DefaultRCSBuilder")
+ DefaultRCSBuilder = SCons.Builder.Builder(action=act, env=None, name="DefaultRCSBuilder")
return DefaultRCSBuilder
+
# Cygwin's os.path.normcase pretends it's on a case-sensitive filesystem.
_is_cygwin = sys.platform == "cygwin"
if os.path.normcase("TeSt") == os.path.normpath("TeSt") and not _is_cygwin:
+
def _my_normcase(x):
return x
else:
+
def _my_normcase(x):
return x.upper()
-
class DiskChecker(object):
def __init__(self, type, do, ignore):
self.type = type
self.do = do
self.ignore = ignore
self.func = do
+
def __call__(self, *args, **kw):
return self.func(*args, **kw)
+
def set(self, list):
if self.type in list:
self.func = self.do
else:
self.func = self.ignore
+
def do_diskcheck_match(node, predicate, errorfmt):
result = predicate()
try:
@@ -427,9 +445,11 @@ def do_diskcheck_match(node, predicate, errorfmt):
if result:
raise TypeError(errorfmt % node.get_abspath())
+
def ignore_diskcheck_match(node, predicate, errorfmt):
pass
+
def do_diskcheck_rcs(node, name):
try:
rcs_dir = node.rcs_dir
@@ -440,12 +460,14 @@ def do_diskcheck_rcs(node, name):
rcs_dir = None
node.rcs_dir = rcs_dir
if rcs_dir:
- return rcs_dir.entry_exists_on_disk(name+',v')
+ return rcs_dir.entry_exists_on_disk(name + ',v')
return None
+
def ignore_diskcheck_rcs(node, name):
return None
+
def do_diskcheck_sccs(node, name):
try:
sccs_dir = node.sccs_dir
@@ -456,12 +478,14 @@ def do_diskcheck_sccs(node, name):
sccs_dir = None
node.sccs_dir = sccs_dir
if sccs_dir:
- return sccs_dir.entry_exists_on_disk('s.'+name)
+ return sccs_dir.entry_exists_on_disk('s.' + name)
return None
+
def ignore_diskcheck_sccs(node, name):
return None
+
diskcheck_match = DiskChecker('match', do_diskcheck_match, ignore_diskcheck_match)
diskcheck_rcs = DiskChecker('rcs', do_diskcheck_rcs, ignore_diskcheck_rcs)
diskcheck_sccs = DiskChecker('sccs', do_diskcheck_sccs, ignore_diskcheck_sccs)
@@ -472,33 +496,31 @@ diskcheckers = [
diskcheck_sccs,
]
+
def set_diskcheck(list):
for dc in diskcheckers:
dc.set(list)
+
def diskcheck_types():
return [dc.type for dc in diskcheckers]
-
class EntryProxy(SCons.Util.Proxy):
__str__ = SCons.Util.Delegate('__str__')
def __get_abspath(self):
entry = self.get()
- return SCons.Subst.SpecialAttrWrapper(entry.get_abspath(),
- entry.name + "_abspath")
+ return SCons.Subst.SpecialAttrWrapper(entry.get_abspath(), entry.name + "_abspath")
def __get_filebase(self):
name = self.get().name
- return SCons.Subst.SpecialAttrWrapper(SCons.Util.splitext(name)[0],
- name + "_filebase")
+ return SCons.Subst.SpecialAttrWrapper(SCons.Util.splitext(name)[0], name + "_filebase")
def __get_suffix(self):
name = self.get().name
- return SCons.Subst.SpecialAttrWrapper(SCons.Util.splitext(name)[1],
- name + "_suffix")
+ return SCons.Subst.SpecialAttrWrapper(SCons.Util.splitext(name)[1], name + "_suffix")
def __get_file(self):
name = self.get().name
@@ -508,8 +530,8 @@ class EntryProxy(SCons.Util.Proxy):
"""Return the file's directory and file name, with the
suffix stripped."""
entry = self.get()
- return SCons.Subst.SpecialAttrWrapper(SCons.Util.splitext(entry.get_path())[0],
- entry.name + "_base")
+ return SCons.Subst.SpecialAttrWrapper(
+ SCons.Util.splitext(entry.get_path())[0], entry.name + "_base")
def __get_posix_path(self):
"""Return the path with / as the path separator,
@@ -550,20 +572,21 @@ class EntryProxy(SCons.Util.Proxy):
def __get_dir(self):
return EntryProxy(self.get().dir)
- dictSpecialAttrs = { "base" : __get_base_path,
- "posix" : __get_posix_path,
- "windows" : __get_windows_path,
- "win32" : __get_windows_path,
- "srcpath" : __get_srcnode,
- "srcdir" : __get_srcdir,
- "dir" : __get_dir,
- "abspath" : __get_abspath,
- "filebase" : __get_filebase,
- "suffix" : __get_suffix,
- "file" : __get_file,
- "rsrcpath" : __get_rsrcnode,
- "rsrcdir" : __get_rsrcdir,
- }
+ dictSpecialAttrs = {
+ "base": __get_base_path,
+ "posix": __get_posix_path,
+ "windows": __get_windows_path,
+ "win32": __get_windows_path,
+ "srcpath": __get_srcnode,
+ "srcdir": __get_srcdir,
+ "dir": __get_dir,
+ "abspath": __get_abspath,
+ "filebase": __get_filebase,
+ "suffix": __get_suffix,
+ "file": __get_file,
+ "rsrcpath": __get_rsrcnode,
+ "rsrcdir": __get_rsrcdir,
+ }
def __getattr__(self, name):
# This is how we implement the "special" attributes
@@ -582,6 +605,7 @@ class EntryProxy(SCons.Util.Proxy):
else:
return attr_function(self)
+
class Base(SCons.Node.Node):
"""A generic class for file system entries. This class is for
when we don't know yet whether the entry being looked up is a file
@@ -595,20 +619,10 @@ class Base(SCons.Node.Node):
object identity comparisons.
"""
- __slots__ = ['name',
- 'fs',
- '_abspath',
- '_labspath',
- '_path',
- '_tpath',
- '_path_elements',
- 'dir',
- 'cwd',
- 'duplicate',
- '_local',
- 'sbuilder',
- '_proxy',
- '_func_sconsign']
+ __slots__ = [
+ 'name', 'fs', '_abspath', '_labspath', '_path', '_tpath', '_path_elements', 'dir', 'cwd',
+ 'duplicate', '_local', 'sbuilder', '_proxy', '_func_sconsign'
+ ]
def __init__(self, name, directory, fs):
"""Initialize a generic Node.FS.Base object.
@@ -626,7 +640,7 @@ class Base(SCons.Node.Node):
#: Filename with extension as it was specified when the object was
#: created; to obtain filesystem path, use Python str() function
self.name = SCons.Util.silent_intern(name)
- self.fs = fs #: Reference to parent Node.FS object
+ self.fs = fs #: Reference to parent Node.FS object
assert directory, "A directory must be provided"
@@ -637,7 +651,7 @@ class Base(SCons.Node.Node):
self._path_elements = None
self.dir = directory
- self.cwd = None # will hold the SConscript directory for target nodes
+ self.cwd = None # will hold the SConscript directory for target nodes
self.duplicate = directory.duplicate
self.changed_since_last_build = 2
self._func_sconsign = 0
@@ -679,16 +693,15 @@ class Base(SCons.Node.Node):
single variables lazily when required, in order to save memory.
The redirection to the getters lets older Tools and
SConstruct continue to work without any additional changes,
- fully transparent to the user.
+ fully transparent to the user.
Note, that __getattr__ is only called as fallback when the
requested attribute can't be found, so there should be no
speed performance penalty involved for standard builds.
"""
if attr in node_bwcomp:
return node_bwcomp[attr](self)
-
- raise AttributeError("%r object has no attribute %r" %
- (self.__class__, attr))
+
+ raise AttributeError("%r object has no attribute %r" % (self.__class__, attr))
def __str__(self):
"""A Node.FS.Base object's string representation is its path
@@ -726,21 +739,29 @@ class Base(SCons.Node.Node):
# Python code in the SConscript files might still create
# or otherwise affect the on-disk file. So get rid of the
# values that the underlying stat() method saved.
- try: del self._memo['stat']
- except KeyError: pass
+ try:
+ del self._memo['stat']
+ except KeyError:
+ pass
if self is not srcnode:
- try: del srcnode._memo['stat']
- except KeyError: pass
+ try:
+ del srcnode._memo['stat']
+ except KeyError:
+ pass
return result
rstr = __str__
@SCons.Memoize.CountMethodCall
def stat(self):
- try: return self._memo['stat']
- except KeyError: pass
- try: result = self.fs.stat(self.get_abspath())
- except os.error: result = None
+ try:
+ return self._memo['stat']
+ except KeyError:
+ pass
+ try:
+ result = self.fs.stat(self.get_abspath())
+ except os.error:
+ result = None
self._memo['stat'] = result
return result
@@ -769,13 +790,17 @@ class Base(SCons.Node.Node):
return st is not None and stat.S_ISREG(st[stat.ST_MODE])
if hasattr(os, 'symlink'):
+
def islink(self):
- try: st = self.fs.lstat(self.get_abspath())
- except os.error: return 0
+ try:
+ st = self.fs.lstat(self.get_abspath())
+ except os.error:
+ return 0
return stat.S_ISLNK(st[stat.ST_MODE])
else:
+
def islink(self):
- return 0 # no symlinks
+ return 0 # no symlinks
def is_under(self, dir):
if self is dir:
@@ -807,12 +832,13 @@ class Base(SCons.Node.Node):
return '.'
path_elems = self.get_path_elements()
pathname = ''
- try: i = path_elems.index(dir)
- except ValueError:
+ try:
+ i = path_elems.index(dir)
+ except ValueError:
for p in path_elems[:-1]:
pathname += p.dirname
else:
- for p in path_elems[i+1:-1]:
+ for p in path_elems[i + 1:-1]:
pathname += p.dirname
return pathname + path_elems[-1].name
@@ -849,13 +875,13 @@ class Base(SCons.Node.Node):
return self.name
else:
return self.dir.entry_path(self.name)
-
+
def get_tpath(self):
if self.dir._tpath == '.':
return self.name
else:
return self.dir.entry_tpath(self.name)
-
+
def get_path_elements(self):
return self.dir._path_elements + [self]
@@ -883,7 +909,8 @@ class Base(SCons.Node.Node):
files that need different behavior. See Tool/swig.py for
an example.
"""
- return SCons.Node._target_from_source_map[self._func_target_from_source](self, prefix, suffix, splitext)
+ return SCons.Node._target_from_source_map[self._func_target_from_source](self, prefix,
+ suffix, splitext)
def _Rfindalldirs_key(self, pathlist):
return pathlist
@@ -948,17 +975,17 @@ class Base(SCons.Node.Node):
def _glob1(self, pattern, ondisk=True, source=False, strings=False):
return []
-
+
+
# Dict that provides a simple backward compatibility
# layer for the Node attributes 'abspath', 'labspath',
# 'path', 'tpath' and 'path_elements'.
# @see Base.__getattr__ above
-node_bwcomp = {'abspath' : Base.get_abspath,
- 'labspath' : Base.get_labspath,
- 'path' : Base.get_internal_path,
- 'tpath' : Base.get_tpath,
- 'path_elements' : Base.get_path_elements,
- 'suffix' : Base.get_suffix}
+node_bwcomp = {
+ 'abspath': Base.get_abspath, 'labspath': Base.get_labspath, 'path': Base.get_internal_path,
+ 'tpath': Base.get_tpath, 'path_elements': Base.get_path_elements, 'suffix': Base.get_suffix
+}
+
class Entry(Base):
"""This is the class for generic Node.FS entries--that is, things
@@ -968,27 +995,16 @@ class Entry(Base):
time comes, and then call the same-named method in the transformed
class."""
- __slots__ = ['scanner_paths',
- 'cachedir_csig',
- 'cachesig',
- 'repositories',
- 'srcdir',
- 'entries',
- 'searched',
- '_sconsign',
- 'variant_dirs',
- 'root',
- 'dirname',
- 'on_disk_entries',
- 'sccs_dir',
- 'rcs_dir',
- 'released_target_info',
- 'contentsig']
+ __slots__ = [
+ 'scanner_paths', 'cachedir_csig', 'cachesig', 'repositories', 'srcdir', 'entries',
+ 'searched', '_sconsign', 'variant_dirs', 'root', 'dirname', 'on_disk_entries', 'sccs_dir',
+ 'rcs_dir', 'released_target_info', 'contentsig'
+ ]
def __init__(self, name, directory, fs):
Base.__init__(self, name, directory, fs)
self._func_exists = 3
- self._func_get_contents = 1
+ self._func_get_contents = 1
def diskcheck_match(self):
pass
@@ -1099,6 +1115,7 @@ class Entry(Base):
def get_subst_proxy(self):
return self.disambiguate().get_subst_proxy()
+
# This is for later so we can differentiate between Entry the class and Entry
# the method of the FS class.
_classEntry = Entry
@@ -1124,59 +1141,79 @@ class LocalFS(object):
# return os.chdir(path)
def chmod(self, path, mode):
return os.chmod(path, mode)
+
def copy(self, src, dst):
return _copy(src, dst)
+
def copy2(self, src, dst):
return _copy2(src, dst)
+
def exists(self, path):
return os.path.exists(path)
+
def getmtime(self, path):
return os.path.getmtime(path)
+
def getsize(self, path):
return os.path.getsize(path)
+
def isdir(self, path):
return os.path.isdir(path)
+
def isfile(self, path):
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):
return os.makedirs(path)
+
def mkdir(self, path):
return os.mkdir(path)
+
def rename(self, old, new):
return os.rename(old, new)
+
def stat(self, path):
return os.stat(path)
+
def symlink(self, src, dst):
return os.symlink(src, dst)
+
def open(self, path):
return open(path)
+
def unlink(self, path):
return os.unlink(path)
if hasattr(os, 'symlink'):
+
def islink(self, path):
return os.path.islink(path)
else:
+
def islink(self, path):
- return 0 # no symlinks
+ return 0 # no symlinks
if hasattr(os, 'readlink'):
+
def readlink(self, file):
return os.readlink(file)
else:
+
def readlink(self, file):
return ''
class FS(LocalFS):
-
- def __init__(self, path = None):
+ def __init__(self, path=None):
"""Initialize the Node.FS subsystem.
The supplied path is the top of the source tree, where we
@@ -1207,7 +1244,7 @@ class FS(LocalFS):
DirNodeInfo.fs = self
FileNodeInfo.fs = self
-
+
def set_SConstruct_dir(self, dir):
self.SConstruct_dir = dir
@@ -1219,16 +1256,16 @@ class FS(LocalFS):
def getcwd(self):
if hasattr(self, "_cwd"):
- return self._cwd
+ return self._cwd
else:
- return "<no cwd>"
+ return "<no cwd>"
def chdir(self, dir, change_os_dir=0):
"""Change the current working directory for lookups.
If change_os_dir is true, we will also change the "real" cwd
to match.
"""
- curr=self._cwd
+ curr = self._cwd
try:
if dir is not None:
self._cwd = dir
@@ -1319,7 +1356,7 @@ class FS(LocalFS):
p = p.strip('/')
needs_normpath = needs_normpath_match(p)
-
+
# The path is relative to the top-level SCons directory.
if p in ('', '.'):
p = directory.get_labspath()
@@ -1391,7 +1428,7 @@ class FS(LocalFS):
return root._lookup_abs(p, fsclass, create)
- def Entry(self, name, directory = None, create = 1):
+ def Entry(self, name, directory=None, create=1):
"""Look up or create a generic Entry node with the specified name.
If the name is a relative path (begins with ./, ../, or a file
name), then it is looked up relative to the supplied directory
@@ -1400,7 +1437,7 @@ class FS(LocalFS):
"""
return self._lookup(name, directory, Entry, create)
- def File(self, name, directory = None, create = 1):
+ def File(self, name, directory=None, create=1):
"""Look up or create a File node with the specified name. If
the name is a relative path (begins with ./, ../, or a file name),
then it is looked up relative to the supplied directory node,
@@ -1412,7 +1449,7 @@ class FS(LocalFS):
"""
return self._lookup(name, directory, File, create)
- def Dir(self, name, directory = None, create = True):
+ def Dir(self, name, directory=None, create=True):
"""Look up or create a Dir node with the specified name. If
the name is a relative path (begins with ./, ../, or a file name),
then it is looked up relative to the supplied directory node,
@@ -1436,8 +1473,9 @@ class FS(LocalFS):
raise SCons.Errors.UserError("Source directory cannot be under variant directory.")
if variant_dir.srcdir:
if variant_dir.srcdir == src_dir:
- return # We already did this.
- raise SCons.Errors.UserError("'%s' already has a source directory: '%s'."%(variant_dir, variant_dir.srcdir))
+ return # We already did this.
+ raise SCons.Errors.UserError("'%s' already has a source directory: '%s'." %
+ (variant_dir, variant_dir.srcdir))
variant_dir.link(src_dir, duplicate)
def Repository(self, *dirs):
@@ -1478,12 +1516,13 @@ class FS(LocalFS):
"""
Globs
- This is mainly a shim layer
+ This is mainly a shim layer
"""
if cwd is None:
cwd = self.getcwd()
return cwd.glob(pathname, ondisk, source, strings, exclude)
+
class DirNodeInfo(SCons.Node.NodeInfoBase):
__slots__ = ()
# This should get reset by the FS initialization.
@@ -1502,35 +1541,28 @@ class DirNodeInfo(SCons.Node.NodeInfoBase):
s = top.get_labspath() + '/' + s
return root._lookup_abs(s, Entry)
+
class DirBuildInfo(SCons.Node.BuildInfoBase):
__slots__ = ()
current_version_id = 2
+
glob_magic_check = re.compile('[*?[]')
+
def has_glob_magic(s):
return glob_magic_check.search(s) is not None
+
class Dir(Base):
"""A class for directories in a file system.
"""
- __slots__ = ['scanner_paths',
- 'cachedir_csig',
- 'cachesig',
- 'repositories',
- 'srcdir',
- 'entries',
- 'searched',
- '_sconsign',
- 'variant_dirs',
- 'root',
- 'dirname',
- 'on_disk_entries',
- 'sccs_dir',
- 'rcs_dir',
- 'released_target_info',
- 'contentsig']
+ __slots__ = [
+ 'scanner_paths', 'cachedir_csig', 'cachesig', 'repositories', 'srcdir', 'entries',
+ 'searched', '_sconsign', 'variant_dirs', 'root', 'dirname', 'on_disk_entries', 'sccs_dir',
+ 'rcs_dir', 'released_target_info', 'contentsig'
+ ]
NodeInfo = DirNodeInfo
BuildInfo = DirBuildInfo
@@ -1564,7 +1596,7 @@ class Dir(Base):
self._func_sconsign = 1
self._func_exists = 2
self._func_get_contents = 2
-
+
self._abspath = SCons.Util.silent_intern(self.dir.entry_abspath(self.name))
self._labspath = SCons.Util.silent_intern(self.dir.entry_labspath(self.name))
if self.dir._path == '.':
@@ -1603,12 +1635,11 @@ class Dir(Base):
# Prepend MkdirBuilder action to existing action list
l = self.get_executor().action_list
a = get_MkdirBuilder().action
- l.insert(0, a)
+ l.insert(0, a)
self.get_executor().set_action_list(l)
def diskcheck_match(self):
- diskcheck_match(self, self.isfile,
- "File %s found where directory expected.")
+ diskcheck_match(self, self.isfile, "File %s found where directory expected.")
def __clearRepositoryCache(self, duplicate=None):
"""Called when we change the repository(ies) for a directory.
@@ -1626,7 +1657,7 @@ class Dir(Base):
except AttributeError:
pass
if duplicate is not None:
- node.duplicate=duplicate
+ node.duplicate = duplicate
def __resetDuplicate(self, node):
if node != self:
@@ -1751,7 +1782,7 @@ class Dir(Base):
path_elems = ['..'] * (len(self._path_elements) - i) \
+ [n.name for n in other._path_elements[i:]]
-
+
result = OS_SEP.join(path_elems)
memo_dict[other] = result
@@ -1886,11 +1917,13 @@ class Dir(Base):
if not self.exists():
norm_name = _my_normcase(self.name)
for dir in self.dir.get_all_rdirs():
- try: node = dir.entries[norm_name]
- except KeyError: node = dir.dir_on_disk(self.name)
+ try:
+ node = dir.entries[norm_name]
+ except KeyError:
+ node = dir.dir_on_disk(self.name)
if node and node.exists() and \
(isinstance(dir, Dir) or isinstance(dir, Entry)):
- return node
+ return node
return self
def sconsign(self):
@@ -1922,10 +1955,10 @@ class Dir(Base):
def get_internal_path(self):
return self._path
-
+
def get_tpath(self):
return self._tpath
-
+
def get_path_elements(self):
return self._path_elements
@@ -1945,7 +1978,7 @@ class Dir(Base):
""" Searches through the file/dir entries of the current
directory, and returns True if a physical entry with the given
name could be found.
-
+
@see rentry_exists_on_disk
"""
try:
@@ -1979,10 +2012,10 @@ class Dir(Base):
The local directory (self) gets searched first, so
repositories take a lower precedence regarding the
searching order.
-
+
@see entry_exists_on_disk
"""
-
+
rentry_exists = self.entry_exists_on_disk(name)
if not rentry_exists:
# Search through the repository folders
@@ -2056,15 +2089,18 @@ class Dir(Base):
def func(node):
if (isinstance(node, File) or isinstance(node, Entry)) and \
(node.is_derived() or node.exists()):
- return node
+ return node
return None
norm_name = _my_normcase(filename)
for rdir in self.get_all_rdirs():
- try: node = rdir.entries[norm_name]
- except KeyError: node = rdir.file_on_disk(filename)
- else: node = func(node)
+ try:
+ node = rdir.entries[norm_name]
+ except KeyError:
+ node = rdir.file_on_disk(filename)
+ else:
+ node = func(node)
if node:
result = (node, self)
memo_dict[filename] = result
@@ -2072,9 +2108,12 @@ class Dir(Base):
for srcdir in self.srcdir_list():
for rdir in srcdir.get_all_rdirs():
- try: node = rdir.entries[norm_name]
- except KeyError: node = rdir.file_on_disk(filename)
- else: node = func(node)
+ try:
+ node = rdir.entries[norm_name]
+ except KeyError:
+ node = rdir.file_on_disk(filename)
+ else:
+ node = func(node)
if node:
result = (File(filename, self, self.fs), srcdir)
memo_dict[filename] = result
@@ -2086,8 +2125,10 @@ class Dir(Base):
def dir_on_disk(self, name):
if self.entry_exists_on_disk(name):
- try: return self.Dir(name)
- except TypeError: pass
+ try:
+ return self.Dir(name)
+ except TypeError:
+ pass
node = self.srcdir_duplicate(name)
if isinstance(node, File):
return None
@@ -2097,8 +2138,10 @@ class Dir(Base):
if self.entry_exists_on_disk(name) or \
diskcheck_rcs(self, name) or \
diskcheck_sccs(self, name):
- try: return self.File(name)
- except TypeError: pass
+ try:
+ return self.File(name)
+ except TypeError:
+ pass
node = self.srcdir_duplicate(name)
if isinstance(node, Dir):
return None
@@ -2211,13 +2254,13 @@ class Dir(Base):
# We use the .name attribute from the Node because the keys of
# the dir.entries dictionary are normalized (that is, all upper
# case) on case-insensitive systems like Windows.
- node_names = [ v.name for k, v in dir.entries.items()
- if k not in ('.', '..') ]
+ node_names = [v.name for k, v in dir.entries.items() if k not in ('.', '..')]
names.extend(node_names)
if not strings:
# Make sure the working directory (self) actually has
# entries for all Nodes in repositories or variant dirs.
- for name in node_names: selfEntry(name)
+ for name in node_names:
+ selfEntry(name)
if ondisk:
try:
disk_names = os.listdir(dir._abspath)
@@ -2257,6 +2300,7 @@ class Dir(Base):
return [self.entries[_my_normcase(n)] for n in names]
+
class RootDir(Dir):
"""A class for the root directory of a file system.
@@ -2265,9 +2309,9 @@ class RootDir(Dir):
add a separator when creating the path names of entries within
this directory.
"""
-
+
__slots__ = ['_lookupDict']
-
+
def __init__(self, drive, fs):
if SCons.Debug.track_instances: logInstanceCreation(self, 'Node.FS.RootDir')
SCons.Node.Node.__init__(self)
@@ -2275,7 +2319,7 @@ class RootDir(Dir):
# Handle all the types of drives:
if drive == '':
# No drive, regular UNIX root or Windows default drive.
- name = OS_SEP
+ name = OS_SEP
dirname = OS_SEP
elif drive == '//':
# UNC path
@@ -2289,7 +2333,7 @@ class RootDir(Dir):
#: Filename with extension as it was specified when the object was
#: created; to obtain filesystem path, use Python str() function
self.name = SCons.Util.silent_intern(name)
- self.fs = fs #: Reference to parent Node.FS object
+ self.fs = fs #: Reference to parent Node.FS object
self._path_elements = [self]
self.dir = self
@@ -2345,7 +2389,7 @@ class RootDir(Dir):
self._func_sconsign = 1
self._func_exists = 2
self._func_get_contents = 2
-
+
# Don't just reset the executor, replace its action list,
# because it might have some pre-or post-actions that need to
# be preserved.
@@ -2361,9 +2405,8 @@ class RootDir(Dir):
# Prepend MkdirBuilder action to existing action list
l = self.get_executor().action_list
a = get_MkdirBuilder().action
- l.insert(0, a)
+ l.insert(0, a)
self.get_executor().set_action_list(l)
-
def must_be_same(self, klass):
if klass is Dir:
@@ -2391,11 +2434,12 @@ class RootDir(Dir):
result = self._lookupDict[k]
except KeyError:
if not create:
- msg = "No such file or directory: '%s' in '%s' (and create is False)" % (p, str(self))
+ msg = "No such file or directory: '%s' in '%s' (and create is False)" % (p,
+ str(self))
raise SCons.Errors.UserError(msg)
# There is no Node for this path name, and we're allowed
# to create it.
- dir_name, file_name = p.rsplit('/',1)
+ dir_name, file_name = p.rsplit('/', 1)
dir_node = self._lookup_abs(dir_name, Dir)
result = klass(file_name, dir_node, self.fs)
@@ -2442,6 +2486,7 @@ class RootDir(Dir):
def src_builder(self):
return _null
+
class FileNodeInfo(SCons.Node.NodeInfoBase):
__slots__ = ('csig', 'timestamp', 'size')
current_version_id = 2
@@ -2471,7 +2516,7 @@ class FileNodeInfo(SCons.Node.NodeInfoBase):
"""
state = getattr(self, '__dict__', {}).copy()
for obj in type(self).mro():
- for name in getattr(obj,'__slots__',()):
+ for name in getattr(obj, '__slots__', ()):
if hasattr(self, name):
state[name] = getattr(self, name)
@@ -2490,9 +2535,10 @@ class FileNodeInfo(SCons.Node.NodeInfoBase):
# TODO check or discard version
del state['_version_id']
for key, value in state.items():
- if key not in ('__weakref__',):
+ if key not in ('__weakref__', ):
setattr(self, key, value)
+
class FileBuildInfo(SCons.Node.BuildInfoBase):
__slots__ = ()
current_version_id = 2
@@ -2508,6 +2554,7 @@ class FileBuildInfo(SCons.Node.BuildInfoBase):
if os_sep_is_slash:
node_to_str = str
else:
+
def node_to_str(n):
try:
s = n.get_internal_path()
@@ -2516,6 +2563,7 @@ class FileBuildInfo(SCons.Node.BuildInfoBase):
else:
s = s.replace(OS_SEP, '/')
return s
+
for attr in ['bsources', 'bdepends', 'bimplicit']:
try:
val = getattr(self, attr)
@@ -2523,6 +2571,7 @@ class FileBuildInfo(SCons.Node.BuildInfoBase):
pass
else:
setattr(self, attr, list(map(node_to_str, val)))
+
def convert_from_sconsign(self, dir, name):
"""
Converts a newly-read FileBuildInfo object for in-SCons use
@@ -2531,6 +2580,7 @@ class FileBuildInfo(SCons.Node.BuildInfoBase):
perform--but we're leaving this method here to make that clear.
"""
pass
+
def prepare_dependencies(self):
"""
Prepares a FileBuildInfo object for explaining what changed
@@ -2559,38 +2609,55 @@ class FileBuildInfo(SCons.Node.BuildInfoBase):
s = ni.str_to_node(s)
nodes.append(s)
setattr(self, nattr, nodes)
+
def format(self, names=0):
result = []
bkids = self.bsources + self.bdepends + self.bimplicit
bkidsigs = self.bsourcesigs + self.bdependsigs + self.bimplicitsigs
for bkid, bkidsig in zip(bkids, bkidsigs):
- result.append(str(bkid) + ': ' +
- ' '.join(bkidsig.format(names=names)))
- if not hasattr(self,'bact'):
+ result.append(str(bkid) + ': ' + ' '.join(bkidsig.format(names=names)))
+ if not hasattr(self, 'bact'):
self.bact = "none"
result.append('%s [%s]' % (self.bactsig, self.bact))
return '\n'.join(result)
+
+def log_cache_rate(fn):
+ """
+ Logs the cache hit ratio.
+ """
+ global requests
+ global hits
+ hits = 0
+ requests = 0
+
+ def wrapper(self):
+ global requests
+ global hits
+
+ requests += 1
+ print('req', requests)
+ result = fn(self)
+ print('res', result)
+ if result:
+ hits += 1
+ print('hits', hits)
+
+ print 'Cache hit ratio: %d%%' % (hits / requests)
+ return result
+
+ return wrapper
+
+
class File(Base):
"""A class for files in a file system.
"""
- __slots__ = ['scanner_paths',
- 'cachedir_csig',
- 'cachesig',
- 'repositories',
- 'srcdir',
- 'entries',
- 'searched',
- '_sconsign',
- 'variant_dirs',
- 'root',
- 'dirname',
- 'on_disk_entries',
- 'sccs_dir',
- 'rcs_dir',
- 'released_target_info',
- 'contentsig']
+ __slots__ = [
+ 'scanner_paths', 'cachedir_csig', 'cachesig', 'repositories', 'srcdir', 'entries',
+ 'searched', '_sconsign', 'variant_dirs', 'root', 'dirname', 'on_disk_entries', 'sccs_dir',
+ 'rcs_dir', 'released_target_info', 'contentsig'
+ ]
NodeInfo = FileNodeInfo
BuildInfo = FileBuildInfo
@@ -2598,8 +2665,7 @@ class File(Base):
md5_chunksize = 64
def diskcheck_match(self):
- diskcheck_match(self, self.isdir,
- "Directory %s found where file expected.")
+ diskcheck_match(self, self.isdir, "Directory %s found where file expected.")
def __init__(self, name, directory, fs):
if SCons.Debug.track_instances: logInstanceCreation(self, 'Node.FS.File')
@@ -2637,11 +2703,11 @@ class File(Base):
self.store_info = 1
self._func_exists = 4
self._func_get_contents = 3
-
+
# Initialize this Node's decider function to decide_source() because
# every file is a source file until it has a Builder attached...
self.changed_since_last_build = 4
-
+
# If there was already a Builder set on this entry, then
# we need to make sure we call the target-decider function,
# not the source-decider. Reaching in and doing this by hand
@@ -2689,13 +2755,13 @@ class File(Base):
fname = self.rfile().get_abspath()
try:
cs = SCons.Util.MD5filesignature(fname,
- chunksize=SCons.Node.FS.File.md5_chunksize*1024)
+ chunksize=SCons.Node.FS.File.md5_chunksize * 1024)
except EnvironmentError, e:
if not e.filename:
e.filename = fname
raise
return cs
-
+
@SCons.Memoize.CountMethodCall
def get_size(self):
try:
@@ -2737,7 +2803,6 @@ class File(Base):
'ninfo',
]
-
convert_sig_attrs = [
'bsourcesigs',
'bimplicitsigs',
@@ -2871,8 +2936,10 @@ class File(Base):
def get_stored_implicit(self):
binfo = self.get_stored_info().binfo
binfo.prepare_dependencies()
- try: return binfo.bimplicit
- except AttributeError: return None
+ try:
+ return binfo.bimplicit
+ except AttributeError:
+ return None
def rel_path(self, other):
return self.dir.rel_path(other)
@@ -2928,6 +2995,7 @@ class File(Base):
if self.exists():
self.get_build_env().get_CacheDir().push(self)
+ @log_cache_rate
def retrieve_from_cache(self):
"""Try to retrieve the node's content from a cache
@@ -2954,7 +3022,7 @@ class File(Base):
ninfo.csig = csig
ninfo.timestamp = self.get_timestamp()
- ninfo.size = self.get_size()
+ ninfo.size = self.get_size()
if not self.has_builder():
# This is a source file, but it might have been a target file
@@ -2969,11 +3037,11 @@ class File(Base):
def release_target_info(self):
"""Called just after this node has been marked
up-to-date or was built completely.
-
+
This is where we try to release as many target node infos
as possible for clean builds and update runs, in order
to minimize the overall memory consumption.
-
+
We'd like to remove a lot more attributes like self.sources
and self.sources_set, but they might get used
in a next build step. For example, during configuration
@@ -2981,18 +3049,18 @@ class File(Base):
which linker to use for the resulting Program (gcc vs. g++)!
That's why we check for the 'keep_targetinfo' attribute,
config Nodes and the Interactive mode just don't allow
- an early release of most variables.
+ an early release of most variables.
In the same manner, we can't simply remove the self.attributes
here. The smart linking relies on the shared flag, and some
parts of the java Tool use it to transport information
about nodes...
-
+
@see: built() and Node.release_target_info()
"""
if (self.released_target_info or SCons.Node.interactive):
return
-
+
if not hasattr(self.attributes, 'keep_targetinfo'):
# Cache some required values, before releasing
# stuff like env, executor and builder...
@@ -3065,7 +3133,7 @@ class File(Base):
def _rmv_existing(self):
self.clear_memoized_values()
if SCons.Node.print_duplicate:
- print "dup: removing existing target %s"%self
+ print "dup: removing existing target %s" % self
e = Unlink(self, [], None)
if isinstance(e, SCons.Errors.BuildError):
raise e
@@ -3107,11 +3175,12 @@ class File(Base):
def do_duplicate(self, src):
self._createDir()
if SCons.Node.print_duplicate:
- print "dup: relinking variant '%s' from '%s'"%(self, src)
+ print "dup: relinking variant '%s' from '%s'" % (self, src)
Unlink(self, None, None)
e = Link(self, src, None)
if isinstance(e, SCons.Errors.BuildError):
- desc = "Cannot duplicate `%s' in `%s': %s." % (src.get_internal_path(), self.dir._path, e.errstr)
+ desc = "Cannot duplicate `%s' in `%s': %s." % (src.get_internal_path(), self.dir._path,
+ e.errstr)
raise SCons.Errors.StopError(desc)
self.linked = 1
# The Link() action may or may not have actually
@@ -3126,7 +3195,7 @@ class File(Base):
return self._memo['exists']
except KeyError:
pass
-
+
result = SCons.Node._exists_map[self._func_exists](self)
self._memo['exists'] = result
return result
@@ -3208,37 +3277,36 @@ class File(Base):
def built(self):
"""Called just after this File node is successfully built.
-
+
Just like for 'release_target_info' we try to release
some more target node attributes in order to minimize the
overall memory consumption.
-
+
@see: release_target_info
"""
SCons.Node.Node.built(self)
- if (not SCons.Node.interactive and
- not hasattr(self.attributes, 'keep_targetinfo')):
- # Ensure that the build infos get computed and cached...
+ if (not SCons.Node.interactive and not hasattr(self.attributes, 'keep_targetinfo')):
+ # Ensure that the build infos get computed and cached...
SCons.Node.store_info_map[self.store_info](self)
# ... then release some more variables.
self._specific_sources = False
self._labspath = None
self._save_str()
self.cwd = None
-
+
self.scanner_paths = None
def changed(self, node=None, allowcache=False):
"""
Returns if the node is up-to-date with respect to the BuildInfo
- stored last time it was built.
-
+ stored last time it was built.
+
For File nodes this is basically a wrapper around Node.changed(),
but we allow the return value to get cached after the reference
to the Executor got released in release_target_info().
-
+
@see: Node.changed()
"""
if node is None:
@@ -3246,7 +3314,7 @@ class File(Base):
return self._memo['changed']
except KeyError:
pass
-
+
has_changed = SCons.Node.Node.changed(self, node)
if allowcache:
self._memo['changed'] = has_changed
@@ -3299,7 +3367,7 @@ class File(Base):
# ...and they'd like a local copy.
e = LocalCopy(self, r, None)
if isinstance(e, SCons.Errors.BuildError):
- raise
+ raise
SCons.Node.store_info_map[self.store_info](self)
if T: Trace(' 1\n')
return 1
@@ -3321,26 +3389,28 @@ class File(Base):
if not self.exists():
norm_name = _my_normcase(self.name)
for dir in self.dir.get_all_rdirs():
- try: node = dir.entries[norm_name]
- except KeyError: node = dir.file_on_disk(self.name)
+ try:
+ node = dir.entries[norm_name]
+ except KeyError:
+ node = dir.file_on_disk(self.name)
if node and node.exists() and \
(isinstance(node, File) or isinstance(node, Entry) \
or not node.is_derived()):
- result = node
- # Copy over our local attributes to the repository
- # Node so we identify shared object files in the
- # repository and don't assume they're static.
- #
- # This isn't perfect; the attribute would ideally
- # be attached to the object in the repository in
- # case it was built statically in the repository
- # and we changed it to shared locally, but that's
- # rarely the case and would only occur if you
- # intentionally used the same suffix for both
- # shared and static objects anyway. So this
- # should work well in practice.
- result.attributes = self.attributes
- break
+ result = node
+ # Copy over our local attributes to the repository
+ # Node so we identify shared object files in the
+ # repository and don't assume they're static.
+ #
+ # This isn't perfect; the attribute would ideally
+ # be attached to the object in the repository in
+ # case it was built statically in the repository
+ # and we changed it to shared locally, but that's
+ # rarely the case and would only occur if you
+ # intentionally used the same suffix for both
+ # shared and static objects anyway. So this
+ # should work well in practice.
+ result.attributes = self.attributes
+ break
self._memo['rfile'] = result
return result
@@ -3381,12 +3451,12 @@ class File(Base):
It computes and returns the signature for this
node's contents.
"""
-
+
try:
return self.contentsig
except AttributeError:
pass
-
+
executor = self.get_executor()
result = self.contentsig = SCons.Util.MD5signature(executor.get_contents())
@@ -3406,7 +3476,7 @@ class File(Base):
return self.cachesig
except AttributeError:
pass
-
+
# Collect signatures for all children
children = self.children()
sigs = [n.get_cachedir_csig() for n in children]
@@ -3418,14 +3488,17 @@ class File(Base):
result = self.cachesig = SCons.Util.MD5collect(sigs)
return result
+
default_fs = None
+
def get_default_fs():
global default_fs
if not default_fs:
default_fs = FS()
return default_fs
+
class FileFinder(object):
"""
"""
@@ -3470,7 +3543,7 @@ class FileFinder(object):
def _find_file_key(self, filename, paths, verbose=None):
return (filename, paths)
-
+
@SCons.Memoize.CountDictCall(_find_file_key)
def find_file(self, filename, paths, verbose=None):
"""
@@ -3527,6 +3600,7 @@ class FileFinder(object):
return result
+
find_file = FileFinder().find_file
@@ -3556,7 +3630,7 @@ def invalidate_node_memos(targets):
if not SCons.Util.is_List(targets):
targets = [targets]
-
+
for entry in targets:
# If the target is a Node object, clear the cache. If it is a
# filename, look up potentially existing Node object first.
@@ -3568,7 +3642,8 @@ def invalidate_node_memos(targets):
# do not correspond to an existing Node object.
node = get_default_fs().Entry(entry)
if node:
- node.clear_memoized_values()
+ node.clear_memoized_values()
+
# Local Variables:
# tab-width:4