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/Node | |
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/Node')
-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 |
4 files changed, 121 insertions, 7 deletions
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. |