Add BuildDir() support to the Repository functionality.
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Tue, 13 Aug 2002 22:18:56 +0000 (22:18 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Tue, 13 Aug 2002 22:18:56 +0000 (22:18 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@439 fdb21ef1-2011-0410-befe-b5e4ea1792b1

src/engine/SCons/Node/FS.py
src/engine/SCons/Node/FSTests.py
src/engine/SCons/Scanner/CTests.py
src/engine/SCons/Scanner/FortranTests.py
test/Repository/BuildDir.py [new file with mode: 0644]

index 9b80425507413ce0b109fda3c46ff861fc3153f8..157f984ff80309369cec12d754a2e75dfd594b3c 100644 (file)
@@ -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]
index 8ffb2e64ca980cdd826309d2f0f6ee16f998418d..f9f1c9e0f1ea1099e43dbda7c1a22a07120a84ab 100644 (file)
@@ -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
index 8a70134ca57dbf4f4ba36c2034f04d96dc0d7fc1..6b949e8bc1ba818ff12121c3fd42575d2ed89d4e 100644 (file)
@@ -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']
index 6d2a0664255965881de8d2793c36f22ec9e48909..e882153bd1ecd5c570356fc7032b930f5119b0c5 100644 (file)
@@ -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 (file)
index 0000000..2d75590
--- /dev/null
@@ -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()