From df03c65239ee829c8e1a9a932721d75a5a785416 Mon Sep 17 00:00:00 2001
From: Steven Knight <knight@baldmt.com>
Date: Wed, 20 Oct 2004 23:59:50 +0000
Subject: Allow explicit target_factory=Dir with Builders that make a directory
 to override the default, implicit make-a-directory Builder..

---
 doc/man/scons.1                    |  2 +-
 src/CHANGES.txt                    |  3 +++
 src/engine/SCons/Builder.py        |  4 +++-
 src/engine/SCons/BuilderTests.py   |  2 ++
 src/engine/SCons/Node/FS.py        |  1 +
 src/engine/SCons/Node/NodeTests.py | 13 ++++++++++++-
 src/engine/SCons/Node/__init__.py  |  9 +++++++++
 test/Dir.py                        | 16 ++++++++++++++++
 8 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/doc/man/scons.1 b/doc/man/scons.1
index f21e00b..b94d680 100644
--- a/doc/man/scons.1
+++ b/doc/man/scons.1
@@ -7655,7 +7655,7 @@ Example:
 MakeDirectoryBuilder = Builder(action=my_mkdir, target_factory=Dir)
 env = Environment()
 env.Append(BUILDERS = {'MakeDirectory':MakeDirectoryBuilder})
-env.MakeDirectory('new_directory')
+env.MakeDirectory('new_directory', [])
 .EE
 
 .IP source_factory
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index 8e0a1ce..5a4062f 100644
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -97,6 +97,9 @@ RELEASE 0.97 - XXX
   - Packaging build fix:  Rebuild the files that are use to report the
     --version of SCons whenever the development version number changes.
 
+  - Fix the ability to specify a target_factory of Dir() to a Builder,
+    which the default create-a-directory Builder was interfering with.
+
   From Clive Levinson:
 
   - Make ParseConfig() recognize and add -mno-cygwin to $LINKFLAGS and
diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py
index e9d4e11..6afff58 100644
--- a/src/engine/SCons/Builder.py
+++ b/src/engine/SCons/Builder.py
@@ -284,7 +284,7 @@ def _init_nodes(builder, env, overrides, executor_kw, tlist, slist):
     for t in tlist:
         if t.side_effect:
             raise UserError, "Multiple ways to build the same target were specified for: %s" % str(t)
-        if t.has_builder():
+        if t.has_explicit_builder():
             if not t.env is None and not t.env is env:
                 t_contents = t.builder.action.get_contents(tlist, slist, t.env)
                 contents = t.builder.action.get_contents(tlist, slist, env)
@@ -412,6 +412,7 @@ class BuilderBase:
                         single_source = 0,
                         name = None,
                         chdir = _null,
+                        is_explicit = 1,
                         **overrides):
         if __debug__: logInstanceCreation(self, 'BuilderBase')
         self.action = SCons.Action.Action(action)
@@ -453,6 +454,7 @@ class BuilderBase:
         self.executor_kw = {}
         if not chdir is _null:
             self.executor_kw['chdir'] = chdir
+        self.is_explicit = is_explicit
 
     def __nonzero__(self):
         raise InternalError, "Do not test for the Node.builder attribute directly; use Node.has_builder() instead"
diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py
index a67d22a..2075bf0 100644
--- a/src/engine/SCons/BuilderTests.py
+++ b/src/engine/SCons/BuilderTests.py
@@ -140,6 +140,8 @@ class MyNode_without_target_from_source:
         self.builder = builder
     def has_builder(self):
         return not self.builder is None
+    def has_explicit_builder(self):
+        return not self.builder is None and self.builder.is_explicit
     def env_set(self, env, safe=0):
         self.env = env
     def add_source(self, source):
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py
index 2bd68e1..883b82c 100644
--- a/src/engine/SCons/Node/FS.py
+++ b/src/engine/SCons/Node/FS.py
@@ -194,6 +194,7 @@ def get_MkdirBuilder():
         MkdirBuilder = SCons.Builder.Builder(action = Mkdir,
                                              env = None,
                                              explain = None,
+                                             is_explicit = None,
                                              name = "MkdirBuilder")
     return MkdirBuilder
 
diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py
index f8cd62b..ce67781 100644
--- a/src/engine/SCons/Node/NodeTests.py
+++ b/src/engine/SCons/Node/NodeTests.py
@@ -93,10 +93,11 @@ class Environment:
         self._dict.update(dict)
 
 class Builder:
-    def __init__(self):
+    def __init__(self, is_explicit=1):
         self.env = Environment()
         self.overrides = {}
         self.action = MyAction()
+        self.is_explicit = is_explicit
     def targets(self, t):
         return [t]
     def get_actions(self):
@@ -314,6 +315,16 @@ class NodeTestCase(unittest.TestCase):
         n1.builder_set(Builder())
         assert n1.has_builder() == 1
 
+    def test_has_explicit_builder(self):
+        """Test the has_explicit_builder() method
+        """
+        n1 = SCons.Node.Node()
+        assert not n1.has_explicit_builder()
+        n1.builder_set(Builder(is_explicit=1))
+        assert n1.has_explicit_builder()
+        n1.builder_set(Builder(is_explicit=None))
+        assert not n1.has_explicit_builder()
+
     def test_multiple_side_effect_has_builder(self):
         """Test the multiple_side_effect_has_builder() method
         """
diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py
index 338df07..38cff92 100644
--- a/src/engine/SCons/Node/__init__.py
+++ b/src/engine/SCons/Node/__init__.py
@@ -307,6 +307,15 @@ class Node:
             b = self.builder
         return not b is None
 
+    def has_explicit_builder(self):
+        """Return whether this Node has an explicit builder
+
+        This allows an internal Builder created by SCons to be marked
+        non-explicit, so that it can be overridden by an explicit
+        builder that the user supplies (the canonical example being
+        directories)."""
+        return self.has_builder() and self.builder.is_explicit
+
     multiple_side_effect_has_builder = has_builder
 
     def is_derived(self):
diff --git a/test/Dir.py b/test/Dir.py
index 5c4eaa3..d7ec9ae 100644
--- a/test/Dir.py
+++ b/test/Dir.py
@@ -55,4 +55,20 @@ bbb_bbb
 scons: `.' is up to date.
 """))
 
+
+
+test.write('SConstruct', """\
+import os
+def my_mkdir(target=None, source=None, env=None):
+    os.mkdir(str(target[0]))
+
+MDBuilder = Builder(action=my_mkdir, target_factory=Dir)
+env = Environment()
+env.Append(BUILDERS = {'MD':MDBuilder})
+env.MD(target='sub1', source=['SConstruct'])
+env.MD(target='sub2', source=['SConstruct'], OVERRIDE='foo')
+""")
+
+test.run()
+
 test.pass_test()
-- 
cgit v0.12