diff options
Diffstat (limited to 'src/engine/SCons/Node/FS.py')
-rw-r--r-- | src/engine/SCons/Node/FS.py | 100 |
1 files changed, 56 insertions, 44 deletions
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index c9a1443..152a389 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -572,6 +572,16 @@ class Base(SCons.Node.Node): self.cwd = None # will hold the SConscript directory for target nodes self.duplicate = directory.duplicate + def must_be_same(self, klass): + """ + This node, which already existed, is being looked up as the + specified klass. Raise an exception if it isn't. + """ + if self.__class__ is klass or klass is Entry: + return + raise TypeError, "Tried to lookup %s '%s' as a %s." %\ + (self.__class__.__name__, self.path, klass.__name__) + def get_dir(self): return self.dir @@ -668,8 +678,8 @@ class Base(SCons.Node.Node): name=self.name while dir: if dir.srcdir: - srcnode = self.fs.Entry(name, dir.srcdir, - klass=self.__class__) + srcnode = dir.srcdir.Entry(name) + srcnode.must_be_same(self.__class__) return srcnode name = dir.name + os.sep + name dir = dir.up() @@ -848,12 +858,13 @@ class Entry(Base): else: return self.get_contents() - def must_be_a_Dir(self): + 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.""" - self.__class__ = Dir - self._morph() - return self + if not self.__class__ is klass: + self.__class__ = klass + self._morph() + self.clear # The following methods can get called before the Taskmaster has # had a chance to call disambiguate() directly to see if this Entry @@ -1011,16 +1022,6 @@ class FS(LocalFS): def getcwd(self): return self._cwd - def __checkClass(self, node, klass): - if isinstance(node, klass) or klass == Entry: - return node - if node.__class__ == Entry: - node.__class__ = klass - node._morph() - return node - raise TypeError, "Tried to lookup %s '%s' as a %s." % \ - (node.__class__.__name__, node.path, klass.__name__) - def _doLookup_key(self, fsclass, name, directory = None, create = 1): return (fsclass, name, directory) @@ -1099,7 +1100,7 @@ class FS(LocalFS): # We tried to look up the entry in either an Entry or # a File. Give whatever it is a chance to do what's # appropriate: morph into a Dir or raise an exception. - directory.must_be_a_Dir() + directory.must_be_same(Dir) entries = directory.entries try: directory = entries[norm] @@ -1117,7 +1118,7 @@ class FS(LocalFS): directory.add_wkid(d) directory = d - directory.must_be_a_Dir() + directory.must_be_same(Dir) try: e = directory.entries[last_norm] @@ -1135,7 +1136,8 @@ class FS(LocalFS): directory.entries[last_norm] = result directory.add_wkid(result) else: - result = self.__checkClass(e, fsclass) + e.must_be_same(fsclass) + result = e memo_dict[memo_key] = result @@ -1151,15 +1153,18 @@ class FS(LocalFS): If directory is None, and name is a relative path, then the same applies. """ - if not SCons.Util.is_String(name): - # This handles cases where the object is a Proxy wrapping - # a Node.FS.File object (e.g.). It would be good to handle - # this more directly some day by having the callers of this - # function recognize that a Proxy can be treated like the - # underlying object (that is, get rid of the isinstance() - # calls that explicitly look for a Node.FS.Base object). + try: + # Decide if this is a top-relative look up. The normal case + # (by far) is handed a non-zero-length string to look up, + # so just (try to) check for the initial '#'. + top_relative = (name[0] == '#') + except (AttributeError, IndexError): + # The exceptions we may encounter in unusual cases: + # AttributeError: a proxy without a __getitem__() method. + # IndexError: a null string. + top_relative = False name = str(name) - if name and name[0] == '#': + if top_relative: directory = self.Top name = name[1:] if name and (name[0] == os.sep or name[0] == '/'): @@ -1199,7 +1204,8 @@ class FS(LocalFS): klass = Entry if isinstance(name, Base): - return self.__checkClass(name, klass) + name.must_be_same(klass) + return name else: if directory and not isinstance(directory, Dir): directory = self.Dir(directory) @@ -1628,11 +1634,6 @@ class Dir(Base): def entry_tpath(self, name): return self.tpath + os.sep + name - def must_be_a_Dir(self): - """Called to make sure a Node is a Dir. Since we're already - one, this is a no-op for us.""" - return self - def entry_exists_on_disk(self, name): try: d = self.on_disk_entries @@ -1777,6 +1778,11 @@ class RootDir(Dir): self.tpath = name + os.sep self._morph() + def must_be_same(self, klass): + if klass is Dir: + return + Base.must_be_same(self, klass) + def __str__(self): return self.abspath @@ -1856,14 +1862,25 @@ class FileBuildInfo(SCons.Node.BuildInfoBase): as dependency info. Convert the strings to actual Nodes (for use by the --debug=explain code and --implicit-cache). """ - Entry_func = self.node.dir.Entry + def str_to_node(s, entry=self.node.dir.Entry): + # This is a little bogus; we're going to mimic the lookup + # order of env.arg2nodes() by hard-coding an Alias lookup + # before we assume it's an Entry. This should be able to + # go away once the Big Signature Refactoring pickles the + # actual NodeInfo object, which will let us know precisely + # what type of Node to turn it into. + import SCons.Node.Alias + n = SCons.Node.Alias.default_ans.lookup(s) + if not n: + n = entry(s) + return n for attr in ['bsources', 'bdepends', 'bimplicit']: try: val = getattr(self, attr) except AttributeError: pass else: - setattr(self, attr, map(Entry_func, val)) + setattr(self, attr, map(str_to_node, val)) def format(self): result = [ self.ninfo.format() ] bkids = self.bsources + self.bdepends + self.bimplicit @@ -1899,12 +1916,12 @@ class File(Base): def Entry(self, name): """Create an entry node named 'name' relative to the SConscript directory of this file.""" - return self.fs.Entry(name, self.cwd) + return self.cwd.Entry(name) def Dir(self, name): """Create a directory node named 'name' relative to the SConscript directory of this file.""" - return self.fs.Dir(name, self.cwd) + return self.cwd.Dir(name) def Dirs(self, pathlist): """Create a list of directories relative to the SConscript @@ -1914,7 +1931,7 @@ class File(Base): def File(self, name): """Create a file node named 'name' relative to the SConscript directory of this file.""" - return self.fs.File(name, self.cwd) + return self.cwd.File(name) #def generate_build_dict(self): # """Return an appropriate dictionary of values for building @@ -2032,7 +2049,7 @@ class File(Base): Note that there's a special trick here with the execute flag (one that's not normally done for other actions). Basically - if the user requested a noexec (-n) build, then + if the user requested a no_exec (-n) build, then SCons.Action.execute_actions is set to 0 and when any action is called, it does its showing but then just returns zero instead of actually calling the action execution operation. @@ -2334,11 +2351,6 @@ class File(Base): dir = os.path.join(self.fs.CachePath, subdir) return dir, os.path.join(dir, cache_sig) - def must_be_a_Dir(self): - """Called to make sure a Node is a Dir. Since we're already a - File, this is a TypeError...""" - raise TypeError, "Tried to lookup File '%s' as a Dir." % self.path - default_fs = None class FileFinder: |