diff options
author | Steven Knight <knight@baldmt.com> | 2003-02-18 08:04:29 (GMT) |
---|---|---|
committer | Steven Knight <knight@baldmt.com> | 2003-02-18 08:04:29 (GMT) |
commit | 5aaf9d3bad67e5ac33a342478e4449e4c71f039c (patch) | |
tree | 9b62b6fab5539b7ef535182b0fe29b05acd4baff /src/engine/SCons | |
parent | bdbeeed7d1492c270c24d809237eb5f724c7cbf5 (diff) | |
download | SCons-5aaf9d3bad67e5ac33a342478e4449e4c71f039c.zip SCons-5aaf9d3bad67e5ac33a342478e4449e4c71f039c.tar.gz SCons-5aaf9d3bad67e5ac33a342478e4449e4c71f039c.tar.bz2 |
Add support for fetching files from rcs.
Diffstat (limited to 'src/engine/SCons')
-rw-r--r-- | src/engine/SCons/Builder.py | 6 | ||||
-rw-r--r-- | src/engine/SCons/Environment.py | 9 | ||||
-rw-r--r-- | src/engine/SCons/EnvironmentTests.py | 12 | ||||
-rw-r--r-- | src/engine/SCons/Node/FS.py | 37 | ||||
-rw-r--r-- | src/engine/SCons/Node/FSTests.py | 29 | ||||
-rw-r--r-- | src/engine/SCons/Node/NodeTests.py | 19 | ||||
-rw-r--r-- | src/engine/SCons/Node/__init__.py | 43 | ||||
-rw-r--r-- | src/engine/SCons/Tool/BitKeeper.py | 62 | ||||
-rw-r--r-- | src/engine/SCons/Tool/CVS.py | 61 | ||||
-rw-r--r-- | src/engine/SCons/Tool/RCS.py | 54 | ||||
-rw-r--r-- | src/engine/SCons/Tool/SCCS.py | 53 | ||||
-rw-r--r-- | src/engine/SCons/Tool/Subversion.py | 61 | ||||
-rw-r--r-- | src/engine/SCons/Tool/__init__.py | 4 |
13 files changed, 441 insertions, 9 deletions
diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py index cf85a4a..b6839e4 100644 --- a/src/engine/SCons/Builder.py +++ b/src/engine/SCons/Builder.py @@ -216,12 +216,16 @@ class BuilderBase: source_factory = None, scanner = None, emitter = None, - multi = 0): + multi = 0, + env = None, + overrides = {}): self.name = name self.action = SCons.Action.Action(action) self.multi = multi self.prefix = prefix self.suffix = suffix + self.env = env + self.overrides = overrides self.set_src_suffix(src_suffix) diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 97d20f9..c2a1ab6 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -367,6 +367,15 @@ class Environment: ret = ret[0] return ret + def SourceCode(self, entry, builder): + """Arrange for a source code builder for (part of) a tree.""" + entries = SCons.Node.arg2nodes(entry, self.fs.Entry) + for entry in entries: + entry.set_src_builder(builder) + if len(entries) == 1: + return entries[0] + return entries + def SideEffect(self, side_effect, target): """Tell scons that side_effects are built as side effects of building targets.""" diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index 657f190..e313939 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -473,6 +473,18 @@ class EnvironmentTestCase(unittest.TestCase): assert 'foo1.in' in map(lambda x: x.path, t.sources) assert 'foo2.in' in map(lambda x: x.path, t.sources) + def test_SourceCode(self): + """Test the SourceCode() method.""" + env = Environment() + e = env.SourceCode('foo', None) + s = e.src_builder() + assert s is None, s + + b = Builder() + env.SourceCode(e, b) + s = e.src_builder() + assert s is b, s + def test_SideEffect(self): """Test the SideEffect() method""" env = Environment() diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index 651d280..5a8687e 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -168,6 +168,9 @@ class ParentOfRoot: def get_dir(self): return None + def src_builder(self): + return None + if os.path.normcase("TeSt") == os.path.normpath("TeSt"): def _my_normcase(x): return x @@ -294,6 +297,24 @@ class Entry(SCons.Node.Node): self._srcnode = self return self._srcnode + def set_src_builder(self, builder): + """Set the source code builder for this node.""" + self.sbuilder = builder + + def src_builder(self): + """Fetch the source code builder for this node. + + If there isn't one, we cache the source code builder specified + for the directory (which in turn will cache the value from its + parent directory, and so on up to the file system root). + """ + try: + scb = self.sbuilder + except AttributeError: + scb = self.dir.src_builder() + self.sbuilder = scb + return scb + # This is for later so we can differentiate between Entry the class and Entry # the method of the FS class. _classEntry = Entry @@ -995,6 +1016,22 @@ 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): + """Return whether this Node has a builder or not. + + 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. + """ + try: + b = self.builder + except AttributeError: + if not os.path.exists(self.path): + b = self.src_builder() + else: + b = None + self.builder = b + return not b is None + def prepare(self): """Prepare for this file to be created.""" diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index fa32c25..f1160c1 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -1168,6 +1168,34 @@ class StringDirTestCase(unittest.TestCase): assert str(f) == os.path.join('sub', 'file') assert not f.exists() +class has_builderTestCase(unittest.TestCase): + def runTest(self): + """Test the has_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) + + h = f1.has_builder() + assert not h, h + + b1 = Builder(fs.File) + d.set_src_builder(b1) + + test.write(['sub', 'f2'], "sub/f2\n") + h = f1.has_builder() # cached from previous has_builder() call + assert not h, h + h = f2.has_builder() + assert not h, h + h = f3.has_builder() + assert h, h + assert f3.builder is b1, f3.builder + class prepareTestCase(unittest.TestCase): def runTest(self): """Test the prepare() method""" @@ -1328,6 +1356,7 @@ if __name__ == "__main__": suite.addTest(RepositoryTestCase()) suite.addTest(find_fileTestCase()) suite.addTest(StringDirTestCase()) + suite.addTest(has_builderTestCase()) suite.addTest(prepareTestCase()) suite.addTest(get_actionsTestCase()) suite.addTest(CacheDirTestCase()) diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py index 86dcc56..b47106d 100644 --- a/src/engine/SCons/Node/NodeTests.py +++ b/src/engine/SCons/Node/NodeTests.py @@ -110,7 +110,7 @@ class ExceptBuilder2: class Environment: def Dictionary(self, *args): return {} - def Override(selv, overrides): + def Override(self, overrides): return overrides class Scanner: @@ -166,7 +166,7 @@ class NodeTestCase(unittest.TestCase): node.overrides = { "foo" : 1, "bar" : 2 } node.build() assert built_it - assert built_target[0] == node, build_target[0] + assert built_target[0] == node, built_target[0] assert built_source == ["rrr", "sss"], built_source assert built_args["foo"] == 1, built_args assert built_args["bar"] == 2, built_args @@ -186,6 +186,21 @@ class NodeTestCase(unittest.TestCase): # [Charles C. 1/7/2002] Uhhh, why are there no asserts here? built_it = None + jjj = MyNode("jjj") + b = Builder() + jjj.builder_set(b) + # NOTE: No env_set()! We should pull the environment from the builder. + b.env = Environment() + b.overrides = { "on" : 3, "off" : 4 } + e.builder = b + jjj.build() + assert built_it + assert built_target[0] == jjj, built_target[0] + assert built_source == [], built_source + assert built_args["on"] == 3, built_args + assert built_args["off"] == 4, built_args + + built_it = None built_order = 0 node = MyNode("xxx") node.builder_set(Builder()) diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index 600c478..27ff4db 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -89,15 +89,21 @@ class Node: pass def __init__(self): + # Note that we no longer explicitly initialize a self.builder + # attribute to None here. That's because the self.builder + # attribute may be created on-the-fly later by a subclass (the + # canonical example being a builder to fetch a file from a + # source code system like CVS or Subversion). + self.sources = [] # source files used to build node self.depends = [] # explicit dependencies (from Depends) self.implicit = None # implicit (scanned) dependencies (None means not scanned yet) self.ignore = [] # dependencies to ignore self.parents = {} self.wkids = None # Kids yet to walk, when it's an array - self.builder = None self.source_scanner = None # implicit scanner from scanner map self.target_scanner = None # explicit scanner from this node's Builder + self.env = None self.state = None self.precious = None @@ -116,12 +122,32 @@ class Node: Annotate(self) def generate_build_env(self): - return self.env.Override(self.overrides) + """Generate the appropriate Environment to build this node.""" + if self.env is None: + # The node itself doesn't have an associated Environment + # (which kind of implies it's a source code file, but who + # knows...). Regardless of why, use the environment (if + # any) associated with the Builder itself. + env = self.builder.env + overrides = self.builder.overrides + else: + # The normal case: use the Environment used to specify how + # this Node is to be built. + env = self.env + overrides = self.overrides + return env.Override(overrides) def _for_each_action(self, func): + """Call a function for each action required to build a node. + + The purpose here is to have one place for the logic that + collects and executes all of the actions for a node's builder, + even though multiple sections of code elsewhere need this logic + to do different things.""" if not self.has_builder(): - return None - action_list = self.pre_actions + self.builder.get_actions() + \ + return + action_list = self.pre_actions + \ + self.builder.get_actions() + \ self.post_actions if not action_list: return @@ -193,7 +219,14 @@ class Node: class(es), generating a bazillion extra calls and slowing things down immensely. """ - return not self.builder is None + try: + b = self.builder + except AttributeError: + # There was no explicit builder for this Node, so initialize + # the self.builder attribute to None now. + self.builder = None + b = self.builder + return not b is None def builder_sig_adapter(self): """Create an adapter for calculating a builder's signature. diff --git a/src/engine/SCons/Tool/BitKeeper.py b/src/engine/SCons/Tool/BitKeeper.py new file mode 100644 index 0000000..94e084f --- /dev/null +++ b/src/engine/SCons/Tool/BitKeeper.py @@ -0,0 +1,62 @@ +"""SCons.Tool.BitKeeper.py + +Tool-specific initialization for the BitKeeper source code control +system. + +There normally shouldn't be any need to import this module directly. +It will usually be imported through the generic SCons.Tool.Tool() +selection method. + +""" + +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import os.path + +import SCons.Builder + +def generate(env, platform): + """Add a Builder factory function and construction variables for + BitKeeper to an Environment.""" + + def BitKeeperFactory(repos, module='', env=env): + """ """ + # fail if repos is not an absolute path name? + if module != '': + module = os.path.join(module, '') + return SCons.Builder.Builder(action = "$BITKEEPERCOM", + env = env, + overrides = {'BKREPOSITORY':repos, + 'BKMODULE':module}) + + setattr(env, 'BitKeeper', BitKeeperFactory) + + env['BITKEEPER'] = 'bk' + env['BITKEEPERFLAGS'] = '' + env['BITKEEPERCOM'] = '$BITKEEPER get $BITKEEPERFLAGS -p $BKREPOSITORY/$BKMODULE$TARGET > $TARGET' + +def exists(env): + return env.Detect('bk') diff --git a/src/engine/SCons/Tool/CVS.py b/src/engine/SCons/Tool/CVS.py new file mode 100644 index 0000000..c8b1f68 --- /dev/null +++ b/src/engine/SCons/Tool/CVS.py @@ -0,0 +1,61 @@ +"""SCons.Tool.CVS.py + +Tool-specific initialization for CVS. + +There normally shouldn't be any need to import this module directly. +It will usually be imported through the generic SCons.Tool.Tool() +selection method. + +""" + +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import os.path + +import SCons.Builder + +def generate(env, platform): + """Add a Builder factory function and construction variables for + CVS to an Environment.""" + + def CVSFactory(repos, module='', env=env): + """ """ + # fail if repos is not an absolute path name? + if module != '': + module = os.path.join(module, '') + return SCons.Builder.Builder(action = '$CVSCOM', + env = env, + overrides = {'CVSREPOSITORY':repos, + 'CVSMODULE':module}) + + setattr(env, 'CVS', CVSFactory) + + env['CVS'] = 'cvs' + env['CVSFLAGS'] = '' + env['CVSCOM'] = '$CVS $CVSFLAGS -d $CVSREPOSITORY co -p $CVSMODULE$TARGET > $TARGET' + +def exists(env): + return env.Detect('cvs') diff --git a/src/engine/SCons/Tool/RCS.py b/src/engine/SCons/Tool/RCS.py new file mode 100644 index 0000000..1f5489b --- /dev/null +++ b/src/engine/SCons/Tool/RCS.py @@ -0,0 +1,54 @@ +"""SCons.Tool.RCS.py + +Tool-specific initialization for RCS. + +There normally shouldn't be any need to import this module directly. +It will usually be imported through the generic SCons.Tool.Tool() +selection method. + +""" + +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import SCons.Builder + +def generate(env, platform): + """Add a Builder factory function and construction variables for + RCS to an Environment.""" + + def RCSFactory(env=env): + """ """ + return SCons.Builder.Builder(action = '$RCSCOM', env = env) + + setattr(env, 'RCS', RCSFactory) + + env['CO'] = 'co' + env['RCS'] = 'rcs' + env['RCSFLAGS'] = '' + env['RCSCOM'] = '$CO $RCSFLAGS -p $TARGET,v > $TARGET' + +def exists(env): + return env.Detect('rcs') diff --git a/src/engine/SCons/Tool/SCCS.py b/src/engine/SCons/Tool/SCCS.py new file mode 100644 index 0000000..1b5d480 --- /dev/null +++ b/src/engine/SCons/Tool/SCCS.py @@ -0,0 +1,53 @@ +"""SCons.Tool.SCCS.py + +Tool-specific initialization for SCCS. + +There normally shouldn't be any need to import this module directly. +It will usually be imported through the generic SCons.Tool.Tool() +selection method. + +""" + +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import SCons.Builder + +def generate(env, platform): + """Add a Builder factory function and construction variables for + SCCS to an Environment.""" + + def SCCSFactory(env=env): + """ """ + return SCons.Builder.Builder(action = '$SCCSCOM', env = env) + + setattr(env, 'SCCS', SCCSFactory) + + env['SCCS'] = 'sccs' + env['SCCSFLAGS'] = '' + env['SCCSCOM'] = '$SCCS $SCCSFLAGS get $TARGET' + +def exists(env): + return env.Detect('sccs') diff --git a/src/engine/SCons/Tool/Subversion.py b/src/engine/SCons/Tool/Subversion.py new file mode 100644 index 0000000..cec3eaf --- /dev/null +++ b/src/engine/SCons/Tool/Subversion.py @@ -0,0 +1,61 @@ +"""SCons.Tool.Subversion.py + +Tool-specific initialization for Subversion. + +There normally shouldn't be any need to import this module directly. +It will usually be imported through the generic SCons.Tool.Tool() +selection method. + +""" + +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import os.path + +import SCons.Builder + +def generate(env, platform): + """Add a Builder factory function and construction variables for + Subversion to an Environment.""" + + def SubversionFactory(repos, module='', env=env): + """ """ + # fail if repos is not an absolute path name? + if module != '': + module = os.path.join(module, '') + return SCons.Builder.Builder(action = '$SUBVERSIONCOM', + env = env, + overrides = {'SUBVERSIONREPOSITORY':repos, + 'SUBVERSIONMODULE':module}) + + setattr(env, 'Subversion', SubversionFactory) + + env['SUBVERSION'] = 'svn' + env['SUBVERSIONFLAGS'] = '' + env['SUBVERSIONCOM'] = '$SUBVERSION $SUBVERSIONFLAGS cat $SUBVERSIONREPOSITORY/$SUBVERSIONMODULE$TARGET > $TARGET' + +def exists(env): + return env.Detect('svn') diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index d2df5bb..b367d32 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -200,9 +200,11 @@ def tool_list(platform, env): else: cxx_compiler = FindTool(['g++'], env) - other_tools = FindAllTools(['dvipdf', 'dvips', + other_tools = FindAllTools(['BitKeeper', 'CVS', + 'dvipdf', 'dvips', 'latex', 'lex', 'pdflatex', 'pdftex', + 'RCS', 'SCCS', 'Subversion', 'tar', 'tex', 'yacc'], env) tools = ([linker, c_compiler, cxx_compiler, |