Browse Source

Merge topic 'cmFileCommand-refactoring'

a7a5f376bc cmFileCommand: Use cmSubcommandTable
b66b7464ab Introduce cmSubcommandTable
2b785875fb cmFileCommand: turn into free function
9703c65718 cmFileCommand: put subcommands in unnamed namespace
64f987c174 cmFileCommand: port to cmExecutionStatus

Acked-by: Kitware Robot <[email protected]>
Merge-request: !3657
Brad King 6 years ago
parent
commit
1996e01578

+ 2 - 0
Source/CMakeLists.txt

@@ -639,6 +639,8 @@ set(SRCS
   cmStringReplaceHelper.cxx
   cmStringCommand.cxx
   cmStringCommand.h
+  cmSubcommandTable.cxx
+  cmSubcommandTable.h
   cmSubdirCommand.cxx
   cmSubdirCommand.h
   cmSubdirDependsCommand.cxx

+ 1 - 1
Source/cmCommands.cxx

@@ -128,7 +128,7 @@ void GetScriptingCommands(cmState* state)
                            cm::make_unique<cmExecProgramCommand>());
   state->AddBuiltinCommand("execute_process",
                            cm::make_unique<cmExecuteProcessCommand>());
-  state->AddBuiltinCommand("file", cm::make_unique<cmFileCommand>());
+  state->AddBuiltinCommand("file", cmFileCommand);
   state->AddBuiltinCommand("find_file", cm::make_unique<cmFindFileCommand>());
   state->AddBuiltinCommand("find_library",
                            cm::make_unique<cmFindLibraryCommand>());

File diff suppressed because it is too large
+ 183 - 238
Source/cmFileCommand.cxx


+ 2 - 65
Source/cmFileCommand.h

@@ -8,72 +8,9 @@
 #include <string>
 #include <vector>
 
-#include "cm_memory.hxx"
-
-#include "cmCommand.h"
-
 class cmExecutionStatus;
 
-/** \class cmFileCommand
- * \brief Command for manipulation of files
- *
- */
-class cmFileCommand : public cmCommand
-{
-public:
-  /**
-   * This is a virtual constructor for the command.
-   */
-  std::unique_ptr<cmCommand> Clone() override
-  {
-    return cm::make_unique<cmFileCommand>();
-  }
-
-  /**
-   * This is called when the command is first encountered in
-   * the CMakeLists.txt file.
-   */
-  bool InitialPass(std::vector<std::string> const& args,
-                   cmExecutionStatus& status) override;
-
-protected:
-  bool HandleRename(std::vector<std::string> const& args);
-  bool HandleRemove(std::vector<std::string> const& args, bool recurse);
-  bool HandleWriteCommand(std::vector<std::string> const& args, bool append);
-  bool HandleReadCommand(std::vector<std::string> const& args);
-  bool HandleHashCommand(std::vector<std::string> const& args);
-  bool HandleStringsCommand(std::vector<std::string> const& args);
-  bool HandleGlobCommand(std::vector<std::string> const& args, bool recurse);
-  bool HandleTouchCommand(std::vector<std::string> const& args, bool create);
-  bool HandleMakeDirectoryCommand(std::vector<std::string> const& args);
-
-  bool HandleRelativePathCommand(std::vector<std::string> const& args);
-  bool HandleCMakePathCommand(std::vector<std::string> const& args,
-                              bool nativePath);
-  bool HandleReadElfCommand(std::vector<std::string> const& args);
-  bool HandleRPathChangeCommand(std::vector<std::string> const& args);
-  bool HandleRPathCheckCommand(std::vector<std::string> const& args);
-  bool HandleRPathRemoveCommand(std::vector<std::string> const& args);
-  bool HandleDifferentCommand(std::vector<std::string> const& args);
-
-  bool HandleCopyCommand(std::vector<std::string> const& args);
-  bool HandleInstallCommand(std::vector<std::string> const& args);
-  bool HandleDownloadCommand(std::vector<std::string> const& args);
-  bool HandleUploadCommand(std::vector<std::string> const& args);
-
-  bool HandleTimestampCommand(std::vector<std::string> const& args);
-  bool HandleGenerateCommand(std::vector<std::string> const& args);
-  bool HandleLockCommand(std::vector<std::string> const& args);
-  bool HandleSizeCommand(std::vector<std::string> const& args);
-  bool HandleReadSymlinkCommand(std::vector<std::string> const& args);
-  bool HandleCreateLinkCommand(std::vector<std::string> const& args);
-  bool HandleGetRuntimeDependenciesCommand(
-    std::vector<std::string> const& args);
-
-private:
-  void AddEvaluationFile(const std::string& inputName,
-                         const std::string& outputExpr,
-                         const std::string& condition, bool inputIsContent);
-};
+bool cmFileCommand(std::vector<std::string> const& args,
+                   cmExecutionStatus& status);
 
 #endif

