Browse Source

Merge topic 'file-accept-empty-lists'

7c516f7e28 file(): TOUCH, TOUCH_NOCREATE and MAKE_DIRECTORY accept empty lists

Acked-by: Kitware Robot <[email protected]>
Tested-by: buildbot <[email protected]>
Merge-request: !9570
Brad King 1 year ago
parent
commit
d1cf2a2206

+ 8 - 0
Help/command/file.rst

@@ -192,6 +192,10 @@ Writing
   With ``TOUCH`` and ``TOUCH_NOCREATE``, the contents of an existing file
   will not be modified.
 
+  .. versionchanged:: 3.30
+    ``<files>`` can be an empty list. CMake 3.29 and earlier required
+    at least one file to be given.
+
 .. signature::
   file(GENERATE [...])
 
@@ -398,6 +402,10 @@ Filesystem
 
   Create the given directories and their parents as needed.
 
+  .. versionchanged:: 3.30
+    ``<directories>`` can be an empty list. CMake 3.29 and earlier required
+    at least one directory to be given.
+
 .. signature::
   file(REMOVE <files>...)
   file(REMOVE_RECURSE <files>...)

+ 17 - 8
Source/cmFileCommand.cxx

@@ -73,6 +73,11 @@ namespace {
 bool HandleWriteImpl(std::vector<std::string> const& args, bool append,
                      cmExecutionStatus& status)
 {
+  if (args.size() < 2) {
+    status.SetError(cmStrCat(
+      args[0], " must be called with at least one additional argument."));
+    return false;
+  }
   auto i = args.begin();
 
   i++; // Get rid of subcommand
@@ -658,8 +663,11 @@ bool HandleStringsCommand(std::vector<std::string> const& args,
 bool HandleGlobImpl(std::vector<std::string> const& args, bool recurse,
                     cmExecutionStatus& status)
 {
-  // File commands has at least one argument
-  assert(args.size() > 1);
+  if (args.size() < 2) {
+    status.SetError(cmStrCat(
+      args[0], " must be called with at least one additional argument."));
+    return false;
+  }
 
   auto i = args.begin();
 
@@ -869,8 +877,8 @@ bool HandleGlobRecurseCommand(std::vector<std::string> const& args,
 bool HandleMakeDirectoryCommand(std::vector<std::string> const& args,
                                 cmExecutionStatus& status)
 {
-  // File command has at least one argument
-  assert(args.size() > 1);
+  // Projects might pass a dynamically generated list of directories, and it
+  // could be an empty list. We should not assume there is at least one.
 
   std::string expr;
   for (std::string const& arg :
@@ -903,8 +911,8 @@ bool HandleMakeDirectoryCommand(std::vector<std::string> const& args,
 bool HandleTouchImpl(std::vector<std::string> const& args, bool create,
                      cmExecutionStatus& status)
 {
-  // File command has at least one argument
-  assert(args.size() > 1);
+  // Projects might pass a dynamically generated list of files, and it
+  // could be an empty list. We should not assume there is at least one.
 
   for (std::string const& arg :
        cmMakeRange(args).advance(1)) // Get rid of subcommand
@@ -3918,8 +3926,9 @@ bool HandleChmodRecurseCommand(std::vector<std::string> const& args,
 bool cmFileCommand(std::vector<std::string> const& args,
                    cmExecutionStatus& status)
 {
-  if (args.size() < 2) {
-    status.SetError("must be called with at least two arguments.");
+  if (args.empty()) {
+    status.SetError(
+      "given no arguments, but it requires at least a sub-command.");
     return false;
   }
 

+ 2 - 2
Tests/CMakeTests/FileTest.cmake.in

@@ -13,13 +13,13 @@ set(Copy-NoDest-STDERR "given no DESTINATION")
 set(Copy-NoFile-RESULT 1)
 set(Copy-NoFile-STDERR "COPY cannot find.*/does_not_exist\\.txt")
 set(Glob-NoArg-RESULT 1)
-set(Glob-NoArg-STDERR "file must be called with at least two arguments")
+set(Glob-NoArg-STDERR "file GLOB must be called with at least one additional argument\\.")
 set(Make_Directory-NoArg-RESULT 1)
 set(Make-Directory-NoArg-STDERR "file must be called with at least two arguments")
 set(MD5-NoFile-RESULT 1)
 set(MD5-NoFile-STDERR "file MD5 failed to read file")
 set(MD5-BadArg1-RESULT 1)
-set(MD5-BadArg1-STDERR "file must be called with at least two arguments")
+set(MD5-BadArg1-STDERR "file MD5 requires a file name and output variable")
 set(MD5-BadArg2-RESULT 1)
 set(MD5-BadArg2-STDERR "file MD5 requires a file name and output variable")
 set(MD5-BadArg4-RESULT 1)

+ 1 - 1
Tests/RunCMake/file/LOCK-error-no-path-stderr.txt

@@ -1,4 +1,4 @@
 CMake Error at LOCK-error-no-path.cmake:[0-9]+ \(file\):
-  file must be called with at least two arguments.
+  sub-command LOCK requires at least two arguments\.
 Call Stack \(most recent call first\):
   CMakeLists.txt:[0-9]+ \(include\)

+ 0 - 1
Tests/RunCMake/file/TOUCH-result.txt

@@ -1 +0,0 @@
-1

+ 0 - 9
Tests/RunCMake/file/TOUCH-stderr.txt

@@ -1,9 +0,0 @@
-^CMake Error at TOUCH\.cmake:[0-9]+ \(file\):
-  file must be called with at least two arguments\.
-Call Stack \(most recent call first\):
-  CMakeLists\.txt:[0-9]+ \(include\)
-+
-CMake Error at TOUCH\.cmake:[0-9]+ \(file\):
-  file must be called with at least two arguments\.
-Call Stack \(most recent call first\):
-  CMakeLists\.txt:[0-9]+ \(include\)

+ 1 - 0
Tests/RunCMake/file/TOUCH.cmake

@@ -12,5 +12,6 @@ if(NOT EXISTS "${file}")
 endif()
 file(REMOVE "${file}")
 
+# Empty arguments used to be an error, but this is valid since CMake 3.30
 file(TOUCH)
 file(TOUCH_NOCREATE)