summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2005-10-08 17:25:47 (GMT)
committerSteven Knight <knight@baldmt.com>2005-10-08 17:25:47 (GMT)
commit7935d8f439453bb30c0db7b1dedcffda71521030 (patch)
tree1969a774c96063c2eb3a09d289a1965df7b4fc44
parente664e763f95c2e24f1f08f11e61828c68baf9854 (diff)
downloadSCons-7935d8f439453bb30c0db7b1dedcffda71521030.zip
SCons-7935d8f439453bb30c0db7b1dedcffda71521030.tar.gz
SCons-7935d8f439453bb30c0db7b1dedcffda71521030.tar.bz2
Remove old, same-named files from a build directory if the file in the source directory does not exist. (Patrick Mezard)
-rw-r--r--src/CHANGES.txt4
-rw-r--r--src/engine/SCons/Node/FS.py18
-rw-r--r--src/engine/SCons/Node/FSTests.py31
-rw-r--r--test/BuildDir/removed-files.py99
4 files changed, 149 insertions, 3 deletions
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index 0d1cf5f..902b915 100644
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -396,6 +396,10 @@ RELEASE 0.97 - XXX
- Fix the -n option when used with -c to print all of the targets
that will be removed for a multi-target Builder call.
+ - If there's no file in the source directory, make sure there isn't
+ one in the build directory, too, to avoid dangling files left
+ over from previous runs when a source file is removed.
+
From Georg Mischler:
- Remove the space after the -o option when invoking the Borland
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py
index ffdc1eb..ceec696 100644
--- a/src/engine/SCons/Node/FS.py
+++ b/src/engine/SCons/Node/FS.py
@@ -1866,12 +1866,24 @@ class File(Base):
"__cacheable__"
# Duplicate from source path if we are set up to do this.
if self.duplicate and not self.is_derived() and not self.linked:
- src=self.srcnode()
+ src = self.srcnode()
if src is self:
return Base.exists(self)
+ # At this point, src is meant to be copied in a build directory.
src = src.rfile()
- if src.abspath != self.abspath and src.exists():
- self.do_duplicate(src)
+ if src.abspath != self.abspath:
+ if src.exists():
+ self.do_duplicate(src)
+ # Can't return 1 here because the duplication might
+ # not actually occur if the -n option is being used.
+ else:
+ # The source file does not exist. Make sure no old
+ # copy remains in the build directory.
+ if Base.exists(self) or self.islink():
+ self.fs.unlink(self.path)
+ # Return None explicitly because the Base.exists() call
+ # above will have cached its value if the file existed.
+ return None
return Base.exists(self)
#
diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py
index 60b0197..71fb3ef 100644
--- a/src/engine/SCons/Node/FSTests.py
+++ b/src/engine/SCons/Node/FSTests.py
@@ -1836,6 +1836,37 @@ class FileTestCase(_tempdirTestCase):
dirs = fff.Dirs(['d1', 'd2'])
assert dirs == [d1, d2], map(str, dirs)
+ def test_exists(self):
+ """Test the File.exists() method"""
+ fs = self.fs
+ test = self.test
+
+ src_f1 = fs.File('src/f1')
+ assert not src_f1.exists(), "%s apparently exists?" % src_f1
+
+ test.subdir('src')
+ test.write(['src', 'f1'], "src/f1\n")
+
+ assert not src_f1.exists(), "%s did not cache previous exists() value" % src_f1
+ src_f1.clear()
+ assert src_f1.exists(), "%s apparently does not exist?" % src_f1
+
+ test.subdir('build')
+ fs.BuildDir('build', 'src')
+ build_f1 = fs.File('build/f1')
+
+ assert build_f1.exists(), "%s did not realize that %s exists" % (build_f1, src_f1)
+ assert os.path.exists(build_f1.abspath), "%s did not get duplicated on disk" % build_f1.abspath
+
+ test.unlink(['src', 'f1'])
+ src_f1.clear() # so the next exists() call will look on disk again
+
+ assert build_f1.exists(), "%s did not cache previous exists() value" % build_f1
+ build_f1.clear()
+ build_f1.linked = None
+ assert not build_f1.exists(), "%s did not realize that %s disappeared" % (build_f1, src_f1)
+ assert not os.path.exists(build_f1.abspath), "%s did not get removed after %s was removed" % (build_f1, src_f1)
+
class RepositoryTestCase(_tempdirTestCase):
diff --git a/test/BuildDir/removed-files.py b/test/BuildDir/removed-files.py
new file mode 100644
index 0000000..7582a93
--- /dev/null
+++ b/test/BuildDir/removed-files.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# 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__"
+
+"""
+Test BuildDir handling of removal of source files.
+
+A C++ Program is created and compiled. First, a header is missing. Then
+the header is added and the compilation should succeed, then the header
+is removed and the compilation should fail again.
+
+Previous versions of SCons did not remove the header from the build
+directory after the source directory's header was removed, which caused
+the compilation to succeed even after the source file was removed.
+
+Test case supplied by Patrick Mezard--many thanks.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+#-------------------------------------------------------------------------------
+#1- Create dep.cpp and the SConstruct. dep.h is missing and the build is
+#expected to fail with 2.
+#-------------------------------------------------------------------------------
+
+test.subdir('src')
+
+test.write(['src', 'dep.cpp'], """\
+#include "dep.h"
+
+int main(int argc, char* argv[])
+{
+ return test_dep();
+}
+""")
+
+test.write('SConstruct', """
+env = Environment()
+env.BuildDir('bin', 'src')
+o = env.Object('bin/dep', 'bin/dep.cpp')
+env.Program('bin/dep', o)
+""")
+
+test.run(arguments = '.', stderr=None, status=2)
+
+
+#-------------------------------------------------------------------------------
+#2- Add dep.h and check the build is OK.
+#-------------------------------------------------------------------------------
+
+test.write(['src', 'dep.h'], """\
+#ifndef DEP_H
+#define DEP_H
+
+inline int test_dep()
+{
+ return 1;
+}
+
+#endif //DEP_H
+""")
+
+test.run(arguments = '.')
+
+
+#-------------------------------------------------------------------------------
+#3- Remove dep.h. The build is expected to fail again like in [1].
+#-------------------------------------------------------------------------------
+
+test.unlink(['src', 'dep.h'])
+
+test.run(arguments = '.', stderr=None, status=2)
+
+
+test.pass_test()