| Index: third_party/scons/scons-local/SCons/Node/FS.py
|
| ===================================================================
|
| --- third_party/scons/scons-local/SCons/Node/FS.py (revision 7505)
|
| +++ third_party/scons/scons-local/SCons/Node/FS.py (working copy)
|
| @@ -33,7 +33,7 @@
|
| # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
| #
|
|
|
| -__revision__ = "src/engine/SCons/Node/FS.py 3603 2008/10/10 05:46:45 scons"
|
| +__revision__ = "src/engine/SCons/Node/FS.py 3842 2008/12/20 22:59:52 scons"
|
|
|
| import fnmatch
|
| from itertools import izip
|
| @@ -61,6 +61,23 @@
|
|
|
| do_store_info = True
|
|
|
| +
|
| +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))
|
| +
|
| # 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
|
| @@ -225,8 +242,6 @@
|
| if func == Link_Funcs[-1]:
|
| # exception of the last link method (copy) are fatal
|
| raise
|
| - else:
|
| - pass
|
| return 0
|
|
|
| Link = SCons.Action.Action(LinkFunc, None)
|
| @@ -485,16 +500,11 @@
|
| except KeyError:
|
| try:
|
| attr = SCons.Util.Proxy.__getattr__(self, name)
|
| - except AttributeError:
|
| - entry = self.get()
|
| - classname = string.split(str(entry.__class__), '.')[-1]
|
| - if classname[-2:] == "'>":
|
| - # new-style classes report their name as:
|
| - # "<class 'something'>"
|
| - # instead of the classic classes:
|
| - # "something"
|
| - classname = classname[:-2]
|
| - raise AttributeError, "%s instance '%s' has no attribute '%s'" % (classname, entry.name, name)
|
| + except AttributeError, e:
|
| + # Raise our own AttributeError subclass with an
|
| + # overridden __str__() method that identifies the
|
| + # name of the entry that caused the exception.
|
| + raise EntryProxyAttributeError(self, name)
|
| return attr
|
| else:
|
| return attr_function(self)
|
| @@ -592,7 +602,7 @@
|
| if self.duplicate or self.is_derived():
|
| return self.get_path()
|
| srcnode = self.srcnode()
|
| - if srcnode.stat() is None and not self.stat() is None:
|
| + if srcnode.stat() is None and self.stat() is not None:
|
| result = self.get_path()
|
| else:
|
| result = srcnode.get_path()
|
| @@ -607,7 +617,7 @@
|
| # values that the underlying stat() method saved.
|
| try: del self._memo['stat']
|
| except KeyError: pass
|
| - if not self is srcnode:
|
| + if self is not srcnode:
|
| try: del srcnode._memo['stat']
|
| except KeyError: pass
|
| return result
|
| @@ -625,7 +635,7 @@
|
| return result
|
|
|
| def exists(self):
|
| - return not self.stat() is None
|
| + return self.stat() is not None
|
|
|
| def rexists(self):
|
| return self.rfile().exists()
|
| @@ -642,11 +652,11 @@
|
|
|
| def isdir(self):
|
| st = self.stat()
|
| - return not st is None and stat.S_ISDIR(st[stat.ST_MODE])
|
| + return st is not 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])
|
| + return st is not None and stat.S_ISREG(st[stat.ST_MODE])
|
|
|
| if hasattr(os, 'symlink'):
|
| def islink(self):
|
| @@ -886,7 +896,7 @@
|
| def must_be_same(self, klass):
|
| """Called to make sure a Node is a Dir. Since we're an
|
| Entry, we can morph into one."""
|
| - if not self.__class__ is klass:
|
| + if self.__class__ is not klass:
|
| self.__class__ = klass
|
| self._morph()
|
| self.clear()
|
| @@ -910,7 +920,7 @@
|
|
|
| def rel_path(self, other):
|
| d = self.disambiguate()
|
| - if d.__class__ == Entry:
|
| + if d.__class__ is Entry:
|
| raise "rel_path() could not disambiguate File/Dir"
|
| return d.rel_path(other)
|
|
|
| @@ -1065,7 +1075,7 @@
|
| """
|
| curr=self._cwd
|
| try:
|
| - if not dir is None:
|
| + if dir is not None:
|
| self._cwd = dir
|
| if change_os_dir:
|
| os.chdir(dir.abspath)
|
| @@ -1171,7 +1181,7 @@
|
| return root._lookup_abs(p, fsclass, create)
|
|
|
| def Entry(self, name, directory = None, create = 1):
|
| - """Lookup or create a generic Entry node with the specified name.
|
| + """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
|
| node, or to the top level directory of the FS (supplied at
|
| @@ -1180,7 +1190,7 @@
|
| return self._lookup(name, directory, Entry, create)
|
|
|
| def File(self, name, directory = None, create = 1):
|
| - """Lookup or create a File node with the specified name. If
|
| + """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,
|
| or to the top level directory of the FS (supplied at construction
|
| @@ -1192,7 +1202,7 @@
|
| return self._lookup(name, directory, File, create)
|
|
|
| def Dir(self, name, directory = None, create = True):
|
| - """Lookup or create a Dir node with the specified name. If
|
| + """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,
|
| or to the top level directory of the FS (supplied at construction
|
| @@ -1348,7 +1358,7 @@
|
| del node._srcreps
|
| except AttributeError:
|
| pass
|
| - if duplicate != None:
|
| + if duplicate is not None:
|
| node.duplicate=duplicate
|
|
|
| def __resetDuplicate(self, node):
|
| @@ -1367,8 +1377,7 @@
|
| Looks up or creates a directory node named 'name' relative to
|
| this directory.
|
| """
|
| - dir = self.fs.Dir(name, self, create)
|
| - return dir
|
| + return self.fs.Dir(name, self, create)
|
|
|
| def File(self, name):
|
| """
|
| @@ -1451,15 +1460,15 @@
|
| """Return a path to "other" relative to this directory.
|
| """
|
|
|
| - # This complicated and expensive method, which constructs relative
|
| - # paths between arbitrary Node.FS objects, is no longer used
|
| - # by SCons itself. It was introduced to store dependency paths
|
| - # in .sconsign files relative to the target, but that ended up
|
| - # being significantly inefficient.
|
| + # This complicated and expensive method, which constructs relative
|
| + # paths between arbitrary Node.FS objects, is no longer used
|
| + # by SCons itself. It was introduced to store dependency paths
|
| + # in .sconsign files relative to the target, but that ended up
|
| + # being significantly inefficient.
|
| #
|
| - # We're continuing to support the method because some SConstruct
|
| - # files out there started using it when it was available, and
|
| - # we're all about backwards compatibility..
|
| + # We're continuing to support the method because some SConstruct
|
| + # files out there started using it when it was available, and
|
| + # we're all about backwards compatibility..
|
|
|
| try:
|
| memo_dict = self._memo['rel_path']
|
| @@ -1473,11 +1482,9 @@
|
| pass
|
|
|
| if self is other:
|
| -
|
| result = '.'
|
|
|
| elif not other in self.path_elements:
|
| -
|
| try:
|
| other_dir = other.get_dir()
|
| except AttributeError:
|
| @@ -1491,9 +1498,7 @@
|
| result = other.name
|
| else:
|
| result = dir_rel_path + os.sep + other.name
|
| -
|
| else:
|
| -
|
| i = self.path_elements.index(other) + 1
|
|
|
| path_elems = ['..'] * (len(self.path_elements) - i) \
|
| @@ -1544,7 +1549,7 @@
|
| def build(self, **kw):
|
| """A null "builder" for directories."""
|
| global MkdirBuilder
|
| - if not self.builder is MkdirBuilder:
|
| + if self.builder is not MkdirBuilder:
|
| apply(SCons.Node.Node.build, [self,], kw)
|
|
|
| #
|
| @@ -1560,10 +1565,9 @@
|
| if parent.exists():
|
| break
|
| listDirs.append(parent)
|
| - p = parent.up()
|
| - if p is None:
|
| - raise SCons.Errors.StopError, parent.path
|
| - parent = p
|
| + parent = parent.up()
|
| + else:
|
| + raise SCons.Errors.StopError, parent.path
|
| listDirs.reverse()
|
| for dirnode in listDirs:
|
| try:
|
| @@ -1583,7 +1587,7 @@
|
|
|
| def multiple_side_effect_has_builder(self):
|
| global MkdirBuilder
|
| - return not self.builder is MkdirBuilder and self.has_builder()
|
| + return self.builder is not MkdirBuilder and self.has_builder()
|
|
|
| def alter_targets(self):
|
| """Return any corresponding targets in a variant directory.
|
| @@ -1622,7 +1626,7 @@
|
| def is_up_to_date(self):
|
| """If any child is not up-to-date, then this directory isn't,
|
| either."""
|
| - if not self.builder is MkdirBuilder and not self.exists():
|
| + if self.builder is not MkdirBuilder and not self.exists():
|
| return 0
|
| up_to_date = SCons.Node.up_to_date
|
| for kid in self.children():
|
| @@ -1795,7 +1799,7 @@
|
| except TypeError: pass
|
| node = self.srcdir_duplicate(name)
|
| if isinstance(node, Dir):
|
| - node = None
|
| + return None
|
| return node
|
|
|
| def walk(self, func, arg):
|
| @@ -1888,6 +1892,7 @@
|
| for srcdir in self.srcdir_list():
|
| search_dir_list.extend(srcdir.get_all_rdirs())
|
|
|
| + selfEntry = self.Entry
|
| names = []
|
| for dir in search_dir_list:
|
| # We use the .name attribute from the Node because the keys of
|
| @@ -1900,35 +1905,36 @@
|
| if not strings:
|
| # Make sure the working directory (self) actually has
|
| # entries for all Nodes in repositories or variant dirs.
|
| - map(self.Entry, node_names)
|
| + map(selfEntry, node_names)
|
| if ondisk:
|
| try:
|
| disk_names = os.listdir(dir.abspath)
|
| except os.error:
|
| - pass
|
| - else:
|
| - names.extend(disk_names)
|
| - if not strings:
|
| - # We're going to return corresponding Nodes in
|
| - # the local directory, so we need to make sure
|
| - # those Nodes exist. We only want to create
|
| - # Nodes for the entries that will match the
|
| - # specified pattern, though, which means we
|
| - # need to filter the list here, even though
|
| - # the overall list will also be filtered later,
|
| - # after we exit this loop.
|
| - if pattern[0] != '.':
|
| - #disk_names = [ d for d in disk_names if d[0] != '.' ]
|
| - disk_names = filter(lambda x: x[0] != '.', disk_names)
|
| - disk_names = fnmatch.filter(disk_names, pattern)
|
| - rep_nodes = map(dir.Entry, disk_names)
|
| - #rep_nodes = [ n.disambiguate() for n in rep_nodes ]
|
| - rep_nodes = map(lambda n: n.disambiguate(), rep_nodes)
|
| - for node, name in izip(rep_nodes, disk_names):
|
| - n = self.Entry(name)
|
| - if n.__class__ != node.__class__:
|
| - n.__class__ = node.__class__
|
| - n._morph()
|
| + continue
|
| + names.extend(disk_names)
|
| + if not strings:
|
| + # We're going to return corresponding Nodes in
|
| + # the local directory, so we need to make sure
|
| + # those Nodes exist. We only want to create
|
| + # Nodes for the entries that will match the
|
| + # specified pattern, though, which means we
|
| + # need to filter the list here, even though
|
| + # the overall list will also be filtered later,
|
| + # after we exit this loop.
|
| + if pattern[0] != '.':
|
| + #disk_names = [ d for d in disk_names if d[0] != '.' ]
|
| + disk_names = filter(lambda x: x[0] != '.', disk_names)
|
| + disk_names = fnmatch.filter(disk_names, pattern)
|
| + dirEntry = dir.Entry
|
| + for name in disk_names:
|
| + # Add './' before disk filename so that '#' at
|
| + # beginning of filename isn't interpreted.
|
| + name = './' + name
|
| + node = dirEntry(name).disambiguate()
|
| + n = selfEntry(name)
|
| + if n.__class__ != node.__class__:
|
| + n.__class__ = node.__class__
|
| + n._morph()
|
|
|
| names = set(names)
|
| if pattern[0] != '.':
|
| @@ -2137,14 +2143,13 @@
|
| strings = getattr(self, nattr)
|
| nodeinfos = getattr(self, sattr)
|
| except AttributeError:
|
| - pass
|
| - else:
|
| - nodes = []
|
| - for s, ni in izip(strings, nodeinfos):
|
| - if not isinstance(s, SCons.Node.Node):
|
| - s = ni.str_to_node(s)
|
| - nodes.append(s)
|
| - setattr(self, nattr, nodes)
|
| + continue
|
| + nodes = []
|
| + for s, ni in izip(strings, nodeinfos):
|
| + if not isinstance(s, SCons.Node.Node):
|
| + 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
|
| @@ -2177,26 +2182,25 @@
|
|
|
| def Entry(self, name):
|
| """Create an entry node named 'name' relative to
|
| - the SConscript directory of this file."""
|
| - cwd = self.cwd or self.fs._cwd
|
| - return cwd.Entry(name)
|
| + the directory of this file."""
|
| + return self.dir.Entry(name)
|
|
|
| def Dir(self, name, create=True):
|
| """Create a directory node named 'name' relative to
|
| - the SConscript directory of this file."""
|
| - cwd = self.cwd or self.fs._cwd
|
| - return cwd.Dir(name, create)
|
| + the directory of this file."""
|
| + return self.dir.Dir(name, create=create)
|
|
|
| def Dirs(self, pathlist):
|
| """Create a list of directories relative to the SConscript
|
| directory of this file."""
|
| + # TODO(1.5)
|
| + # return [self.Dir(p) for p in pathlist]
|
| return map(lambda p, s=self: s.Dir(p), pathlist)
|
|
|
| def File(self, name):
|
| """Create a file node named 'name' relative to
|
| - the SConscript directory of this file."""
|
| - cwd = self.cwd or self.fs._cwd
|
| - return cwd.File(name)
|
| + the directory of this file."""
|
| + return self.dir.File(name)
|
|
|
| #def generate_build_dict(self):
|
| # """Return an appropriate dictionary of values for building
|
| @@ -2390,26 +2394,24 @@
|
| try:
|
| value = getattr(old_entry, attr)
|
| except AttributeError:
|
| - pass
|
| - else:
|
| - setattr(binfo, attr, value)
|
| - delattr(old_entry, attr)
|
| + continue
|
| + setattr(binfo, attr, value)
|
| + delattr(old_entry, attr)
|
| for attr in self.convert_sig_attrs:
|
| try:
|
| sig_list = getattr(old_entry, attr)
|
| except AttributeError:
|
| - pass
|
| - else:
|
| - value = []
|
| - for sig in sig_list:
|
| - ninfo = self.new_ninfo()
|
| - if len(sig) == 32:
|
| - ninfo.csig = sig
|
| - else:
|
| - ninfo.timestamp = sig
|
| - value.append(ninfo)
|
| - setattr(binfo, attr, value)
|
| - delattr(old_entry, attr)
|
| + continue
|
| + value = []
|
| + for sig in sig_list:
|
| + ninfo = self.new_ninfo()
|
| + if len(sig) == 32:
|
| + ninfo.csig = sig
|
| + else:
|
| + ninfo.timestamp = sig
|
| + value.append(ninfo)
|
| + setattr(binfo, attr, value)
|
| + delattr(old_entry, attr)
|
| return new_entry
|
|
|
| memoizer_counters.append(SCons.Memoize.CountValue('get_stored_info'))
|
| @@ -2473,6 +2475,7 @@
|
| pass
|
|
|
| if scanner:
|
| + # result = [n.disambiguate() for n in scanner(self, env, path)]
|
| result = scanner(self, env, path)
|
| result = map(lambda N: N.disambiguate(), result)
|
| else:
|
| @@ -2576,7 +2579,7 @@
|
| scb = self.sbuilder
|
| except AttributeError:
|
| scb = self.sbuilder = self.find_src_builder()
|
| - return not scb is None
|
| + return scb is not None
|
|
|
| def alter_targets(self):
|
| """Return any corresponding targets in a variant directory.
|
| @@ -2649,7 +2652,7 @@
|
| # Duplicate from source path if we are set up to do this.
|
| if self.duplicate and not self.is_derived() and not self.linked:
|
| src = self.srcnode()
|
| - if not src is self:
|
| + if src is not self:
|
| # At this point, src is meant to be copied in a variant directory.
|
| src = src.rfile()
|
| if src.abspath != self.abspath:
|
| @@ -2683,23 +2686,22 @@
|
| old = self.get_stored_info()
|
| mtime = self.get_timestamp()
|
|
|
| - csig = None
|
| max_drift = self.fs.max_drift
|
| if max_drift > 0:
|
| if (time.time() - mtime) > max_drift:
|
| try:
|
| n = old.ninfo
|
| if n.timestamp and n.csig and n.timestamp == mtime:
|
| - csig = n.csig
|
| + return n.csig
|
| except AttributeError:
|
| pass
|
| elif max_drift == 0:
|
| try:
|
| - csig = old.ninfo.csig
|
| + return old.ninfo.csig
|
| except AttributeError:
|
| pass
|
|
|
| - return csig
|
| + return None
|
|
|
| def get_csig(self):
|
| """
|
| @@ -2754,7 +2756,7 @@
|
| return 1
|
|
|
| def changed_state(self, target, prev_ni):
|
| - return (self.state != SCons.Node.up_to_date)
|
| + return self.state != SCons.Node.up_to_date
|
|
|
| def changed_timestamp_then_content(self, target, prev_ni):
|
| if not self.changed_timestamp_match(target, prev_ni):
|
| @@ -2875,13 +2877,14 @@
|
| # Add the path to the cache signature, because multiple
|
| # targets built by the same action will all have the same
|
| # build signature, and we have to differentiate them somehow.
|
| - children = self.children()
|
| + children = self.children()
|
| + executor = self.get_executor()
|
| + # sigs = [n.get_cachedir_csig() for n in children]
|
| sigs = map(lambda n: n.get_cachedir_csig(), children)
|
| - executor = self.get_executor()
|
| sigs.append(SCons.Util.MD5signature(executor.get_contents()))
|
| sigs.append(self.path)
|
| - self.cachesig = SCons.Util.MD5collect(sigs)
|
| - return self.cachesig
|
| + result = self.cachesig = SCons.Util.MD5collect(sigs)
|
| + return result
|
|
|
|
|
| default_fs = None
|
| @@ -2971,14 +2974,11 @@
|
| except KeyError:
|
| pass
|
|
|
| - if verbose:
|
| + if verbose and not callable(verbose):
|
| if not SCons.Util.is_String(verbose):
|
| verbose = "find_file"
|
| - if not callable(verbose):
|
| - verbose = ' %s: ' % verbose
|
| - verbose = lambda s, v=verbose: sys.stdout.write(v + s)
|
| - else:
|
| - verbose = lambda x: x
|
| + verbose = ' %s: ' % verbose
|
| + verbose = lambda s, v=verbose: sys.stdout.write(v + s)
|
|
|
| filedir, filename = os.path.split(filename)
|
| if filedir:
|
| @@ -3017,10 +3017,12 @@
|
|
|
| result = None
|
| for dir in paths:
|
| - verbose("looking for '%s' in '%s' ...\n" % (filename, dir))
|
| + if verbose:
|
| + verbose("looking for '%s' in '%s' ...\n" % (filename, dir))
|
| node, d = dir.srcdir_find_file(filename)
|
| if node:
|
| - verbose("... FOUND '%s' in '%s'\n" % (filename, d))
|
| + if verbose:
|
| + verbose("... FOUND '%s' in '%s'\n" % (filename, d))
|
| result = node
|
| break
|
|
|
| @@ -3048,12 +3050,11 @@
|
| # affected. XXX The way to check if Execute() is in the stacktrace
|
| # is a very dirty hack and should be replaced by a more sensible
|
| # solution.
|
| - must_invalidate = 0
|
| - tb = extract_stack()
|
| - for f in tb:
|
| + for f in extract_stack():
|
| if f[2] == 'Execute' and f[0][-14:] == 'Environment.py':
|
| - must_invalidate = 1
|
| - if not must_invalidate:
|
| + break
|
| + else:
|
| + # Dont have to invalidate, so return
|
| return
|
|
|
| if not SCons.Util.is_List(targets):
|
|
|