| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 | 
							- /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
 
-    file Copyright.txt or https://cmake.org/licensing for details.  */
 
- #include "cmSourceGroupCommand.h"
 
- #include <set>
 
- #include <stddef.h>
 
- #include <utility>
 
- #include "cmAlgorithms.h"
 
- #include "cmMakefile.h"
 
- #include "cmSourceGroup.h"
 
- #include "cmStringAlgorithms.h"
 
- #include "cmSystemTools.h"
 
- namespace {
 
- const std::string kTreeOptionName = "TREE";
 
- const std::string kPrefixOptionName = "PREFIX";
 
- const std::string kFilesOptionName = "FILES";
 
- const std::string kRegexOptionName = "REGULAR_EXPRESSION";
 
- const std::string kSourceGroupOptionName = "<sg_name>";
 
- std::vector<std::string> tokenizePath(const std::string& path)
 
- {
 
-   return cmTokenize(path, "\\/");
 
- }
 
- std::string getFullFilePath(const std::string& currentPath,
 
-                             const std::string& path)
 
- {
 
-   std::string fullPath = path;
 
-   if (!cmSystemTools::FileIsFullPath(path)) {
 
-     fullPath = currentPath;
 
-     fullPath += "/";
 
-     fullPath += path;
 
-   }
 
-   return cmSystemTools::CollapseFullPath(fullPath);
 
- }
 
- std::set<std::string> getSourceGroupFilesPaths(
 
-   const std::string& root, const std::vector<std::string>& files)
 
- {
 
-   std::set<std::string> ret;
 
-   const std::string::size_type rootLength = root.length();
 
-   for (std::string const& file : files) {
 
-     ret.insert(file.substr(rootLength + 1)); // +1 to also omnit last '/'
 
-   }
 
-   return ret;
 
- }
 
- bool rootIsPrefix(const std::string& root,
 
-                   const std::vector<std::string>& files, std::string& error)
 
- {
 
-   for (std::string const& file : files) {
 
-     if (!cmHasPrefix(file, root)) {
 
-       error = cmStrCat("ROOT: ", root, " is not a prefix of file: ", file);
 
-       return false;
 
-     }
 
-   }
 
-   return true;
 
- }
 
- std::vector<std::string> prepareFilesPathsForTree(
 
-   const std::vector<std::string>& filesPaths,
 
-   const std::string& currentSourceDir)
 
- {
 
-   std::vector<std::string> prepared;
 
-   prepared.reserve(filesPaths.size());
 
-   for (auto const& filePath : filesPaths) {
 
-     std::string fullPath =
 
-       cmSystemTools::CollapseFullPath(filePath, currentSourceDir);
 
-     // If provided file path is actually not a file, silently ignore it.
 
-     if (cmSystemTools::FileExists(fullPath, /*isFile=*/true)) {
 
-       prepared.emplace_back(std::move(fullPath));
 
-     }
 
-   }
 
-   return prepared;
 
- }
 
- bool addFilesToItsSourceGroups(const std::string& root,
 
-                                const std::set<std::string>& sgFilesPaths,
 
-                                const std::string& prefix, cmMakefile& makefile,
 
-                                std::string& errorMsg)
 
- {
 
-   cmSourceGroup* sg;
 
-   for (std::string const& sgFilesPath : sgFilesPaths) {
 
-     std::vector<std::string> tokenizedPath;
 
-     if (!prefix.empty()) {
 
-       tokenizedPath = tokenizePath(cmStrCat(prefix, '/', sgFilesPath));
 
-     } else {
 
-       tokenizedPath = tokenizePath(sgFilesPath);
 
-     }
 
-     if (!tokenizedPath.empty()) {
 
-       tokenizedPath.pop_back();
 
-       if (tokenizedPath.empty()) {
 
-         tokenizedPath.emplace_back();
 
-       }
 
-       sg = makefile.GetOrCreateSourceGroup(tokenizedPath);
 
-       if (!sg) {
 
-         errorMsg = "Could not create source group for file: " + sgFilesPath;
 
-         return false;
 
-       }
 
-       const std::string fullPath = getFullFilePath(root, sgFilesPath);
 
-       sg->AddGroupFile(fullPath);
 
-     }
 
-   }
 
-   return true;
 
- }
 
- }
 
- class cmExecutionStatus;
 
- // cmSourceGroupCommand
 
- cmSourceGroupCommand::ExpectedOptions
 
- cmSourceGroupCommand::getExpectedOptions() const
 
- {
 
-   ExpectedOptions options;
 
-   options.push_back(kTreeOptionName);
 
-   options.push_back(kPrefixOptionName);
 
-   options.push_back(kFilesOptionName);
 
-   options.push_back(kRegexOptionName);
 
-   return options;
 
- }
 
- bool cmSourceGroupCommand::isExpectedOption(
 
-   const std::string& argument, const ExpectedOptions& expectedOptions)
 
- {
 
-   return cmContains(expectedOptions, argument);
 
- }
 
- void cmSourceGroupCommand::parseArguments(
 
-   const std::vector<std::string>& args,
 
-   cmSourceGroupCommand::ParsedArguments& parsedArguments)
 