+ 23 - 23
Source/cmFileCopier.cxx

@@ -3,8 +3,8 @@
 
 #include "cmFileCopier.h"
 
+#include "cmExecutionStatus.h"
 #include "cmFSPermissions.h"
-#include "cmFileCommand.h"
 #include "cmFileTimes.h"
 #include "cmMakefile.h"
 #include "cmStringAlgorithms.h"
@@ -21,9 +21,9 @@
 
 using namespace cmFSPermissions;
 
-cmFileCopier::cmFileCopier(cmFileCommand* command, const char* name)
-  : FileCommand(command)
-  , Makefile(command->GetMakefile())
+cmFileCopier::cmFileCopier(cmExecutionStatus& status, const char* name)
+  : Status(status)
+  , Makefile(&status.GetMakefile())
   , Name(name)
   , Always(false)
   , MatchlessFiles(true)
@@ -92,7 +92,7 @@ bool cmFileCopier::SetPermissions(const std::string& toFile,
     if (!cmSystemTools::SetPermissions(toFile, permissions)) {
       std::ostringstream e;
       e << this->Name << " cannot set permissions on \"" << toFile << "\"";
-      this->FileCommand->SetError(e.str());
+      this->Status.SetError(e.str());
       return false;
     }
   }
@@ -106,7 +106,7 @@ bool cmFileCopier::CheckPermissions(std::string const& arg,
   if (!cmFSPermissions::stringToModeT(arg, permissions)) {
     std::ostringstream e;
     e << this->Name << " given invalid permission \"" << arg << "\".";
-    this->FileCommand->SetError(e.str());
+    this->Status.SetError(e.str());
     return false;
   }
   return true;
@@ -122,7 +122,7 @@ bool cmFileCopier::ReportMissing(const std::string& fromFile)
   // The input file does not exist and installation is not optional.
   std::ostringstream e;
   e << this->Name << " cannot find \"" << fromFile << "\".";
-  this->FileCommand->SetError(e.str());
+  this->Status.SetError(e.str());
   return false;
 }
 
@@ -130,7 +130,7 @@ void cmFileCopier::NotBeforeMatch(std::string const& arg)
 {
   std::ostringstream e;
   e << "option " << arg << " may not appear before PATTERN or REGEX.";
-  this->FileCommand->SetError(e.str());
+  this->Status.SetError(e.str());
   this->Doing = DoingError;
 }
 
@@ -138,7 +138,7 @@ void cmFileCopier::NotAfterMatch(std::string const& arg)
 {
   std::ostringstream e;
   e << "option " << arg << " may not appear after PATTERN or REGEX.";
-  this->FileCommand->SetError(e.str());
+  this->Status.SetError(e.str());
   this->Doing = DoingError;
 }
 
