Provide an error message when a target hasn't been defined.
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Thu, 24 Jan 2002 07:32:50 +0000 (07:32 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Thu, 24 Jan 2002 07:32:50 +0000 (07:32 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@222 fdb21ef1-2011-0410-befe-b5e4ea1792b1

src/CHANGES.txt
src/engine/SCons/Node/FS.py
src/engine/SCons/Node/FSTests.py
src/engine/SCons/Script/__init__.py
test/nonexistent.py [new file with mode: 0644]

index bdced280e5213b9b1dca7048cd014ef63a73705d..9e2591b7a220b89510cb803c0232a0e480e24028 100644 (file)
@@ -51,6 +51,9 @@ RELEASE 0.04 -
 
   - Add the Ignore() method to ignore dependencies.
 
+  - Provide an error message when a nonexistent target is specified
+    on the command line.
+
   From Steve Leblanc:
 
   - Add var=value command-line arguments.
index e21e193b72314b2cb8e3b51158197c90a60c16b8..2ce11512906af760917229e0ec3695548cde7c19 100644 (file)
@@ -128,7 +128,7 @@ class FS:
                   (node.__class__.__name__, str(node), klass.__name__)
         return node
         
-    def __doLookup(self, fsclass, name, directory=None):
+    def __doLookup(self, fsclass, name, directory = None, create = 1):
         """This method differs from the File and Dir factory methods in
         one important way: the meaning of the directory parameter.
         In this method, if directory is None or not supplied, the supplied
@@ -144,6 +144,8 @@ class FS:
             try:
                 directory = self.Root[drive_path]
             except KeyError:
+                if not create:
+                    raise UserError
                 dir = Dir(drive, ParentOfRoot())
                 dir.path = dir.path + os.sep
                 dir.abspath = dir.abspath + os.sep
@@ -160,6 +162,8 @@ class FS:
                 directory = self.__checkClass(directory.entries[path_norm],
                                               Dir)
             except KeyError:
+                if not create:
+                    raise UserError
                 dir_temp = Dir(path_name, directory)
                 directory.entries[path_norm] = dir_temp
                 directory.add_wkid(dir_temp)
@@ -168,6 +172,8 @@ class FS:
         try:
             ret = self.__checkClass(directory.entries[file_name], fsclass)
         except KeyError:
+            if not create:
+                raise UserError
             ret = fsclass(path_comp[-1], directory)
             directory.entries[file_name] = ret
             directory.add_wkid(ret)
@@ -198,7 +204,7 @@ class FS:
         if not dir is None:
             self._cwd = dir
 
-    def Entry(self, name, directory = None):
+    def Entry(self, name, directory = None, create = 1):
         """Lookup or create a generic Entry node with the specified name.
         If the name is a relative path (begins with ./, ../, or a file
         name), then it is looked up relative to the supplied directory
@@ -206,9 +212,9 @@ class FS:
         construction time) if no directory is supplied.
         """
         name, directory = self.__transformPath(name, directory)
-        return self.__doLookup(Entry, name, directory)
+        return self.__doLookup(Entry, name, directory, create)
     
-    def File(self, name, directory = None):
+    def File(self, name, directory = None, create = 1):
         """Lookup or create a File node with the specified name.  If
         the name is a relative path (begins with ./, ../, or a file name),
         then it is looked up relative to the supplied directory node,
@@ -219,9 +225,9 @@ class FS:
         specified path.
         """
         name, directory = self.__transformPath(name, directory)
-        return self.__doLookup(File, name, directory)
+        return self.__doLookup(File, name, directory, create)
 
-    def Dir(self, name, directory = None):
+    def Dir(self, name, directory = None, create = 1):
         """Lookup or create a Dir node with the specified name.  If
         the name is a relative path (begins with ./, ../, or a file name),
         then it is looked up relative to the supplied directory node,
@@ -232,7 +238,7 @@ class FS:
         specified path.
         """
         name, directory = self.__transformPath(name, directory)
-        return self.__doLookup(Dir, name, directory)
+        return self.__doLookup(Dir, name, directory, create)
 
     def BuildDir(self, build_dir, src_dir, duplicate=1):
         """Link the supplied build directory to the source directory
index dc3c559fcf063dcdc048cf9a0bfb754e216994eb..12dfdbe7838feee5ac5eab7519c7bc1769669799 100644 (file)
@@ -421,6 +421,23 @@ class FSTestCase(unittest.TestCase):
         f1 = SCons.Node.FS.default_fs.File(test.workpath("binary_file"))
         assert f1.get_contents() == "Foo\x1aBar", f1.get_contents()
 
+        def nonexistent(method, str):
+            try:
+                x = method(str, create = 0)
+            except UserError:
+                pass
+            else:
+                raise TestFailed, "did not catch expected UserError"
+
+        nonexistent(fs.Entry, 'nonexistent')
+        nonexistent(fs.Entry, 'nonexistent/foo')
+
+        nonexistent(fs.File, 'nonexistent')
+        nonexistent(fs.File, 'nonexistent/foo')
+
+        nonexistent(fs.Dir, 'nonexistent')
+        nonexistent(fs.Dir, 'nonexistent/foo')
+
         #XXX test current() for directories
 
         #XXX test sconsign() for directories
index acbd6c0b7af74d53a67554c74806a7594cb3dcf9..f5ddbfe79333429144ce896f133e85c2e004ceea 100644 (file)
@@ -640,10 +640,18 @@ def _main():
     def Entry(x):
        if isinstance(x, SCons.Node.Node):
            return x
-       else:
-           return SCons.Node.FS.default_fs.Entry(x)
-       
-    nodes = map(Entry, targets)
+        try:
+            node = SCons.Node.FS.default_fs.Entry(x, create = 0)
+        except UserError:
+            str = "scons: *** Do not know how to make target `%s'." % x
+            if not keep_going_on_error:
+                sys.stderr.write(str + "  Stop.\n")
+                sys.exit(2)
+            sys.stderr.write(str + "\n")
+            node = None
+        return node
+
+    nodes = filter(lambda x: x is not None, map(Entry, targets))
 
     if not calc:
         calc = SCons.Sig.Calculator(SCons.Sig.MD5)
diff --git a/test/nonexistent.py b/test/nonexistent.py
new file mode 100644 (file)
index 0000000..892a5cb
--- /dev/null
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2001 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 sys
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', "")
+
+test.run(arguments = 'foo',
+         stderr = "scons: *** Do not know how to make target `foo'.  Stop.\n")
+
+test.run(arguments = '-k foo/bar foo',
+         stderr = """scons: *** Do not know how to make target `foo/bar'.
+scons: *** Do not know how to make target `foo'.
+""")
+
+test.pass_test()