瀏覽代碼

Merge topic 'file-copy-relative-from'

99b90dbf file: Add COPY/INSTALL option for fixed layout relative to a directory
dadf1570 file: Refactor COPY/INSTALL relative path handling

Acked-by: Kitware Robot <[email protected]>
Merge-request: !703
Brad King 8 年之前
父節點
當前提交
c003f1b996

+ 51 - 10
Source/cmFileCommand.cxx

@@ -1147,6 +1147,7 @@ protected:
   bool UseGivenPermissionsDir;
   bool UseSourcePermissions;
   std::string Destination;
+  std::string FilesFromDir;
   std::vector<std::string> Files;
   int Doing;
 
@@ -1156,6 +1157,7 @@ protected:
     DoingNone,
     DoingError,
     DoingDestination,
+    DoingFilesFromDir,
     DoingFiles,
     DoingPattern,
     DoingRegex,
@@ -1251,6 +1253,12 @@ bool cmFileCopier::CheckKeyword(std::string const& arg)
     } else {
       this->Doing = DoingDestination;
     }
+  } else if (arg == "FILES_FROM_DIR") {
+    if (this->CurrentMatchRule) {
+      this->NotAfterMatch(arg);
+    } else {
+      this->Doing = DoingFilesFromDir;
+    }
   } else if (arg == "PATTERN") {
     this->Doing = DoingPattern;
   } else if (arg == "REGEX") {
@@ -1314,13 +1322,7 @@ bool cmFileCopier::CheckValue(std::string const& arg)
 {
   switch (this->Doing) {
     case DoingFiles:
-      if (arg.empty() || cmSystemTools::FileIsFullPath(arg.c_str())) {
-        this->Files.push_back(arg);
-      } else {
-        std::string file = this->Makefile->GetCurrentSourceDirectory();
-        file += "/" + arg;
-        this->Files.push_back(file);
-      }
+      this->Files.push_back(arg);
       break;
     case DoingDestination:
       if (arg.empty() || cmSystemTools::FileIsFullPath(arg.c_str())) {
@@ -1331,6 +1333,16 @@ bool cmFileCopier::CheckValue(std::string const& arg)
       }
       this->Doing = DoingNone;
       break;
+    case DoingFilesFromDir:
+      if (cmSystemTools::FileIsFullPath(arg.c_str())) {
+        this->FilesFromDir = arg;
+      } else {
+        this->FilesFromDir = this->Makefile->GetCurrentSourceDirectory();
+        this->FilesFromDir += "/" + arg;
+      }
+      cmSystemTools::ConvertToUnixSlashes(this->FilesFromDir);
+      this->Doing = DoingNone;
+      break;
     case DoingPattern: {
       // Convert the pattern to a regular expression.  Require a
       // leading slash and trailing end-of-string in the matched
@@ -1390,17 +1402,41 @@ bool cmFileCopier::Run(std::vector<std::string> const& args)
     return false;
   }
 
-  std::vector<std::string> const& files = this->Files;
-  for (std::vector<std::string>::size_type i = 0; i < files.size(); ++i) {
+  for (std::vector<std::string>::const_iterator i = this->Files.begin();
+       i != this->Files.end(); ++i) {
+    std::string file;
+    if (!i->empty() && !cmSystemTools::FileIsFullPath(*i)) {
+      if (!this->FilesFromDir.empty()) {
+        file = this->FilesFromDir;
+      } else {
+        file = this->Makefile->GetCurrentSourceDirectory();
+      }
+      file += "/";
+      file += *i;
+    } else if (!this->FilesFromDir.empty()) {
+      this->FileCommand->SetError("option FILES_FROM_DIR requires all files "
+                                  "to be specified as relative paths.");
+      return false;
+    } else {
+      file = *i;
+    }
+
     // Split the input file into its directory and name components.
     std::vector<std::string> fromPathComponents;
-    cmSystemTools::SplitPath(files[i], fromPathComponents);
+    cmSystemTools::SplitPath(file, fromPathComponents);
     std::string fromName = *(fromPathComponents.end() - 1);
     std::string fromDir = cmSystemTools::JoinPath(
       fromPathComponents.begin(), fromPathComponents.end() - 1);
 
     // Compute the full path to the destination file.
     std::string toFile = this->Destination;
+    if (!this->FilesFromDir.empty()) {
+      std::string dir = cmSystemTools::GetFilenamePath(*i);
+      if (!dir.empty()) {
+        toFile += "/";
+        toFile += dir;
+      }
+    }
     std::string const& toName = this->ToName(fromName);
     if (!toName.empty()) {
       toFile += "/";
@@ -1751,6 +1787,11 @@ 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.");
+      return false;
+    }
     if (this->InstallType != cmInstallType_FILES &&
         this->InstallType != cmInstallType_PROGRAMS) {
       this->FileCommand->SetError("INSTALL option RENAME may be used "

+ 1 - 0
Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad-result.txt

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

+ 15 - 0
Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad-stderr.txt

@@ -0,0 +1,15 @@
+^CMake Error at INSTALL-FILES_FROM_DIR-bad.cmake:[0-9]+ \(file\):
+  file option FILES_FROM_DIR requires all files to be specified as relative
+  paths\.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)
++
+CMake Error at INSTALL-FILES_FROM_DIR-bad.cmake:[0-9]+ \(file\):
+  file INSTALL option RENAME may not be combined with FILES_FROM_DIR\.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)
++
+CMake Error at INSTALL-FILES_FROM_DIR-bad.cmake:[0-9]+ \(file\):
+  file option FILES_FROM_DIR may not appear after PATTERN or REGEX\.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)$

+ 5 - 0
Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad.cmake

@@ -0,0 +1,5 @@
+set(src ${CMAKE_CURRENT_SOURCE_DIR}/from)
+set(dst ${CMAKE_CURRENT_BINARY_DIR}/from)
+file(INSTALL FILES ${src}/a.txt FILES_FROM_DIR ${src} DESTINATION ${dst})
+file(INSTALL FILES a.txt FILES_FROM_DIR ${src} DESTINATION ${dst} RENAME b.txt)
+file(INSTALL FILES a.txt DESTINATION ${dst} PATTERN *.txt FILES_FROM_DIR)

+ 8 - 0
Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-stdout.txt

@@ -0,0 +1,8 @@
+-- Before Installing
+-- Installing: .*/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-build/from/a.txt
+-- Installing: .*/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-build/from/a/b.txt
+-- Installing: .*/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-build/from/a/b/c.txt
+-- Up-to-date: .*/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-build/from/a.txt
+-- Up-to-date: .*/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-build/from/a/b.txt
+-- Up-to-date: .*/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-build/from/a/b/c.txt
+-- After Installing

+ 7 - 0
Tests/RunCMake/file/INSTALL-FILES_FROM_DIR.cmake

@@ -0,0 +1,7 @@
+set(src ${CMAKE_CURRENT_SOURCE_DIR}/from)
+set(dst ${CMAKE_CURRENT_BINARY_DIR}/from)
+file(REMOVE RECURSE ${dst})
+message(STATUS "Before Installing")
+file(INSTALL FILES a.txt a/b.txt a/b/c.txt FILES_FROM_DIR ${src} DESTINATION ${dst})
+file(INSTALL FILES a.txt a/b.txt a/b/c.txt FILES_FROM_DIR from DESTINATION ${dst})
+message(STATUS "After Installing")

+ 2 - 0
Tests/RunCMake/file/RunCMakeTest.cmake

@@ -8,6 +8,8 @@ run_cmake(UPLOAD-unused-argument)
 run_cmake(UPLOAD-httpheader-not-set)
 run_cmake(UPLOAD-pass-not-set)
 run_cmake(INSTALL-DIRECTORY)
+run_cmake(INSTALL-FILES_FROM_DIR)
+run_cmake(INSTALL-FILES_FROM_DIR-bad)
 run_cmake(INSTALL-MESSAGE-bad)
 run_cmake(FileOpenFailRead)
 run_cmake(LOCK)

+ 0 - 0
Tests/RunCMake/file/from/a.txt


+ 0 - 0
Tests/RunCMake/file/from/a/b.txt


+ 0 - 0
Tests/RunCMake/file/from/a/b/c.txt