From 1c2053ed54d4ab5276378a54cab9f9300d075e1b Mon Sep 17 00:00:00 2001 From: Steven Knight Date: Fri, 22 Oct 2004 17:42:35 +0000 Subject: Fix the execute-Mkdir-once patch so that it doesn't treat the directory as up-to-date just because it's been made, but still builds all of its children. --- src/engine/SCons/Executor.py | 8 +++ src/engine/SCons/ExecutorTests.py | 33 ++++++++++++- src/engine/SCons/Node/FS.py | 25 ++-------- src/engine/SCons/Node/FSTests.py | 4 -- test/Mkdir.py | 100 +++++++++++++++++++++++++------------- 5 files changed, 109 insertions(+), 61 deletions(-) diff --git a/src/engine/SCons/Executor.py b/src/engine/SCons/Executor.py index 47a72de..6767cc8 100644 --- a/src/engine/SCons/Executor.py +++ b/src/engine/SCons/Executor.py @@ -105,6 +105,9 @@ class Executor: except AttributeError: return al + def do_nothing(self, target, errfunc, **kw): + pass + def __call__(self, target, errfunc, **kw): """Actually execute the action list.""" action_list = self.get_action_list(target) @@ -159,6 +162,11 @@ class Executor: build_env) return self._strfunc + def nullify(self): + self.__call__ = self.do_nothing + self.string = None + self._strfunc = None + def get_raw_contents(self): """Fetch the raw signature contents. This, along with get_contents(), is the real reason this class exists, so we can diff --git a/src/engine/SCons/ExecutorTests.py b/src/engine/SCons/ExecutorTests.py index e259012..d52853c 100644 --- a/src/engine/SCons/ExecutorTests.py +++ b/src/engine/SCons/ExecutorTests.py @@ -50,9 +50,9 @@ class MyAction: for action in self.actions: action(target, source, env, errfunc) def strfunction(self, target, source, env): - return string.join(['STRFUNCTION'] + self.actions + target + source) + return string.join(['STRFUNCTION'] + map(str, self.actions) + target + source) def genstring(self, target, source, env): - return string.join(['GENSTRING'] + self.actions + target + source) + return string.join(['GENSTRING'] + map(str, self.actions) + target + source) def get_raw_contents(self, target, source, env): return string.join(['RAW'] + self.actions + target + source) def get_contents(self, target, source, env): @@ -212,6 +212,35 @@ class ExecutorTestCase(unittest.TestCase): s = x.strfunction() assert s == 'STRFUNCTION action1 action2 t s', s + def test_nullify(self): + """Test the nullify() method""" + env = MyEnvironment(S='string') + + result = [] + def action1(target, source, env, errfunc, result=result, **kw): + result.append('action1') + + env = MyEnvironment() + a = MyAction([action1]) + x = SCons.Executor.Executor(a, env, [], ['t1', 't2'], ['s1', 's2']) + + x(MyNode([], []), None) + assert result == ['action1'], result + s = str(x) + assert s[:10] == 'GENSTRING ', s + s = x.strfunction() + assert s[:12] == 'STRFUNCTION ', s + + del result[:] + x.nullify() + + x(MyNode([], []), None) + assert result == [], result + s = str(x) + assert s == None, s + s = x.strfunction() + assert s == None, s + def test_get_raw_contents(self): """Test fetching the raw signatures contents""" env = MyEnvironment(RC='raw contents') diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index 1e24be0..49cbe7d 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -1111,21 +1111,6 @@ class FS(LocalFS): message = "building associated BuildDir targets: %s" % string.join(map(str, targets)) return targets, message -class DummyExecutor: - """Dummy executor class returned by Dir nodes to bamboozle SCons - into thinking we are an actual derived node, where our sources are - our directory entries.""" - def cleanup(self): - pass - def get_raw_contents(self): - return '' - def get_contents(self): - return '' - def get_timestamp(self): - return 0 - def get_build_env(self): - return None - class Dir(Base): """A class for directories in a file system. """ @@ -1507,7 +1492,7 @@ class File(Base): return includes - def _createDir(self, update=None): + def _createDir(self): # ensure that the directories for this node are # created. @@ -1529,11 +1514,7 @@ class File(Base): # directory. The dirnode.build() method will suppress # the build if it's the default builder. SCons.Node.Node.build(dirnode) - if update: - # Mark this directory as built so we don't try to build - # it again if it has an explicit user-defined Builder. - dirnode.set_state(SCons.Node.executed) - dirnode.built() + dirnode.get_executor().nullify() # The build() action may or may not have actually # created the directory, depending on whether the -n # option was used or not. Delete the _exists and @@ -1672,7 +1653,7 @@ class File(Base): pass else: try: - self._createDir(update=1) + self._createDir() except SCons.Errors.StopError, drive: desc = "No drive `%s' for target `%s'." % (drive, self) raise SCons.Errors.StopError, desc diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index 67c4ffe..c47435f 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -1533,14 +1533,10 @@ class prepareTestCase(unittest.TestCase): xyz.set_state(SCons.Node.up_to_date) xyz.prepare() assert dir_made == [], dir_made - state = new_dir.get_state() - assert state != SCons.Node.executed, state xyz.set_state(0) xyz.prepare() assert dir_made[0].path == "new_dir", dir_made[0] - state = new_dir.get_state() - assert state == SCons.Node.executed, state dir = fs.Dir("dir") dir.prepare() diff --git a/test/Mkdir.py b/test/Mkdir.py index a198571..cbf465e 100644 --- a/test/Mkdir.py +++ b/test/Mkdir.py @@ -34,7 +34,9 @@ import TestSCons test = TestSCons.TestSCons() -test.write('SConstruct', """ +test.subdir('work1', 'work2') + +test.write(['work1', 'SConstruct'], """ Execute(Mkdir('d1')) def cat(env, source, target): target = str(target[0]) @@ -58,9 +60,9 @@ env.Command(Dir('hello'), None, [Mkdir('$TARGET')]) env.Command('hello/world', None, [Touch('$TARGET')]) """) -test.write('f2.in', "f2.in\n") -test.write('f5.in', "f5.in\n") -test.write('f6.in', "f6.in\n") +test.write(['work1', 'f2.in'], "f2.in\n") +test.write(['work1', 'f5.in'], "f5.in\n") +test.write(['work1', 'f6.in'], "f6.in\n") expect = test.wrap_stdout(read_str = 'Mkdir("d1")\n', build_str = """\ @@ -74,34 +76,66 @@ Mkdir("f6.out-Mkdir") Mkdir("hello") Touch("%s") """ % (os.path.join('hello', 'world'))) -test.run(options = '-n', arguments = '.', stdout = expect) - -test.must_not_exist('d1') -test.must_not_exist('f2.out') -test.must_not_exist('d3') -test.must_not_exist('d4') -test.must_not_exist('f5.out') -test.must_not_exist('f6.out') -test.must_not_exist('Mkdir-f6.in') -test.must_not_exist('f6.out-Mkdir') - -test.run() - -test.must_exist('d1') -test.must_match('f2.out', "f2.in\n") -test.must_exist('d3') -test.must_exist('d4') -test.must_match('f5.out', "f5.in\n") -test.must_exist('f6.out') -test.must_exist('Mkdir-f6.in') -test.must_exist('f6.out-Mkdir') -test.must_exist('hello') -test.must_exist('hello/world') - -test.write(['d1', 'file'], "d1/file\n") -test.write(['d3', 'file'], "d3/file\n") -test.write(['Mkdir-f6.in', 'file'], "Mkdir-f6.in/file\n") -test.write(['f6.out-Mkdir', 'file'], "f6.out-Mkdir/file\n") -test.write(['hello', 'file'], "hello/file\n") +test.run(chdir = 'work1', options = '-n', arguments = '.', stdout = expect) + +test.must_not_exist(['work1', 'd1']) +test.must_not_exist(['work1', 'f2.out']) +test.must_not_exist(['work1', 'd3']) +test.must_not_exist(['work1', 'd4']) +test.must_not_exist(['work1', 'f5.out']) +test.must_not_exist(['work1', 'f6.out']) +test.must_not_exist(['work1', 'Mkdir-f6.in']) +test.must_not_exist(['work1', 'f6.out-Mkdir']) + +test.run(chdir = 'work1') + +test.must_exist(['work1', 'd1']) +test.must_match(['work1', 'f2.out'], "f2.in\n") +test.must_exist(['work1', 'd3']) +test.must_exist(['work1', 'd4']) +test.must_match(['work1', 'f5.out'], "f5.in\n") +test.must_exist(['work1', 'f6.out']) +test.must_exist(['work1', 'Mkdir-f6.in']) +test.must_exist(['work1', 'f6.out-Mkdir']) +test.must_exist(['work1', 'hello']) +test.must_exist(['work1', 'hello/world']) + +test.write(['work1', 'd1', 'file'], "d1/file\n") +test.write(['work1', 'd3', 'file'], "d3/file\n") +test.write(['work1', 'Mkdir-f6.in', 'file'], "Mkdir-f6.in/file\n") +test.write(['work1', 'f6.out-Mkdir', 'file'], "f6.out-Mkdir/file\n") +test.write(['work1', 'hello', 'file'], "hello/file\n") + + + + +test.write(['work2', 'SConstruct'], """\ +import os +def catdir(env, source, target): + target = str(target[0]) + source = map(str, source) + outfp = open(target, "wb") + for src in source: + l = os.listdir(src) + l.sort() + for f in l: + f = os.path.join(src, f) + if os.path.isfile(f): + outfp.write(open(f, "rb").read()) + outfp.close() +CatDir = Builder(action = catdir) +env = Environment(BUILDERS = {'CatDir' : CatDir}) +env.Command(Dir('hello'), None, [Mkdir('$TARGET')]) +env.Command('hello/file1.out', 'file1.in', [Copy('$TARGET', '$SOURCE')]) +env.Command('hello/file2.out', 'file2.in', [Copy('$TARGET', '$SOURCE')]) +env.CatDir('output', Dir('hello')) +""") + +test.write(['work2', 'file1.in'], "work2/file1.in\n") +test.write(['work2', 'file2.in'], "work2/file2.in\n") + +test.run(chdir = 'work2', arguments = 'hello/file2.out output') + +test.must_match(['work2', 'output'], "work2/file1.in\nwork2/file2.in\n") test.pass_test() -- cgit v0.12