- {
 
-   const ExpectedOptions expectedOptions = getExpectedOptions();
 
-   size_t i = 0;
 
-   // at this point we know that args vector is not empty
 
-   // if first argument is not one of expected options it's source group name
 
-   if (!isExpectedOption(args[0], expectedOptions)) {
 
-     // get source group name and go to next argument
 
-     parsedArguments[kSourceGroupOptionName].push_back(args[0]);
 
-     ++i;
 
-   }
 
-   for (; i < args.size();) {
 
-     // get current option and increment index to go to next argument
 
-     const std::string& currentOption = args[i++];
 
-     // create current option entry in parsed arguments
 
-     std::vector<std::string>& currentOptionArguments =
 
-       parsedArguments[currentOption];
 
-     // collect option arguments while we won't find another expected option
 
-     while (i < args.size() && !isExpectedOption(args[i], expectedOptions)) {
 
-       currentOptionArguments.push_back(args[i++]);
 
-     }
 
-   }
 
- }
 
- bool cmSourceGroupCommand::InitialPass(std::vector<std::string> const& args,
 
-                                        cmExecutionStatus&)
 
- {
 
-   if (args.empty()) {
 
-     this->SetError("called with incorrect number of arguments");
 
-     return false;
 
-   }
 
-   // If only two arguments are given, the pre-1.8 version of the
 
-   // command is being invoked.
 
-   if (args.size() == 2 && args[1] != "FILES") {
 
-     cmSourceGroup* sg = this->Makefile->GetOrCreateSourceGroup(args[0]);
 
-     if (!sg) {
 
-       this->SetError("Could not create or find source group");
 
-       return false;
 
-     }
 
-     sg->SetGroupRegex(args[1].c_str());
 
-     return true;
 
-   }
 
-   ParsedArguments parsedArguments;
 
-   std::string errorMsg;
 
-   parseArguments(args, parsedArguments);
 
-   if (!checkArgumentsPreconditions(parsedArguments, errorMsg)) {
 
-     return false;
 
-   }
 
-   if (parsedArguments.find(kTreeOptionName) != parsedArguments.end()) {
 
-     if (!processTree(parsedArguments, errorMsg)) {
 
-       this->SetError(errorMsg);
 
-       return false;
 
-     }
 
-   } else {
 
-     if (parsedArguments.find(kSourceGroupOptionName) ==
 
-         parsedArguments.end()) {
 
-       this->SetError("Missing source group name.");
 
-       return false;
 
-     }
 
-     cmSourceGroup* sg = this->Makefile->GetOrCreateSourceGroup(args[0]);
 
-     if (!sg) {
 
-       this->SetError("Could not create or find source group");
 
-       return false;
 
-     }
 
-     // handle regex
 
-     if (parsedArguments.find(kRegexOptionName) != parsedArguments.end()) {
 
-       const std::string& sgRegex = parsedArguments[kRegexOptionName].front();
 
-       sg->SetGroupRegex(sgRegex.c_str());
 
-     }
 
-     // handle files
 
-     const std::vector<std::string>& filesArguments =
 
-       parsedArguments[kFilesOptionName];
 
-     for (auto const& filesArg : filesArguments) {
 
-       std::string src = filesArg;
 
-       if (!cmSystemTools::FileIsFullPath(src)) {
 
-         src = this->Makefile->GetCurrentSourceDirectory();
 
-         src += "/";
 
-         src += filesArg;
 
-       }
 
-       src = cmSystemTools::CollapseFullPath(src);
 
-       sg->AddGroupFile(src);
 
-     }
 
-   }
 
-   return true;
 
- }
 
- bool cmSourceGroupCommand::checkArgumentsPreconditions(
 
-   const ParsedArguments& parsedArguments, std::string& errorMsg) const
 
- {
 
-   return checkSingleParameterArgumentPreconditions(
 
-            kPrefixOptionName, parsedArguments, errorMsg) &&
 
-     checkSingleParameterArgumentPreconditions(kTreeOptionName, parsedArguments,
 
-                                               errorMsg) &&
 
-     checkSingleParameterArgumentPreconditions(kRegexOptionName,
 
-                                               parsedArguments, errorMsg);
 
- }
 
- bool cmSourceGroupCommand::processTree(ParsedArguments& parsedArguments,
 
-                                        std::string& errorMsg)
 
- {
 
-   const std::string root =
 
-     cmSystemTools::CollapseFullPath(parsedArguments[kTreeOptionName].front());
 
-   std::string prefix = parsedArguments[kPrefixOptionName].empty()
 
-     ? ""
 
-     : parsedArguments[kPrefixOptionName].front();
 
-   const std::vector<std::string> filesVector =
 
-     prepareFilesPathsForTree(parsedArguments[kFilesOptionName],
 
-                              this->Makefile->GetCurrentSourceDirectory());
 
-   if (!rootIsPrefix(root, filesVector, errorMsg)) {
 
-     return false;
 
-   }
 
-   std::set<std::string> sourceGroupPaths =
 
-     getSourceGroupFilesPaths(root, filesVector);
 
-   return addFilesToItsSourceGroups(root, sourceGroupPaths, prefix,
 
-                                    *(this->Makefile), errorMsg);
 
- }
 
- bool cmSourceGroupCommand::checkSingleParameterArgumentPreconditions(
 
-   const std::string& argument, const ParsedArguments& parsedArguments,
 
-   std::string& errorMsg) const
 
- {
 
-   ParsedArguments::const_iterator foundArgument =
 
-     parsedArguments.find(argument);
 
-   if (foundArgument != parsedArguments.end()) {
 
-     const std::vector<std::string>& optionArguments = foundArgument->second;
 
-     if (optionArguments.empty()) {
 
-       errorMsg = argument + " argument given without an argument.";
 
-       return false;
 
-     }
 
-     if (optionArguments.size() > 1) {
 
-       errorMsg = "too many arguments passed to " + argument + ".";
 
-       return false;
 
-     }
 
-   }
 
-   return true;
 
- }
 
 
  |