@@ -175,7 +175,7 @@ bool cmFileCopier::GetDefaultDirectoryPermissions(mode_t** mode)
     cmSystemTools::ExpandListArgument(default_dir_install_permissions, items);
     for (const auto& arg : items) {
       if (!this->CheckPermissions(arg, **mode)) {
-        this->FileCommand->SetError(
+        this->Status.SetError(
           " Set with CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS variable.");
         return false;
       }
@@ -195,7 +195,7 @@ bool cmFileCopier::Parse(std::vector<std::string> const& args)
     if (!this->CheckKeyword(args[i]) && !this->CheckValue(args[i])) {
       std::ostringstream e;
       e << "called with unknown argument \"" << args[i] << "\".";
-      this->FileCommand->SetError(e.str());
+      this->Status.SetError(e.str());
       return false;
     }
 
@@ -209,7 +209,7 @@ bool cmFileCopier::Parse(std::vector<std::string> const& args)
   if (this->Destination.empty()) {
     std::ostringstream e;
     e << this->Name << " given no DESTINATION";
-    this->FileCommand->SetError(e.str());
+    this->Status.SetError(e.str());
     return false;
   }
 
@@ -342,7 +342,7 @@ bool cmFileCopier::CheckValue(std::string const& arg)
       } else {
         std::ostringstream e;
         e << "could not compile PATTERN \"" << arg << "\".";
-        this->FileCommand->SetError(e.str());
+        this->Status.SetError(e.str());
         this->Doing = DoingError;
       }
     } break;
@@ -354,7 +354,7 @@ bool cmFileCopier::CheckValue(std::string const& arg)
       } else {
         std::ostringstream e;
         e << "could not compile REGEX \"" << arg << "\".";
-        this->FileCommand->SetError(e.str());
+        this->Status.SetError(e.str());
         this->Doing = DoingError;
       }
       break;
@@ -397,8 +397,8 @@ bool cmFileCopier::Run(std::vector<std::string> const& args)
       file += "/";
       file += f;
     } else if (!this->FilesFromDir.empty()) {
-      this->FileCommand->SetError("option FILES_FROM_DIR requires all files "
-                                  "to be specified as relative paths.");
+      this->Status.SetError("option FILES_FROM_DIR requires all files "
+                            "to be specified as relative paths.");
       return false;
     } else {
       file = f;
@@ -447,7 +447,7 @@ bool cmFileCopier::Install(const std::string& fromFile,
   if (fromFile.empty()) {
     std::ostringstream e;
     e << "INSTALL encountered an empty string input file name.";
-    this->FileCommand->SetError(e.str());
+    this->Status.SetError(e.str());
     return false;
   }
 
@@ -515,7 +515,7 @@ bool cmFileCopier::InstallSymlinkChain(std::string& fromFile,
       if (!cmSystemTools::CreateSymlink(symlinkTarget, toFile)) {
         std::ostringstream e;
         e << this->Name << " cannot create symlink \"" << toFile << "\".";
-        this->FileCommand->SetError(e.str());
+        this->Status.SetError(e.str());
         return false;
       }
     }
@@ -536,7 +536,7 @@ bool cmFileCopier::InstallSymlink(const std::string& fromFile,
     std::ostringstream e;
     e << this->Name << " cannot read symlink \"" << fromFile
       << "\" to duplicate at \"" << toFile << "\".";
-    this->FileCommand->SetError(e.str());
+    this->Status.SetError(e.str());
     return false;
   }
 
@@ -567,7 +567,7 @@ bool cmFileCopier::InstallSymlink(const std::string& fromFile,
       std::ostringstream e;
       e << this->Name << " cannot duplicate symlink \"" << fromFile
         << "\" at \"" << toFile << "\".";
-      this->FileCommand->SetError(e.str());
+      this->Status.SetError(e.str());
       return false;
     }
   }
@@ -596,7 +596,7 @@ bool cmFileCopier::InstallFile(const std::string& fromFile,
     std::ostringstream e;
     e << this->Name << " cannot copy file \"" << fromFile << "\" to \""
       << toFile << "\".";
-    this->FileCommand->SetError(e.str());
+    this->Status.SetError(e.str());
     return false;
   }
 
@@ -612,7 +612,7 @@ bool cmFileCopier::InstallFile(const std::string& fromFile,
       std::ostringstream e;
       e << this->Name << " cannot set modification time on \"" << toFile
         << "\"";
-      this->FileCommand->SetError(e.str());
+      this->Status.SetError(e.str());
       return false;
     }
   }
