diff options
author | Steven Knight <knight@baldmt.com> | 2003-03-22 08:31:26 (GMT) |
---|---|---|
committer | Steven Knight <knight@baldmt.com> | 2003-03-22 08:31:26 (GMT) |
commit | 3be8585d1be52d25020b93d99c333d9c9d577b51 (patch) | |
tree | 1841b7b005e680ba16d9a897e759774390a1583c /src/engine/SCons/Node | |
parent | 5ea9b7416ae70c3a4678bcf337bebd41b944cf86 (diff) | |
download | SCons-3be8585d1be52d25020b93d99c333d9c9d577b51.zip SCons-3be8585d1be52d25020b93d99c333d9c9d577b51.tar.gz SCons-3be8585d1be52d25020b93d99c333d9c9d577b51.tar.bz2 |
Make RCS/SCCS/BitKeeper support more transparent.
Diffstat (limited to 'src/engine/SCons/Node')
-rw-r--r-- | src/engine/SCons/Node/FS.py | 120 | ||||
-rw-r--r-- | src/engine/SCons/Node/FSTests.py | 65 | ||||
-rw-r--r-- | src/engine/SCons/Node/NodeTests.py | 21 | ||||
-rw-r--r-- | src/engine/SCons/Node/__init__.py | 5 |
4 files changed, 143 insertions, 68 deletions
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index e5182cd..89566b2 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -154,6 +154,32 @@ def CachePushFunc(target, source, env): CachePush = SCons.Action.Action(CachePushFunc, None) +class _Null: + pass + +_null = _Null() + +DefaultSCCSBuilder = None +DefaultRCSBuilder = None + +def get_DefaultSCCSBuilder(): + global DefaultSCCSBuilder + if DefaultSCCSBuilder is None: + import SCons.Builder + import SCons.Defaults + DefaultSCCSBuilder = SCons.Builder.Builder(action = '$SCCSCOM', + env = SCons.Defaults._default_env) + return DefaultSCCSBuilder + +def get_DefaultRCSBuilder(): + global DefaultRCSBuilder + if DefaultRCSBuilder is None: + import SCons.Builder + import SCons.Defaults + DefaultRCSBuilder = SCons.Builder.Builder(action = '$RCSCOM', + env = SCons.Defaults._default_env) + return DefaultRCSBuilder + # class ParentOfRoot: """ @@ -188,7 +214,7 @@ class ParentOfRoot: return path_elems def src_builder(self): - return None + return _null if os.path.normcase("TeSt") == os.path.normpath("TeSt"): def _my_normcase(x): @@ -265,7 +291,7 @@ class Entry(SCons.Node.Node): try: return self._exists except AttributeError: - self._exists = os.path.exists(self.abspath) + self._exists = _existsp(self.abspath) return self._exists def rexists(self): @@ -382,7 +408,7 @@ class FS: self.pathTop = path self.Root = {} self.Top = None - self.SConstruct = None + self.SConstruct_dir = None self.CachePath = None self.cache_force = None self.cache_show = None @@ -391,8 +417,8 @@ class FS: assert not self.Top, "You can only set the top-level path on an FS object that has not had its File, Dir, or Entry methods called yet." self.pathTop = path - def set_SConstruct(self, path): - self.SConstruct = self.File(path) + def set_SConstruct_dir(self, dir): + self.SConstruct_dir = dir def __setTopLevelDir(self): if not self.Top: @@ -636,7 +662,6 @@ class FS: # Go up one directory d = d.get_dir() return None - def Rsearchall(self, pathlist, must_exist=1, clazz=_classEntry, cwd=None): """Search for a list of somethings in the Repository list.""" @@ -661,16 +686,20 @@ class FS: d = n.get_dir() name = n.name - # Search repositories of all directories that this file is under. + # Search repositories of all directories that this file + # is under. while d: for rep in d.getRepositories(): try: rnode = self.__doLookup(clazz, name, rep) - # Only find the node if it exists (or must_exist is zero) - # and it is not a derived file. If for some reason, we - # are explicitly building a file IN a Repository, we don't - # want it to show up in the build tree. This is usually the - # case with BuildDir(). We only want to find pre-existing files. + # Only find the node if it exists (or + # must_exist is zero) and it is not a + # derived file. If for some reason, we + # are explicitly building a file IN a + # Repository, we don't want it to show up in + # the build tree. This is usually the case + # with BuildDir(). We only want to find + # pre-existing files. if (not must_exist or rnode.exists()) and \ (not rnode.has_builder() or isinstance(rnode, Dir)): ret.append(rnode) @@ -851,6 +880,17 @@ class Dir(Entry): else: return 0 + def rdir(self): + try: + return self._rdir + except AttributeError: + self._rdir = self + if not self.exists(): + n = self.fs.Rsearch(self.path, clazz=Dir, cwd=self.fs.Top) + if n: + self._rdir = n + return self._rdir + def sconsign(self): """Return the .sconsign file info for this directory, creating it first if necessary.""" @@ -1039,9 +1079,10 @@ class File(Entry): so only do thread safe stuff here. Do thread unsafe stuff in built(). """ - if not self.has_builder(): + b = self.has_builder() + if not b and not self.has_src_builder(): return - if self.fs.CachePath: + if b and self.fs.CachePath: if self.fs.cache_show: if CacheRetrieveSilent(self, None, None) == 0: def do_print(action, targets, sources, env, self=self): @@ -1074,27 +1115,56 @@ class File(Entry): if self.fs.CachePath and self.fs.cache_force and os.path.exists(self.path): CachePush(self, None, None) - def has_builder(self, fetch = 1): - """Return whether this Node has a builder or not. + def has_src_builder(self): + """Return whether this Node has a source builder or not. + + If this Node doesn't have an explicit source code builder, this + is where we figure out, on the fly, if there's a transparent + source code builder for it. - If this Node doesn't have an explicit builder, this is where we - figure out, on the fly, if there's a source code builder for it. + Note that if we found a source builder, we also set the + self.builder attribute, so that all of the methods that actually + *build* this file don't have to do anything different. """ try: - b = self.builder + scb = self.sbuilder except AttributeError: - if fetch and not os.path.exists(self.path): - b = self.src_builder() + if self.rexists(): + scb = None else: - b = None - self.builder = b - return not b is None + scb = self.dir.src_builder() + if scb is _null: + scb = None + dir = self.dir.path + sccspath = os.path.join('SCCS', 's.' + self.name) + if dir != '.': + sccspath = os.path.join(dir, sccspath) + if os.path.exists(sccspath): + scb = get_DefaultSCCSBuilder() + else: + rcspath = os.path.join('RCS', self.name + ',v') + if dir != '.': + rcspath = os.path.join(dir, rcspath) + if os.path.exists(rcspath): + scb = get_DefaultRCSBuilder() + self.builder = scb + self.sbuilder = scb + return not scb is None + + def is_derived(self): + """Return whether this file is a derived file or not. + + This overrides the base class method to account for the fact + that a file may be derived transparently from a source code + builder. + """ + return self.has_builder() or self.side_effect or self.has_src_builder() def prepare(self): """Prepare for this file to be created.""" def missing(node): - return not node.has_builder() and not node.linked and not node.rexists() + return not node.has_builder() and not node.linked and not node.rexists() and not node.has_src_builder() missing_sources = filter(missing, self.children()) if missing_sources: desc = "No Builder for target `%s', needed by `%s'." % (missing_sources[0], self) diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index 294a4bb..d460c1e 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -1182,47 +1182,46 @@ class StringDirTestCase(unittest.TestCase): assert str(f) == os.path.join('sub', 'file') assert not f.exists() -class has_builderTestCase(unittest.TestCase): +class has_src_builderTestCase(unittest.TestCase): def runTest(self): - """Test the has_builder() method""" + """Test the has_src_builder() method""" test = TestCmd(workdir = '') fs = SCons.Node.FS.FS(test.workpath('')) os.chdir(test.workpath('')) - test.subdir('sub') - - d = fs.Dir('sub', '.') - f1 = fs.File('f1', d) - f2 = fs.File('f2', d) - f3 = fs.File('f3', d) - f4 = fs.File('f4', d) - f5 = fs.File('f5', d) - f6 = fs.File('f6', d) - f7 = fs.File('f7', d) - - h = f1.has_builder() + test.subdir('sub1') + test.subdir('sub2', ['sub2', 'SCCS'], ['sub2', 'RCS']) + + sub1 = fs.Dir('sub1', '.') + f1 = fs.File('f1', sub1) + f2 = fs.File('f2', sub1) + f3 = fs.File('f3', sub1) + sub2 = fs.Dir('sub2', '.') + f4 = fs.File('f4', sub2) + f5 = fs.File('f5', sub2) + f6 = fs.File('f6', sub2) + + h = f1.has_src_builder() assert not h, h b1 = Builder(fs.File) - d.set_src_builder(b1) + sub1.set_src_builder(b1) - test.write(['sub', 'f2'], "sub/f2\n") - h = f1.has_builder() # cached from previous has_builder() call + test.write(['sub1', 'f2'], "sub1/f2\n") + h = f1.has_src_builder() # cached from previous call assert not h, h - h = f2.has_builder() + h = f2.has_src_builder() assert not h, h - h = f3.has_builder() + h = f3.has_src_builder() assert h, h assert f3.builder is b1, f3.builder - test.write(['sub', 'f4'], "sub/f4\n") - test.write(['sub', 'f6'], "sub/f6\n") - h = f4.has_builder(fetch = 0) + test.write(['sub2', 'SCCS', 's.f5'], "sub2/SCCS/s.f5\n") + test.write(['sub2', 'RCS', 'f6,v'], "sub2/RCS/f6,v\n") + h = f4.has_src_builder() assert not h, h - h = f5.has_builder(fetch = 0) - assert not h, h - h = f6.has_builder(fetch = 1) - assert not h, h - h = f7.has_builder(fetch = 1) + h = f5.has_src_builder() + assert h, h + h = f6.has_src_builder() assert h, h class prepareTestCase(unittest.TestCase): @@ -1267,13 +1266,13 @@ class get_actionsTestCase(unittest.TestCase): a = dir.get_actions() assert a == [], a -class SConstructTestCase(unittest.TestCase): +class SConstruct_dirTestCase(unittest.TestCase): def runTest(self): - """Test setting the SConstruct file""" + """Test setting the SConstruct directory""" fs = SCons.Node.FS.FS() - fs.set_SConstruct('xxx') - assert fs.SConstruct.path == 'xxx' + fs.set_SConstruct_dir(fs.Dir('xxx')) + assert fs.SConstruct_dir.path == 'xxx' class CacheDirTestCase(unittest.TestCase): def runTest(self): @@ -1437,10 +1436,10 @@ if __name__ == "__main__": suite.addTest(RepositoryTestCase()) suite.addTest(find_fileTestCase()) suite.addTest(StringDirTestCase()) - suite.addTest(has_builderTestCase()) + suite.addTest(has_src_builderTestCase()) suite.addTest(prepareTestCase()) suite.addTest(get_actionsTestCase()) - suite.addTest(SConstructTestCase()) + suite.addTest(SConstruct_dirTestCase()) suite.addTest(CacheDirTestCase()) if not unittest.TextTestRunner().run(suite).wasSuccessful(): sys.exit(1) diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py index a9fa361..91b35d0 100644 --- a/src/engine/SCons/Node/NodeTests.py +++ b/src/engine/SCons/Node/NodeTests.py @@ -259,20 +259,23 @@ class NodeTestCase(unittest.TestCase): """Test the has_builder() method """ n1 = SCons.Node.Node() + assert n1.has_builder() == 0 + n1.builder_set(Builder()) + assert n1.has_builder() == 1 + + def test_is_derived(self): + """Test the is_derived() method + """ + n1 = SCons.Node.Node() n2 = SCons.Node.Node() n3 = SCons.Node.Node() - assert n1.has_builder() == 0 - assert n2.has_builder(fetch = 0) == 0 - assert n3.has_builder(fetch = 1) == 0 - - n1.builder_set(Builder()) n2.builder_set(Builder()) - n3.builder_set(Builder()) + n3.side_effect = 1 - assert n1.has_builder() == 1 - assert n2.has_builder(fetch = 0) == 1 - assert n3.has_builder(fetch = 1) == 1 + assert n1.is_derived() == 0 + assert n2.is_derived() == 1 + assert n3.is_derived() == 1 def test_builder_sig_adapter(self): """Test the node's adapter for builder signatures diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index 0a64586..326aee3 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -208,7 +208,7 @@ class Node: def builder_set(self, builder): self.builder = builder - def has_builder(self, fetch = 1): + def has_builder(self): """Return whether this Node has a builder or not. In Boolean tests, this turns out to be a *lot* more efficient @@ -228,6 +228,9 @@ class Node: b = self.builder return not b is None + def is_derived(self): + return self.has_builder() or self.side_effect + def builder_sig_adapter(self): """Create an adapter for calculating a builder's signature. |