diff options
| author | Steven Knight <knight@baldmt.com> | 2001-10-25 13:11:10 (GMT) |
|---|---|---|
| committer | Steven Knight <knight@baldmt.com> | 2001-10-25 13:11:10 (GMT) |
| commit | 123be6df3fe113bad181c0c93aab4ee58b26e91f (patch) | |
| tree | ac0b0ab9c7630768dc6411a2e8887ae3efc6dd3f /src/engine/SCons/Node | |
| parent | 6a98a941a75eab2e4c22fa3e19cb973046f613b6 (diff) | |
| download | SCons-123be6df3fe113bad181c0c93aab4ee58b26e91f.zip SCons-123be6df3fe113bad181c0c93aab4ee58b26e91f.tar.gz SCons-123be6df3fe113bad181c0c93aab4ee58b26e91f.tar.bz2 | |
Support building (sub)directories.
Diffstat (limited to 'src/engine/SCons/Node')
| -rw-r--r-- | src/engine/SCons/Node/FS.py | 79 | ||||
| -rw-r--r-- | src/engine/SCons/Node/FSTests.py | 88 | ||||
| -rw-r--r-- | src/engine/SCons/Node/NodeTests.py | 6 | ||||
| -rw-r--r-- | src/engine/SCons/Node/__init__.py | 16 |
4 files changed, 157 insertions, 32 deletions
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index e44da22..cfb4142 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -35,7 +35,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os import os.path -from SCons.Node import Node +import SCons.Node from UserDict import UserDict import sys @@ -119,6 +119,7 @@ class FS: self.Root = PathDict() self.Top = self.__doLookup(Dir, path) self.Top.path = '.' + self.Top.path_ = './' def __doLookup(self, fsclass, name, directory=None): """This method differs from the File and Dir factory methods in @@ -228,7 +229,7 @@ class FS: -class Entry(Node): +class Entry(SCons.Node.Node): """A generic class for file system entries. This class if for when we don't know yet whether the entry being looked up is a file or a directory. Instances of this class can morph into either @@ -241,8 +242,9 @@ class Entry(Node): our relative and absolute paths, identify our parent directory, and indicate that this node should use signatures.""" - Node.__init__(self) + SCons.Node.Node.__init__(self) + self.name = name if directory: self.abspath = os.path.join(directory.abspath, name) if str(directory.path) == '.': @@ -251,13 +253,18 @@ class Entry(Node): self.path = os.path.join(directory.path, name) else: self.abspath = self.path = name - self.parent = directory + self.path_ = self.path + self.abspath_ = self.abspath + self.dir = directory self.use_signature = 1 def __str__(self): """A FS node's string representation is its path name.""" return self.path + def set_signature(self, sig): + SCons.Node.Node.set_signature(self, sig) + def exists(self): return os.path.exists(self.path) @@ -299,17 +306,18 @@ class Dir(Entry): into the file system tree. Specify that directories (this node) don't use signatures for currency calculation.""" - self.path = os.path.join(self.path, '') - self.abspath = os.path.join(self.abspath, '') + self.path_ = os.path.join(self.path, '') + self.abspath_ = os.path.join(self.abspath, '') self.entries = PathDict() self.entries['.'] = self - if hasattr(self, 'parent'): - self.entries['..'] = self.parent - delattr(self, 'parent') + if hasattr(self, 'dir'): + self.entries['..'] = self.dir else: self.entries['..'] = None self.use_signature = None + self.builder = 1 + self._sconsign = None def up(self): return self.entries['..'] @@ -321,15 +329,42 @@ class Dir(Entry): return self.entries['..'].root() def children(self): - return map(lambda x, s=self: s.entries[x], + #XXX --random: randomize "dependencies?" + kids = map(lambda x, s=self: s.entries[x], filter(lambda k: k != '.' and k != '..', self.entries.keys())) + kids.sort() + return kids + + def build(self): + """A null "builder" for directories.""" + pass + + def set_signature(self, sig): + """A directory has no signature.""" + pass def current(self): - """Always return that a directory node is out-of-date so - that it will always be "built" by trying to build all of - its directory entries.""" - return 0 + """If all of our children were up-to-date, then this + directory was up-to-date, too.""" + state = 0 + for kid in self.children(): + s = kid.get_state() + if s and (not state or s > state): + state = s + import SCons.Node + if state == SCons.Node.up_to_date: + return 1 + else: + return 0 + + def sconsign(self): + if not self._sconsign: + #XXX Rework this to get rid of the hard-coding + import SCons.Sig + import SCons.Sig.MD5 + self._sconsign = SCons.Sig.SConsignFile(self.path, SCons.Sig.MD5) + return self._sconsign # XXX TODO? @@ -362,13 +397,25 @@ class File(Entry): pass def root(self): - return self.parent.root() + return self.dir.root() def get_contents(self): return open(self.path, "r").read() def get_timestamp(self): - return os.path.getmtime(self.path) + if self.exists(): + return os.path.getmtime(self.path) + else: + return 0 + + def set_signature(self, sig): + Entry.set_signature(self, sig) + #XXX Rework this to get rid of the hard-coding + import SCons.Sig.MD5 + self.dir.sconsign().set(self.name, self.get_timestamp(), sig, SCons.Sig.MD5) + + def get_oldentry(self): + return self.dir.sconsign().get(self.name) default_fs = FS() diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index 044f83f..8b1ee5a 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -84,36 +84,60 @@ class FSTestCase(unittest.TestCase): for sep in seps: - def Dir_test(lpath, path, abspath, up_path, fileSys=fs, s=sep): + def Dir_test(lpath, path_, abspath_, up_path_, fileSys=fs, s=sep): dir = fileSys.Dir(string.replace(lpath, '/', s)) + def strip_slash(p): + if p[-1] == '/' and len(p) > 1: + p = p[:-1] + return p + path = strip_slash(path_) + abspath = strip_slash(abspath_) + up_path = strip_slash(up_path_) + name = string.split(abspath, '/')[-1] + if os.sep != '/': path = string.replace(path, '/', os.sep) + path_ = string.replace(path_, '/', os.sep) abspath = string.replace(abspath, '/', os.sep) + abspath_ = string.replace(abspath_, '/', os.sep) up_path = string.replace(up_path, '/', os.sep) + up_path_ = string.replace(up_path_, '/', os.sep) + assert dir.name == name, \ + "dir.name %s != expected name %s" % \ + (dir.name, name) assert dir.path == path, \ "dir.path %s != expected path %s" % \ (dir.path, path) assert str(dir) == path, \ "str(dir) %s != expected path %s" % \ (str(dir), path) + assert dir.path_ == path_, \ + "dir.path_ %s != expected path_ %s" % \ + (dir.path_, path_) assert dir.abspath == abspath, \ "dir.abspath %s != expected absolute path %s" % \ (dir.abspath, abspath) + assert dir.abspath_ == abspath_, \ + "dir.abspath_ %s != expected absolute path_ %s" % \ + (dir.abspath_, abspath_) assert dir.up().path == up_path, \ "dir.up().path %s != expected parent path %s" % \ (dir.up().path, up_path) + assert dir.up().path_ == up_path_, \ + "dir.up().path_ %s != expected parent path_ %s" % \ + (dir.up().path_, up_path_) - Dir_test('foo', 'foo/', sub_dir_foo, '.') + Dir_test('foo', 'foo/', sub_dir_foo, './') Dir_test('foo/bar', 'foo/bar/', sub_dir_foo_bar, 'foo/') Dir_test('/foo', '/foo/', '/foo/', '/') Dir_test('/foo/bar', '/foo/bar/', '/foo/bar/', '/foo/') Dir_test('..', sub, sub, wp) - Dir_test('foo/..', '.', sub_dir, sub) + Dir_test('foo/..', './', sub_dir, sub) Dir_test('../foo', sub_foo, sub_foo, sub) - Dir_test('.', '.', sub_dir, sub) - Dir_test('./.', '.', sub_dir, sub) + Dir_test('.', './', sub_dir, sub) + Dir_test('./.', './', sub_dir, sub) Dir_test('foo/./bar', 'foo/bar/', sub_dir_foo_bar, 'foo/') try: @@ -136,7 +160,7 @@ class FSTestCase(unittest.TestCase): f2 = fs.File('d1') except TypeError, x: assert str(x) == ("Tried to lookup Dir '%s' as a File." % - os.path.join('d1', '')), x + 'd1'), x except: raise @@ -150,10 +174,16 @@ class FSTestCase(unittest.TestCase): fs.Dir(string.join(['ddd', 'd1', 'f5'], sep)) kids = map(lambda x: x.path, dir.children()) kids.sort() - assert kids == [os.path.join('ddd', 'd1', ''), + assert kids == [os.path.join('ddd', 'd1'), os.path.join('ddd', 'f1'), os.path.join('ddd', 'f2'), os.path.join('ddd', 'f3')] + kids = map(lambda x: x.path_, dir.children()) + kids.sort() + assert kids == [os.path.join('ddd', 'd1', ''), + os.path.join('ddd', 'f1'), + os.path.join('ddd', 'f2'), + os.path.join('ddd', 'f3')] # Test for sub-classing of node building. global built_it @@ -164,7 +194,7 @@ class FSTestCase(unittest.TestCase): d1.builder_set(Builder()) d1.env_set(Environment()) d1.build() - assert built_it + assert not built_it assert d1.get_parents() == [] @@ -178,35 +208,71 @@ class FSTestCase(unittest.TestCase): e1 = fs.Entry("d1") assert e1.__class__.__name__ == 'Dir' - assert e1.path == "d1/", e1.path + assert e1.path == "d1", e1.path + assert e1.path_ == "d1/", e1.path_ + assert e1.dir.path == ".", e1.dir.path e2 = fs.Entry("d1/f1") assert e2.__class__.__name__ == 'File' assert e2.path == "d1/f1", e2.path + assert e2.path_ == "d1/f1", e2.path_ + assert e2.dir.path == "d1", e2.dir.path e3 = fs.Entry("e3") assert e3.__class__.__name__ == 'Entry' assert e3.path == "e3", e3.path + assert e3.path_ == "e3", e3.path_ + assert e3.dir.path == ".", e3.dir.path e4 = fs.Entry("d1/e4") assert e4.__class__.__name__ == 'Entry' assert e4.path == "d1/e4", e4.path + assert e4.path_ == "d1/e4", e4.path_ + assert e4.dir.path == "d1", e4.dir.path e5 = fs.Entry("e3/e5") assert e3.__class__.__name__ == 'Dir' - assert e3.path == "e3/", e3.path + assert e3.path == "e3", e3.path + assert e3.path_ == "e3/", e3.path_ + assert e3.dir.path == ".", e3.dir.path assert e5.__class__.__name__ == 'Entry' assert e5.path == "e3/e5", e5.path + assert e5.path_ == "e3/e5", e5.path_ + assert e5.dir.path == "e3", e5.dir.path e6 = fs.Dir("d1/e4") assert e6 is e4 assert e4.__class__.__name__ == 'Dir' - assert e4.path == "d1/e4/", e4.path + assert e4.path == "d1/e4", e4.path + assert e4.path_ == "d1/e4/", e4.path_ + assert e4.dir.path == "d1", e4.dir.path e7 = fs.File("e3/e5") assert e7 is e5 assert e5.__class__.__name__ == 'File' assert e5.path == "e3/e5", e5.path + assert e5.path_ == "e3/e5", e5.path_ + assert e5.dir.path == "e3", e5.dir.path + + #XXX test set_signature() + + #XXX test exists() + + #XXX test current() for directories + + #XXX test sconsign() for directories + + #XXX test set_signature() for directories + + #XXX test build() for directories + + #XXX test root() + + #XXX test get_contents() + + #XXX test get_timestamp() + + #XXX test get_oldentry() diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py index b8015c2..cf7e59b 100644 --- a/src/engine/SCons/Node/NodeTests.py +++ b/src/engine/SCons/Node/NodeTests.py @@ -90,6 +90,8 @@ class NodeTestCase(unittest.TestCase): assert node.builder == b def test_current(self): + """Test the default current() method + """ node = SCons.Node.Node() assert node.current() is None @@ -226,6 +228,10 @@ class NodeTestCase(unittest.TestCase): assert node.get_state() == None node.set_state(SCons.Node.executing) assert node.get_state() == SCons.Node.executing + assert SCons.Node.pending < SCons.Node.executing + assert SCons.Node.executing < SCons.Node.up_to_date + assert SCons.Node.up_to_date < SCons.Node.executed + assert SCons.Node.executed < SCons.Node.failed def test_walker(self): """Test walking a Node tree. diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index b7bdecf..2995576 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -36,12 +36,18 @@ import string import types import copy -# Node states: -executing = 1 -executed = 2 +# Node states +# +# These are in "priority" order, so that the maximum value for any +# child/dependency of a node represents the state of that node if +# it has no builder of its own. The canonical example is a file +# system directory, which is only up to date if all of its children +# were up to date. +pending = 1 +executing = 2 up_to_date = 3 -failed = 4 -pending = 5 +executed = 4 +failed = 5 class Node: """The base Node class, for entities that we know how to |