@@ -649,7 +649,7 @@ bool cmFileCopier::InstallDirectory(const std::string& source,
     std::ostringstream e;
     e << this->Name << " cannot make directory \"" << destination
       << "\": " << cmSystemTools::GetLastSystemError();
-    this->FileCommand->SetError(e.str());
+    this->Status.SetError(e.str());
     return false;
   }
 

+ 3 - 3
Source/cmFileCopier.h

@@ -12,19 +12,19 @@
 #include <string>
 #include <vector>
 
-class cmFileCommand;
+class cmExecutionStatus;
 class cmMakefile;
 
 // File installation helper class.
 struct cmFileCopier
 {
-  cmFileCopier(cmFileCommand* command, const char* name = "COPY");
+  cmFileCopier(cmExecutionStatus& status, const char* name = "COPY");
   virtual ~cmFileCopier();
 
   bool Run(std::vector<std::string> const& args);
 
 protected:
-  cmFileCommand* FileCommand;
+  cmExecutionStatus& Status;
   cmMakefile* Makefile;
   const char* Name;
   bool Always;

+ 20 - 20
Source/cmFileInstaller.cxx

@@ -3,8 +3,8 @@
 
 #include "cmFileInstaller.h"
 
+#include "cmExecutionStatus.h"
 #include "cmFSPermissions.h"
-#include "cmFileCommand.h"
 #include "cmMakefile.h"
 #include "cmSystemTools.h"
 
@@ -14,8 +14,8 @@
 
 using namespace cmFSPermissions;
 
-cmFileInstaller::cmFileInstaller(cmFileCommand* command)
-  : cmFileCopier(command, "INSTALL")
+cmFileInstaller::cmFileInstaller(cmExecutionStatus& status)
+  : cmFileCopier(status, "INSTALL")
   , InstallType(cmInstallType_FILES)
   , Optional(false)
   , MessageAlways(false)
@@ -111,19 +111,19 @@ bool cmFileInstaller::Parse(std::vector<std::string> const& args)
 
   if (!this->Rename.empty()) {
     if (!this->FilesFromDir.empty()) {
-      this->FileCommand->SetError("INSTALL option RENAME may not be "
-                                  "combined with FILES_FROM_DIR.");
+      this->Status.SetError("INSTALL option RENAME may not be "
+                            "combined with FILES_FROM_DIR.");
       return false;
     }
     if (this->InstallType != cmInstallType_FILES &&
         this->InstallType != cmInstallType_PROGRAMS) {
-      this->FileCommand->SetError("INSTALL option RENAME may be used "
-                                  "only with FILES or PROGRAMS.");
+      this->Status.SetError("INSTALL option RENAME may be used "
+                            "only with FILES or PROGRAMS.");
       return false;
     }
     if (this->Files.size() > 1) {
-      this->FileCommand->SetError("INSTALL option RENAME may be used "
-                                  "only with one file.");
+      this->Status.SetError("INSTALL option RENAME may be used "
+                            "only with one file.");
       return false;
     }
   }
@@ -134,9 +134,9 @@ bool cmFileInstaller::Parse(std::vector<std::string> const& args)
 
   if (((this->MessageAlways ? 1 : 0) + (this->MessageLazy ? 1 : 0) +
        (this->MessageNever ? 1 : 0)) > 1) {
-    this->FileCommand->SetError("INSTALL options MESSAGE_ALWAYS, "
-                                "MESSAGE_LAZY, and MESSAGE_NEVER "
-                                "are mutually exclusive.");
+    this->Status.SetError("INSTALL options MESSAGE_ALWAYS, "
+                          "MESSAGE_LAZY, and MESSAGE_NEVER "
+                          "are mutually exclusive.");
     return false;
   }
 
@@ -213,7 +213,7 @@ bool cmFileInstaller::CheckKeyword(std::string const& arg)
     e << "INSTALL called with old-style " << arg << " argument.  "
       << "This script was generated with an older version of CMake.  "
       << "Re-run this cmake version on your build tree.";
-    this->FileCommand->SetError(e.str());
+    this->Status.SetError(e.str());
     this->Doing = DoingError;
   } else {
     return this->cmFileCopier::CheckKeyword(arg);
@@ -257,7 +257,7 @@ bool cmFileInstaller::GetTargetTypeFromString(const std::string& stype)
   } else {
     std::ostringstream e;
     e << "Option TYPE given unknown value \"" << stype << "\".";
-    this->FileCommand->SetError(e.str());
+    this->Status.SetError(e.str());
     return false;
   }
   return true;
