summaryrefslogtreecommitdiffstats
path: root/src/scons/Node/FS.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/scons/Node/FS.py')
-rw-r--r--src/scons/Node/FS.py139
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)