From f20003e768275ac3d5a1f6402751336c83a6a8af Mon Sep 17 00:00:00 2001 From: stevenknight Date: Tue, 13 Aug 2002 22:18:56 +0000 Subject: [PATCH] Add BuildDir() support to the Repository functionality. git-svn-id: http://scons.tigris.org/svn/scons/trunk@439 fdb21ef1-2011-0410-befe-b5e4ea1792b1 --- src/engine/SCons/Node/FS.py | 72 ++++---- src/engine/SCons/Node/FSTests.py | 20 ++- src/engine/SCons/Scanner/CTests.py | 16 +- src/engine/SCons/Scanner/FortranTests.py | 14 +- test/Repository/BuildDir.py | 199 +++++++++++++++++++++++ 5 files changed, 278 insertions(+), 43 deletions(-) create mode 100644 test/Repository/BuildDir.py diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index 9b804255..157f984f 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -62,13 +62,13 @@ class ParentOfRoot: This class is an instance of the Null object pattern. """ def __init__(self): - self.abspath = "" self.duplicate = 1 - self.path = "" - self.srcpath = "" - self.abspath_='' - self.path_='' - self.srcpath_='' + self.abspath = '' + self.path = '' + self.srcpath = '' + self.abspath_ = '' + self.path_ = '' + self.srcpath_ = '' def is_under(self, dir): return 0 @@ -164,9 +164,9 @@ class FS: drive, path_first = os.path.splitdrive(path_comp[0]) if not path_first: # Absolute path - drive = _my_normcase(drive) + drive_path = _my_normcase(drive) try: - directory = self.Root[drive] + directory = self.Root[drive_path] except KeyError: if not create: raise UserError @@ -174,7 +174,7 @@ class FS: dir.path = dir.path + os.sep dir.abspath = dir.abspath + os.sep dir.srcpath = dir.srcpath + os.sep - self.Root[drive] = dir + self.Root[drive_path] = dir directory = dir path_comp = path_comp[1:] else: @@ -322,8 +322,8 @@ class FS: n = func(None, path) if n: return n - for dir in self.Repositories: - n = func(dir.path, path) + for rep in self.Repositories: + n = func(rep.path, path) if n: return n return None @@ -345,8 +345,8 @@ class FS: if not os.path.isabs(path): if path[0] == '#': path = path[1:] - for dir in self.Repositories: - n = func(dir.path, path) + for rep in self.Repositories: + n = func(rep.path, path) if n: ret.append(n) return ret @@ -471,8 +471,6 @@ class Entry(SCons.Node.Node): # XXX TODO? # Annotate with the creator # rel_path -# srcpath / srcdir -# link / is_linked # linked_targets # is_accessible @@ -608,16 +606,10 @@ class Dir(Entry): # XXX TODO? -# rsrcpath -# source_exists -# derived_exists -# is_on_rpath # base_suf # suffix # addsuffix # accessible -# ignore -# bind # relpath class File(Entry): @@ -711,15 +703,35 @@ class File(Entry): return Entry.exists(self) def rexists(self): - if self.duplicate and not self.created: - self.created = 1 - if self.srcpath != self.path and \ - os.path.exists(self.srcpath): - if os.path.exists(self.path): - os.unlink(self.path) - self.__createDir() - file_link(self.srcpath, self.path) - return Entry.rexists(self) + if self.path != self.srcpath: + if os.path.exists(self.srcpath): + if self.duplicate and not self.created: + self.created = 1 + if os.path.exists(self.path): + os.unlink(self.path) + self.__createDir() + file_link(self.srcpath, self.path) + return 1 + for rep in self.fs.Repositories: + if not os.path.isabs(self.path): + f = os.path.join(rep.path, self.path) + if os.path.exists(f): + return 1 + f = os.path.join(rep.path, self.srcpath) + if os.path.exists(f): + if self.duplicate and not self.created: + self.created = 1 + if os.path.exists(self.path): + os.unlink(self.path) + self.__createDir() + file_link(f, self.path) + else: + self.srcpath = f + self.srcpath_ = f + os.sep + return 1 + return None + else: + return Entry.rexists(self) def scanner_key(self): return os.path.splitext(self.name)[1] diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index 8ffb2e64..f9f1c9e0 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -672,17 +672,25 @@ class RepositoryTestCase(unittest.TestCase): work_d4 = fs.File(os.path.join('work', 'd4')) list = fs.Rsearchall(['d3', work_d4]) assert list == ['d3', work_d4], list + + fs.BuildDir('build', '.') - f1 = fs.File(test.workpath("work", "i_do_not_exist")) - assert not f1.rexists() + f = fs.File(test.workpath("work", "i_do_not_exist")) + assert not f.rexists() test.write(["rep2", "i_exist"], "\n") - f1 = fs.File(test.workpath("work", "i_exist")) - assert f1.rexists() + f = fs.File(test.workpath("work", "i_exist")) + assert f.rexists() test.write(["work", "i_exist_too"], "\n") - f1 = fs.File(test.workpath("work", "i_exist_too")) - assert f1.rexists() + f = fs.File(test.workpath("work", "i_exist_too")) + assert f.rexists() + + f1 = fs.File(os.path.join('build', 'f1')) + assert not f1.rexists() + + f2 = fs.File(os.path.join('build', 'f2')) + assert f2.rexists() test.write(["rep2", "tstamp"], "tstamp\n") # Okay, *this* manipulation accomodates Windows FAT file systems diff --git a/src/engine/SCons/Scanner/CTests.py b/src/engine/SCons/Scanner/CTests.py index 8a70134c..6b949e8b 100644 --- a/src/engine/SCons/Scanner/CTests.py +++ b/src/engine/SCons/Scanner/CTests.py @@ -211,11 +211,19 @@ class CScannerTestCase5(unittest.TestCase): def runTest(self): env = DummyEnvironment([]) s = SCons.Scanner.C.CScan() - deps = s.scan(make_node('f3.cpp'), env, DummyTarget()) - - # Make sure exists() gets called on the file node being + + n = make_node('f3.cpp') + def my_rexists(s=n): + s.rexists_called = 1 + return s.old_rexists() + setattr(n, 'old_rexists', n.rexists) + setattr(n, 'rexists', my_rexists) + + deps = s.scan(n, env, DummyTarget()) + + # Make sure rexists() got called on the file node being # scanned, essential for cooperation with BuildDir functionality. - assert SCons.Node.FS.default_fs.File(test.workpath('f3.cpp')).created + assert n.rexists_called headers = ['d1/f1.h', 'd1/f2.h', 'd1/f3-test.h', 'f1.h', 'f2.h', 'f3-test.h', 'fi.h', 'fj.h'] diff --git a/src/engine/SCons/Scanner/FortranTests.py b/src/engine/SCons/Scanner/FortranTests.py index 6d2a0664..e882153b 100644 --- a/src/engine/SCons/Scanner/FortranTests.py +++ b/src/engine/SCons/Scanner/FortranTests.py @@ -233,11 +233,19 @@ class FortranScannerTestCase9(unittest.TestCase): test.write('f3.f', "\n") env = DummyEnvironment([]) s = SCons.Scanner.Fortran.FortranScan() - deps = s.scan(make_node('fff3.f'), env, DummyTarget()) + + n = make_node('fff3.f') + def my_rexists(s=n): + s.rexists_called = 1 + return s.old_rexists() + setattr(n, 'old_rexists', n.rexists) + setattr(n, 'rexists', my_rexists) + + deps = s.scan(n, env, DummyTarget()) - # Make sure exists() gets called on the file node being + # Make sure rexists() got called on the file node being # scanned, essential for cooperation with BuildDir functionality. - assert SCons.Node.FS.default_fs.File(test.workpath('fff3.f')).created + assert n.rexists_called headers = ['d1/f3.f', 'f3.f'] deps_match(self, deps, map(test.workpath, headers)) diff --git a/test/Repository/BuildDir.py b/test/Repository/BuildDir.py new file mode 100644 index 00000000..2d755903 --- /dev/null +++ b/test/Repository/BuildDir.py @@ -0,0 +1,199 @@ +#!/usr/bin/env python +# +# Copyright (c) 2001, 2002 Steven Knight +# +# 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 sys +import TestSCons + +test = TestSCons.TestSCons() + +test.subdir('repository', ['repository', 'src'], + 'work1', ['work1', 'src'], + 'work2', ['work2', 'src']) + +opts = "-Y " + test.workpath('repository') + +# +test.write(['repository', 'SConstruct'], r""" +BuildDir('build0', 'src', duplicate=0) +BuildDir('build1', 'src', duplicate=1) +SConscript('build0/SConscript') +SConscript('build1/SConscript') +""") + +test.write(['repository', 'src', 'SConscript'], r""" +def cat(env, source, target): + target = str(target[0]) + source = map(str, source) + print 'cat(%s) > %s' % (source, target) + f = open(target, "wb") + for src in source: + f.write(open(src, "rb").read()) + f.close() + +env = Environment(BUILDERS={'Build':Builder(action=cat)}) +env.Build('aaa.mid', 'aaa.in') +env.Build('bbb.mid', 'bbb.in') +env.Build('ccc.mid', 'ccc.in') +env.Build('output', ['aaa.mid', 'bbb.mid', 'ccc.mid']) +""") + +test.write(['repository', 'src', 'aaa.in'], "repository/src/aaa.in\n") +test.write(['repository', 'src', 'bbb.in'], "repository/src/bbb.in\n") +test.write(['repository', 'src', 'ccc.in'], "repository/src/ccc.in\n") + +# Make the entire repository non-writable, so we'll detect +# if we try to write into it accidentally. +test.writable('repository', 0) + +# +test.run(chdir = 'work1', options = opts, arguments = '.') + +test.fail_test(test.read(['work1', 'build0', 'output']) != +"""repository/src/aaa.in +repository/src/bbb.in +repository/src/ccc.in +""") + +test.fail_test(os.path.exists('work1/build0/aaa.in')) +test.fail_test(os.path.exists('work1/build0/bbb.in')) +test.fail_test(os.path.exists('work1/build0/ccc.in')) +test.fail_test(not os.path.exists('work1/build0/aaa.mid')) +test.fail_test(not os.path.exists('work1/build0/bbb.mid')) +test.fail_test(not os.path.exists('work1/build0/ccc.mid')) + +test.fail_test(test.read(['work1', 'build1', 'output']) != +"""repository/src/aaa.in +repository/src/bbb.in +repository/src/ccc.in +""") + +test.fail_test(not os.path.exists('work1/build1/aaa.in')) +test.fail_test(not os.path.exists('work1/build1/bbb.in')) +test.fail_test(not os.path.exists('work1/build1/ccc.in')) +test.fail_test(not os.path.exists('work1/build1/aaa.mid')) +test.fail_test(not os.path.exists('work1/build1/bbb.mid')) +test.fail_test(not os.path.exists('work1/build1/ccc.mid')) + +test.up_to_date(chdir = 'work1', options = opts, arguments = '.') + +# +test.write(['work1', 'src', 'bbb.in'], "work1/src/bbb.in\n") + +test.run(chdir = 'work1', options = opts, arguments = '.') + +test.fail_test(test.read(['work1', 'build0', 'output']) != +"""repository/src/aaa.in +work1/src/bbb.in +repository/src/ccc.in +""") + +test.fail_test(os.path.exists('work1/build0/aaa.in')) +test.fail_test(os.path.exists('work1/build0/bbb.in')) +test.fail_test(os.path.exists('work1/build0/ccc.in')) +test.fail_test(not os.path.exists('work1/build0/aaa.mid')) +test.fail_test(not os.path.exists('work1/build0/bbb.mid')) +test.fail_test(not os.path.exists('work1/build0/ccc.mid')) + +test.fail_test(test.read(['work1', 'build1', 'output']) != +"""repository/src/aaa.in +work1/src/bbb.in +repository/src/ccc.in +""") + +test.fail_test(not os.path.exists('work1/build1/aaa.in')) +test.fail_test(not os.path.exists('work1/build1/bbb.in')) +test.fail_test(not os.path.exists('work1/build1/ccc.in')) +test.fail_test(not os.path.exists('work1/build1/aaa.mid')) +test.fail_test(not os.path.exists('work1/build1/bbb.mid')) +test.fail_test(not os.path.exists('work1/build1/ccc.mid')) + +test.up_to_date(chdir = 'work1', options = opts, arguments = '.') + +# Now build the stuff in the repository, +# and redo the above steps in a fresh work directory. +test.writable('repository', 1) + +test.run(chdir = 'repository', arguments = '.') + +test.writable('repository', 0) + +# +test.run(chdir = 'work2', options = opts, arguments = '.') + +test.fail_test(os.path.exists('work2/build0/aaa.in')) +test.fail_test(os.path.exists('work2/build0/bbb.in')) +test.fail_test(os.path.exists('work2/build0/ccc.in')) +test.fail_test(os.path.exists('work2/build0/aaa.mid')) +test.fail_test(os.path.exists('work2/build0/bbb.mid')) +test.fail_test(os.path.exists('work2/build0/ccc.mid')) +test.fail_test(os.path.exists('work2/build0/output')) + +test.fail_test(os.path.exists('work2/build1/aaa.in')) +test.fail_test(os.path.exists('work2/build1/bbb.in')) +test.fail_test(os.path.exists('work2/build1/ccc.in')) +test.fail_test(os.path.exists('work2/build1/aaa.mid')) +test.fail_test(os.path.exists('work2/build1/bbb.mid')) +test.fail_test(os.path.exists('work2/build1/ccc.mid')) +test.fail_test(os.path.exists('work2/build1/output')) + +test.up_to_date(chdir = 'work2', options = opts, arguments = '.') + +# +test.write(['work2', 'src', 'bbb.in'], "work2/src/bbb.in\n") + +test.run(chdir = 'work2', options = opts, arguments = '.') + +test.fail_test(test.read(['work2', 'build0', 'output']) != +"""repository/src/aaa.in +work2/src/bbb.in +repository/src/ccc.in +""") + +test.fail_test(os.path.exists('work2/build0/aaa.in')) +test.fail_test(os.path.exists('work2/build0/bbb.in')) +test.fail_test(os.path.exists('work2/build0/ccc.in')) +test.fail_test(os.path.exists('work2/build0/aaa.mid')) +test.fail_test(not os.path.exists('work2/build0/bbb.mid')) +test.fail_test(os.path.exists('work2/build0/ccc.mid')) + +test.fail_test(test.read(['work2', 'build1', 'output']) != +"""repository/src/aaa.in +work2/src/bbb.in +repository/src/ccc.in +""") + +test.fail_test(os.path.exists('work2/build1/aaa.in')) +test.fail_test(not os.path.exists('work2/build1/bbb.in')) +test.fail_test(os.path.exists('work2/build1/ccc.in')) +test.fail_test(os.path.exists('work2/build1/aaa.mid')) +test.fail_test(not os.path.exists('work2/build1/bbb.mid')) +test.fail_test(os.path.exists('work2/build1/ccc.mid')) + +test.up_to_date(chdir = 'work2', options = opts, arguments = '.') + +# +test.pass_test() -- 2.26.2