@@ -269,8 +269,8 @@ bool cmFileInstaller::HandleInstallDestination()
 
   // allow for / to be a valid destination
   if (destination.size() < 2 && destination != "/") {
-    this->FileCommand->SetError("called with inappropriate arguments. "
-                                "No DESTINATION provided or .");
+    this->Status.SetError("called with inappropriate arguments. "
+                          "No DESTINATION provided or .");
     return false;
   }
 
@@ -300,7 +300,7 @@ bool cmFileInstaller::HandleInstallDestination()
       if (relative) {
         // This is relative path on unix or windows. Since we are doing
         // destdir, this case does not make sense.
-        this->FileCommand->SetError(
+        this->Status.SetError(
           "called with relative DESTINATION. This "
           "does not make sense when using DESTDIR. Specify "
           "absolute path or remove DESTDIR environment variable.");
@@ -315,7 +315,7 @@ bool cmFileInstaller::HandleInstallDestination()
           "absolute path or remove DESTDIR environment variable."
           "\nDESTINATION=\n";
         message += destination;
-        this->FileCommand->SetError(message);
+        this->Status.SetError(message);
         return false;
       }
     }
@@ -335,14 +335,14 @@ bool cmFileInstaller::HandleInstallDestination()
       if (!cmSystemTools::MakeDirectory(destination, default_dir_mode)) {
         std::string errstring = "cannot create directory: " + destination +
           ". Maybe need administrative privileges.";
-        this->FileCommand->SetError(errstring);
+        this->Status.SetError(errstring);
         return false;
       }
     }
     if (!cmSystemTools::FileIsDirectory(destination)) {
       std::string errstring =
         "INSTALL destination: " + destination + " is not a directory.";
-      this->FileCommand->SetError(errstring);
+      this->Status.SetError(errstring);
       return false;
     }
   }

+ 2 - 2
Source/cmFileInstaller.h

@@ -12,11 +12,11 @@
 #include <string>
 #include <vector>
 
-class cmFileCommand;
+class cmExecutionStatus;
 
 struct cmFileInstaller : public cmFileCopier
 {
-  cmFileInstaller(cmFileCommand* command);
+  cmFileInstaller(cmExecutionStatus& status);
   ~cmFileInstaller() override;
 
 protected:

+ 5 - 5
Source/cmRuntimeDependencyArchive.cxx

@@ -6,7 +6,7 @@
 #include "cmBinUtilsLinuxELFLinker.h"
 #include "cmBinUtilsMacOSMachOLinker.h"
 #include "cmBinUtilsWindowsPELinker.h"
-#include "cmCommand.h"
+#include "cmExecutionStatus.h"
 #include "cmMakefile.h"
 #include "cmStateTypes.h"
 #include "cmSystemTools.h"
@@ -108,13 +108,13 @@ static cmsys::RegularExpression TransformCompile(const std::string& str)
 }
 
 cmRuntimeDependencyArchive::cmRuntimeDependencyArchive(
-  cmCommand* command, std::vector<std::string> searchDirectories,
+  cmExecutionStatus& status, std::vector<std::string> searchDirectories,
   std::string bundleExecutable,
   const std::vector<std::string>& preIncludeRegexes,
   const std::vector<std::string>& preExcludeRegexes,
   const std::vector<std::string>& postIncludeRegexes,
   const std::vector<std::string>& postExcludeRegexes)
-  : Command(command)
+  : Status(status)
   , SearchDirectories(std::move(searchDirectories))
   , BundleExecutable(std::move(bundleExecutable))
   , PreIncludeRegexes(preIncludeRegexes.size())
