diff options
Diffstat (limited to 'src/scons/Node/FS.py')
-rw-r--r-- | src/scons/Node/FS.py | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/src/scons/Node/FS.py b/src/scons/Node/FS.py new file mode 100644 index 0000000..7640a7a --- /dev/null +++ b/src/scons/Node/FS.py @@ -0,0 +1,139 @@ +"""scons.Node.FS + +File system nodes. + +""" + +__revision__ = "Node/FS.py __REVISION__ __DATE__ __DEVELOPER__" + + + +import os +import os.path +from scons.Node import Node + + + +Top = None +Root = {} + + + +def init(path = None): + """Initialize the Node.FS subsystem. + + The supplied path is the top of the source tree, where we + expect to find the top-level build file. If no path is + supplied, the current directory is the default. + """ + global Top + if path == None: + path = os.getcwd() + Top = lookup(Dir, path, directory = None) + Top.path = '.' + +def lookup(fsclass, name, directory = Top): + """Look up a file system node for a path name. If the path + name is relative, it will be looked up relative to the + specified directory node, or to the top-level directory + if no node was specified. An initial '#' specifies that + the name will be looked up relative to the top-level directory, + regardless of the specified directory argument. Returns the + existing or newly-created node for the specified path name. + The node returned will be of the specified fsclass (Dir or + File). + """ + global Top + head, tail = os.path.split(name) + if not tail: + drive, path = os.path.splitdrive(head) + if not Root.has_key(drive): + Root[drive] = Dir(head, None) + Root[drive].abspath = head + Root[drive].path = head + return Root[drive] + if tail[0] == '#': + directory = Top + tail = tail[1:] + elif directory is None: + directory = Top + if head: + directory = lookup(Dir, head, directory) + try: + self = directory.entries[tail] + except AttributeError: + # There was no "entries" attribute on the directory, + # which essentially implies that it was a file. + # Return it as a more descriptive exception. + raise TypeError, directory + except KeyError: + # There was to entry for "tail," so create the new + # node and link it in to the existing structure. + self = fsclass(tail, directory) + self.name = tail + if self.path[0:2] == "./": + self.path = self.path[2:] + directory.entries[tail] = self + except: + raise + if self.__class__.__name__ != fsclass.__name__: + # Here, we found an existing node for this path, + # but it was the wrong type (a File when we were + # looking for a Dir, or vice versa). + raise TypeError, self + return self + + + +# XXX TODO? +# Annotate with the creator +# is_under +# rel_path +# srcpath / srcdir +# link / is_linked +# linked_targets +# is_accessible + +class Dir(Node): + """A class for directories in a file system. + """ + + def __init__(self, name, directory): + self.entries = {} + self.entries['.'] = self + self.entries['..'] = directory + if not directory is None: + self.abspath = os.path.join(directory.abspath, name, '') + self.path = os.path.join(directory.path, name, '') + + def up(self): + return self.entries['..'] + + +# XXX TODO? +# rfile +# precious +# no_rfile +# rpath +# rsrcpath +# source_exists +# derived_exists +# is_on_rpath +# local +# base_suf +# suffix +# addsuffix +# accessible +# ignore +# build +# bind +# is_under +# relpath + +class File(Node): + """A class for files in a file system. + """ + + def __init__(self, name, directory): + self.abspath = os.path.join(directory.abspath, name) + self.path = os.path.join(directory.path, name) |