@@ -190,7 +190,7 @@ bool cmRuntimeDependencyArchive::GetRuntimeDependencies(
 
 void cmRuntimeDependencyArchive::SetError(const std::string& e)
 {
-  this->Command->SetError(e);
+  this->Status.SetError(e);
 }
 
 std::string cmRuntimeDependencyArchive::GetBundleExecutable()
@@ -361,7 +361,7 @@ void cmRuntimeDependencyArchive::AddUnresolvedPath(const std::string& name)
 
 cmMakefile* cmRuntimeDependencyArchive::GetMakefile()
 {
-  return this->Command->GetMakefile();
+  return &this->Status.GetMakefile();
 }
 
 const std::map<std::string, std::set<std::string>>&

+ 3 - 3
Source/cmRuntimeDependencyArchive.h

@@ -14,14 +14,14 @@
 #include <string>
 #include <vector>
 
-class cmCommand;
+class cmExecutionStatus;
 class cmMakefile;
 
 class cmRuntimeDependencyArchive
 {
 public:
   explicit cmRuntimeDependencyArchive(
-    cmCommand* command, std::vector<std::string> searchDirectories,
+    cmExecutionStatus& status, std::vector<std::string> searchDirectories,
     std::string bundleExecutable,
     const std::vector<std::string>& preIncludeRegexes,
     const std::vector<std::string>& preExcludeRegexes,
@@ -51,7 +51,7 @@ public:
   const std::set<std::string>& GetUnresolvedPaths();
 
 private:
-  cmCommand* Command;
+  cmExecutionStatus& Status;
   std::unique_ptr<cmBinUtilsLinker> Linker;
 
   std::string GetRuntimeDependenciesTool;

+ 31 - 0
Source/cmSubcommandTable.cxx

@@ -0,0 +1,31 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmSubcommandTable.h"
+
+#include <algorithm>
+
+#include "cmExecutionStatus.h"
+#include "cmStringAlgorithms.h"
+
+cmSubcommandTable::cmSubcommandTable(std::initializer_list<InitElem> init)
+  : Impl(init.begin(), init.end())
+{
+  std::sort(this->Impl.begin(), this->Impl.end(),
+            [](Elem const& left, Elem const& right) {
+              return left.first < right.first;
+            });
+}
+
+bool cmSubcommandTable::operator()(cm::string_view key,
+                                   std::vector<std::string> const& args,
+                                   cmExecutionStatus& status) const
+{
+  auto const it = std::lower_bound(
+    this->Impl.begin(), this->Impl.end(), key,
+    [](Elem const& elem, cm::string_view k) { return elem.first < k; });
+  if (it != this->Impl.end() && it->first == key) {
+    return it->second(args, status);
+  }
+  status.SetError(cmStrCat("does not recognize sub-command ", key));
+  return false;
+}

+ 36 - 0
Source/cmSubcommandTable.h

@@ -0,0 +1,36 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cmSubcommandTable_h
+#define cmSubcommandTable_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cm_static_string_view.hxx"
+#include "cm_string_view.hxx"
+
+#include <initializer_list>
+#include <string>
+#include <utility>
+#include <vector>
+
+class cmExecutionStatus;
+
+class cmSubcommandTable
+{
+public:
+  using Command = bool (*)(std::vector<std::string> const&,
+                           cmExecutionStatus&);
+
+  using Elem = std::pair<cm::string_view, Command>;
+  using InitElem = std::pair<cm::static_string_view, Command>;
+
+  cmSubcommandTable(std::initializer_list<InitElem> init);
+
+  bool operator()(cm::string_view key, std::vector<std::string> const& args,
+                  cmExecutionStatus& status) const;
+
+private:
+  std::vector<Elem> Impl;
+};
+
+#endif

+ 1 - 0
bootstrap

@@ -426,6 +426,7 @@ CMAKE_CXX_SOURCES="\
   cmStringAlgorithms \
   cmStringReplaceHelper \
   cmStringCommand \
+  cmSubcommandTable \
   cmSubdirCommand \
   cmSystemTools \
   cmTarget \

Some files were not shown because too many files changed in this diff