/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include "cmCPackGenerator.h"

#include <algorithm>
#include <cstring>
#include <memory>
#include <utility>

#include "cmsys/FStream.hxx"
#include "cmsys/Glob.hxx"
#include "cmsys/RegularExpression.hxx"

#include "cmCPackComponentGroup.h"
#include "cmCPackLog.h"
#include "cmCryptoHash.h"
#include "cmDuration.h"
#include "cmFSPermissions.h"
#include "cmFileTimes.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmState.h"
#include "cmStateSnapshot.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmVersion.h"
#include "cmWorkingDirectory.h"
#include "cmXMLSafe.h"
#include "cmake.h"

#if defined(__HAIKU__)
#  include <FindDirectory.h>
#  include <StorageDefs.h>
#endif

cmCPackGenerator::cmCPackGenerator()
{
  this->GeneratorVerbose = cmSystemTools::OUTPUT_NONE;
  this->MakefileMap = nullptr;
  this->Logger = nullptr;
  this->componentPackageMethod = ONE_PACKAGE_PER_GROUP;
}

cmCPackGenerator::~cmCPackGenerator()
{
  this->MakefileMap = nullptr;
}

void cmCPackGenerator::DisplayVerboseOutput(const std::string& msg,
                                            float progress)
{
  (void)progress;
  cmCPackLogger(cmCPackLog::LOG_VERBOSE, "" << msg << std::endl);
}

int cmCPackGenerator::PrepareNames()
{
  cmCPackLogger(cmCPackLog::LOG_DEBUG, "Create temp directory." << std::endl);

  // checks CPACK_SET_DESTDIR support
  if (IsOn("CPACK_SET_DESTDIR")) {
    if (SETDESTDIR_UNSUPPORTED == SupportsSetDestdir()) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "CPACK_SET_DESTDIR is set to ON but the '"
                      << Name << "' generator does NOT support it."
                      << std::endl);
      return 0;
    }
    if (SETDESTDIR_SHOULD_NOT_BE_USED == SupportsSetDestdir()) {
      cmCPackLogger(cmCPackLog::LOG_WARNING,
                    "CPACK_SET_DESTDIR is set to ON but it is "
                      << "usually a bad idea to do that with '" << Name
                      << "' generator. Use at your own risk." << std::endl);
    }
  }

  std::string tempDirectory =
    cmStrCat(this->GetOption("CPACK_PACKAGE_DIRECTORY"), "/_CPack_Packages/");
  const char* toplevelTag = this->GetOption("CPACK_TOPLEVEL_TAG");
  if (toplevelTag) {
    tempDirectory += toplevelTag;
    tempDirectory += "/";
  }
  tempDirectory += this->GetOption("CPACK_GENERATOR");
  std::string topDirectory = tempDirectory;
  const char* pfname = this->GetOption("CPACK_PACKAGE_FILE_NAME");
  if (!pfname) {
    cmCPackLogger(cmCPackLog::LOG_ERROR,
                  "CPACK_PACKAGE_FILE_NAME not specified" << std::endl);
    return 0;
  }
  std::string outName = pfname;
  tempDirectory += "/" + outName;
  if (!this->GetOutputExtension()) {
    cmCPackLogger(cmCPackLog::LOG_ERROR,
                  "No output extension specified" << std::endl);
    return 0;
  }
  outName += this->GetOutputExtension();
  const char* pdir = this->GetOption("CPACK_PACKAGE_DIRECTORY");
  if (!pdir) {
    cmCPackLogger(cmCPackLog::LOG_ERROR,
                  "CPACK_PACKAGE_DIRECTORY not specified" << std::endl);
    return 0;
  }

  std::string destFile = pdir;
  this->SetOptionIfNotSet("CPACK_OUTPUT_FILE_PREFIX", destFile.c_str());
  destFile += "/" + outName;
  std::string outFile = topDirectory + "/" + outName;
  this->SetOptionIfNotSet("CPACK_TOPLEVEL_DIRECTORY", topDirectory.c_str());
  this->SetOptionIfNotSet("CPACK_TEMPORARY_DIRECTORY", tempDirectory.c_str());
  this->SetOptionIfNotSet("CPACK_OUTPUT_FILE_NAME", outName.c_str());
  this->SetOptionIfNotSet("CPACK_OUTPUT_FILE_PATH", destFile.c_str());
  this->SetOptionIfNotSet("CPACK_TEMPORARY_PACKAGE_FILE_NAME",
                          outFile.c_str());
  this->SetOptionIfNotSet("CPACK_INSTALL_DIRECTORY", this->GetInstallPath());
  this->SetOptionIfNotSet(
    "CPACK_NATIVE_INSTALL_DIRECTORY",
    cmsys::SystemTools::ConvertToOutputPath(this->GetInstallPath()).c_str());
  this->SetOptionIfNotSet("CPACK_TEMPORARY_INSTALL_DIRECTORY",
                          tempDirectory.c_str());

  cmCPackLogger(cmCPackLog::LOG_DEBUG,
                "Look for: CPACK_PACKAGE_DESCRIPTION_FILE" << std::endl);
  const char* descFileName = this->GetOption("CPACK_PACKAGE_DESCRIPTION_FILE");
  if (descFileName && !this->GetOption("CPACK_PACKAGE_DESCRIPTION")) {
    cmCPackLogger(cmCPackLog::LOG_DEBUG,
                  "Look for: " << descFileName << std::endl);
    if (!cmSystemTools::FileExists(descFileName)) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "Cannot find description file name: ["
                      << descFileName << "]" << std::endl);
      return 0;
    }
    cmsys::ifstream ifs(descFileName);
    if (!ifs) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "Cannot open description file name: " << descFileName
                                                          << std::endl);
      return 0;
    }
    std::ostringstream ostr;
    std::string line;

    cmCPackLogger(cmCPackLog::LOG_VERBOSE,
                  "Read description file: " << descFileName << std::endl);
    while (ifs && cmSystemTools::GetLineFromStream(ifs, line)) {
      ostr << cmXMLSafe(line) << std::endl;
    }
    this->SetOption("CPACK_PACKAGE_DESCRIPTION", ostr.str().c_str());
    const char* defFileName =
      this->GetOption("CPACK_DEFAULT_PACKAGE_DESCRIPTION_FILE");
    if (defFileName && !strcmp(defFileName, descFileName)) {
      this->SetOption("CPACK_USED_DEFAULT_PACKAGE_DESCRIPTION_FILE", "ON");
    }
  }
  if (!this->GetOption("CPACK_PACKAGE_DESCRIPTION")) {
    cmCPackLogger(
      cmCPackLog::LOG_ERROR,
      "Project description not specified. Please specify "
      "CPACK_PACKAGE_DESCRIPTION or CPACK_PACKAGE_DESCRIPTION_FILE."
        << std::endl);
    return 0;
  }
  const char* algoSignature = this->GetOption("CPACK_PACKAGE_CHECKSUM");
  if (algoSignature) {
    if (!cmCryptoHash::New(algoSignature)) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "Cannot recognize algorithm: " << algoSignature
                                                   << std::endl);
      return 0;
    }
  }

  this->SetOptionIfNotSet("CPACK_REMOVE_TOPLEVEL_DIRECTORY", "1");

  return 1;
}

int cmCPackGenerator::InstallProject()
{
  cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Install projects" << std::endl);
  this->CleanTemporaryDirectory();

  std::string bareTempInstallDirectory =
    this->GetOption("CPACK_TEMPORARY_INSTALL_DIRECTORY");
  std::string tempInstallDirectoryStr = bareTempInstallDirectory;
  bool setDestDir = cmIsOn(this->GetOption("CPACK_SET_DESTDIR")) |
    cmIsInternallyOn(this->GetOption("CPACK_SET_DESTDIR"));
  if (!setDestDir) {
    tempInstallDirectoryStr += this->GetPackagingInstallPrefix();
  }

  const char* tempInstallDirectory = tempInstallDirectoryStr.c_str();
  int res = 1;
  if (!cmsys::SystemTools::MakeDirectory(bareTempInstallDirectory)) {
    cmCPackLogger(cmCPackLog::LOG_ERROR,
                  "Problem creating temporary directory: "
                    << (tempInstallDirectory ? tempInstallDirectory : "(NULL)")
                    << std::endl);
    return 0;
  }

  if (setDestDir) {
    std::string destDir = cmStrCat("DESTDIR=", tempInstallDirectory);
    cmSystemTools::PutEnv(destDir);
  } else {
    // Make sure there is no destdir
    cmSystemTools::PutEnv("DESTDIR=");
  }

  // prepare default created directory permissions
  mode_t default_dir_mode_v = 0;
  mode_t* default_dir_mode = nullptr;
  const char* default_dir_install_permissions =
    this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
  if (default_dir_install_permissions && *default_dir_install_permissions) {
    std::vector<std::string> items =
      cmExpandedList(default_dir_install_permissions);
    for (const auto& arg : items) {
      if (!cmFSPermissions::stringToModeT(arg, default_dir_mode_v)) {
        cmCPackLogger(cmCPackLog::LOG_ERROR,
                      "Invalid permission value '"
                        << arg
                        << "'."
                           " CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS "
                           "value is invalid."
                        << std::endl);
        return 0;
      }
    }

    default_dir_mode = &default_dir_mode_v;
  }

  // If the CPackConfig file sets CPACK_INSTALL_COMMANDS then run them
  // as listed
  if (!this->InstallProjectViaInstallCommands(setDestDir,
                                              tempInstallDirectory)) {
    return 0;
  }

  // If the CPackConfig file sets CPACK_INSTALL_SCRIPT(S) then run them
  // as listed
  if (!this->InstallProjectViaInstallScript(setDestDir,
                                            tempInstallDirectory)) {
    return 0;
  }

  // If the CPackConfig file sets CPACK_INSTALLED_DIRECTORIES
  // then glob it and copy it to CPACK_TEMPORARY_DIRECTORY
  // This is used in Source packaging
  if (!this->InstallProjectViaInstalledDirectories(
        setDestDir, tempInstallDirectory, default_dir_mode)) {
    return 0;
  }

  // If the project is a CMAKE project then run pre-install
  // and then read the cmake_install script to run it
  if (!this->InstallProjectViaInstallCMakeProjects(
        setDestDir, bareTempInstallDirectory, default_dir_mode)) {
    return 0;
  }

  // Run pre-build actions
  const char* preBuildScripts = this->GetOption("CPACK_PRE_BUILD_SCRIPTS");
  if (preBuildScripts) {
    const auto scripts = cmExpandedList(preBuildScripts, false);
    for (const auto& script : scripts) {
      cmCPackLogger(cmCPackLog::LOG_OUTPUT,
                    "Executing pre-build script: " << script << std::endl);

      if (!this->MakefileMap->ReadListFile(script)) {
        cmCPackLogger(cmCPackLog::LOG_ERROR,
                      "The pre-build script not found: " << script
                                                         << std::endl);
        return 0;
      }
    }
  }

  if (setDestDir) {
    cmSystemTools::PutEnv("DESTDIR=");
  }

  return res;
}

int cmCPackGenerator::InstallProjectViaInstallCommands(
  bool setDestDir, const std::string& tempInstallDirectory)
{
  (void)setDestDir;
  const char* installCommands = this->GetOption("CPACK_INSTALL_COMMANDS");
  if (installCommands && *installCommands) {
    std::string tempInstallDirectoryEnv =
      cmStrCat("CMAKE_INSTALL_PREFIX=", tempInstallDirectory);
    cmSystemTools::PutEnv(tempInstallDirectoryEnv);
    std::vector<std::string> installCommandsVector =
      cmExpandedList(installCommands);
    for (std::string const& ic : installCommandsVector) {
      cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << ic << std::endl);
      std::string output;
      int retVal = 1;
      bool resB = cmSystemTools::RunSingleCommand(
        ic, &output, &output, &retVal, nullptr, this->GeneratorVerbose,
        cmDuration::zero());
      if (!resB || retVal) {
        std::string tmpFile = cmStrCat(
          this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/InstallOutput.log");
        cmGeneratedFileStream ofs(tmpFile);
        ofs << "# Run command: " << ic << std::endl
            << "# Output:" << std::endl
            << output << std::endl;
        cmCPackLogger(cmCPackLog::LOG_ERROR,
                      "Problem running install command: "
                        << ic << std::endl
                        << "Please check " << tmpFile << " for errors"
                        << std::endl);
        return 0;
      }
    }
  }
  return 1;
}

int cmCPackGenerator::InstallProjectViaInstalledDirectories(
  bool setDestDir, const std::string& tempInstallDirectory,
  const mode_t* default_dir_mode)
{
  (void)setDestDir;
  (void)tempInstallDirectory;
  std::vector<cmsys::RegularExpression> ignoreFilesRegex;
  const char* cpackIgnoreFiles = this->GetOption("CPACK_IGNORE_FILES");
  if (cpackIgnoreFiles) {
    std::vector<std::string> ignoreFilesRegexString =
      cmExpandedList(cpackIgnoreFiles);
    for (std::string const& ifr : ignoreFilesRegexString) {
      cmCPackLogger(cmCPackLog::LOG_VERBOSE,
                    "Create ignore files regex for: " << ifr << std::endl);
      ignoreFilesRegex.emplace_back(ifr);
    }
  }
  const char* installDirectories =
    this->GetOption("CPACK_INSTALLED_DIRECTORIES");
  if (installDirectories && *installDirectories) {
    std::vector<std::string> installDirectoriesVector =
      cmExpandedList(installDirectories);
    if (installDirectoriesVector.size() % 2 != 0) {
      cmCPackLogger(
        cmCPackLog::LOG_ERROR,
        "CPACK_INSTALLED_DIRECTORIES should contain pairs of <directory> "
        "and "
        "<subdirectory>. The <subdirectory> can be '.' to be installed in "
        "the toplevel directory of installation."
          << std::endl);
      return 0;
    }
    std::vector<std::string>::iterator it;
    const std::string& tempDir = tempInstallDirectory;
    for (it = installDirectoriesVector.begin();
         it != installDirectoriesVector.end(); ++it) {
      std::vector<std::pair<std::string, std::string>> symlinkedFiles;
      cmCPackLogger(cmCPackLog::LOG_DEBUG, "Find files" << std::endl);
      cmsys::Glob gl;
      std::string top = *it;
      it++;
      std::string subdir = *it;
      std::string findExpr = cmStrCat(top, "/*");
      cmCPackLogger(cmCPackLog::LOG_OUTPUT,
                    "- Install directory: " << top << std::endl);
      gl.RecurseOn();
      gl.SetRecurseListDirs(true);
      gl.SetRecurseThroughSymlinks(false);
      if (!gl.FindFiles(findExpr)) {
        cmCPackLogger(cmCPackLog::LOG_ERROR,
                      "Cannot find any files in the installed directory"
                        << std::endl);
        return 0;
      }
      files = gl.GetFiles();
      for (std::string const& gf : files) {
        bool skip = false;
        std::string inFile = gf;
        if (cmSystemTools::FileIsDirectory(gf)) {
          inFile += '/';
        }
        for (cmsys::RegularExpression& reg : ignoreFilesRegex) {
          if (reg.find(inFile)) {
            cmCPackLogger(cmCPackLog::LOG_VERBOSE,
                          "Ignore file: " << inFile << std::endl);
            skip = true;
          }
        }
        if (skip) {
          continue;
        }
        std::string filePath = cmStrCat(tempDir, '/', subdir, '/',
                                        cmSystemTools::RelativePath(top, gf));
        cmCPackLogger(cmCPackLog::LOG_DEBUG,
                      "Copy file: " << inFile << " -> " << filePath
                                    << std::endl);
        /* If the file is a symlink we will have to re-create it */
        if (cmSystemTools::FileIsSymlink(inFile)) {
          std::string targetFile;
          std::string inFileRelative =
            cmSystemTools::RelativePath(top, inFile);
          cmSystemTools::ReadSymlink(inFile, targetFile);
          symlinkedFiles.emplace_back(std::move(targetFile),
                                      std::move(inFileRelative));
        }
        /* If it is not a symlink then do a plain copy */
        else if (!(cmSystemTools::CopyFileIfDifferent(inFile, filePath) &&
                   cmFileTimes::Copy(inFile, filePath))) {
          cmCPackLogger(cmCPackLog::LOG_ERROR,
                        "Problem copying file: " << inFile << " -> "
                                                 << filePath << std::endl);
          return 0;
        }
      }
      /* rebuild symlinks in the installed tree */
      if (!symlinkedFiles.empty()) {
        std::string goToDir = cmStrCat(tempDir, '/', subdir);
        cmCPackLogger(cmCPackLog::LOG_DEBUG,
                      "Change dir to: " << goToDir << std::endl);
        cmWorkingDirectory workdir(goToDir);
        if (workdir.Failed()) {
          cmCPackLogger(cmCPackLog::LOG_ERROR,
                        "Failed to change working directory to "
                          << goToDir << " : "
                          << std::strerror(workdir.GetLastResult())
                          << std::endl);
          return 0;
        }
        for (auto const& symlinked : symlinkedFiles) {
          cmCPackLogger(cmCPackLog::LOG_DEBUG,
                        "Will create a symlink: " << symlinked.second << "--> "
                                                  << symlinked.first
                                                  << std::endl);
          // make sure directory exists for symlink
          std::string destDir =
            cmSystemTools::GetFilenamePath(symlinked.second);
          if (!destDir.empty() &&
              !cmSystemTools::MakeDirectory(destDir, default_dir_mode)) {
            cmCPackLogger(cmCPackLog::LOG_ERROR,
                          "Cannot create dir: "
                            << destDir << "\nTrying to create symlink: "
                            << symlinked.second << "--> " << symlinked.first
                            << std::endl);
          }
          if (!cmSystemTools::CreateSymlink(symlinked.first,
                                            symlinked.second)) {
            cmCPackLogger(cmCPackLog::LOG_ERROR,
                          "Cannot create symlink: "
                            << symlinked.second << "--> " << symlinked.first
                            << std::endl);
            return 0;
          }
        }
        cmCPackLogger(cmCPackLog::LOG_DEBUG,
                      "Going back to: " << workdir.GetOldDirectory()
                                        << std::endl);
      }
    }
  }
  return 1;
}

int cmCPackGenerator::InstallProjectViaInstallScript(
  bool setDestDir, const std::string& tempInstallDirectory)
{
  const char* cmakeScripts = this->GetOption("CPACK_INSTALL_SCRIPTS");
  {
    const char* const cmakeScript = this->GetOption("CPACK_INSTALL_SCRIPT");
    if (cmakeScript && cmakeScripts) {
      cmCPackLogger(
        cmCPackLog::LOG_WARNING,
        "Both CPACK_INSTALL_SCRIPTS and CPACK_INSTALL_SCRIPT are set, "
        "the latter will be ignored."
          << std::endl);
    } else if (cmakeScript && !cmakeScripts) {
      cmakeScripts = cmakeScript;
    }
  }
  if (cmakeScripts && *cmakeScripts) {
    cmCPackLogger(cmCPackLog::LOG_OUTPUT,
                  "- Install scripts: " << cmakeScripts << std::endl);
    std::vector<std::string> cmakeScriptsVector = cmExpandedList(cmakeScripts);
    for (std::string const& installScript : cmakeScriptsVector) {

      cmCPackLogger(cmCPackLog::LOG_OUTPUT,
                    "- Install script: " << installScript << std::endl);

      if (setDestDir) {
        // For DESTDIR based packaging, use the *project*
        // CMAKE_INSTALL_PREFIX underneath the tempInstallDirectory. The
        // value of the project's CMAKE_INSTALL_PREFIX is sent in here as the
        // value of the CPACK_INSTALL_PREFIX variable.

        std::string dir;
        if (this->GetOption("CPACK_INSTALL_PREFIX")) {
          dir += this->GetOption("CPACK_INSTALL_PREFIX");
        }
        this->SetOption("CMAKE_INSTALL_PREFIX", dir.c_str());
        cmCPackLogger(
          cmCPackLog::LOG_DEBUG,
          "- Using DESTDIR + CPACK_INSTALL_PREFIX... (this->SetOption)"
            << std::endl);
        cmCPackLogger(cmCPackLog::LOG_DEBUG,
                      "- Setting CMAKE_INSTALL_PREFIX to '" << dir << "'"
                                                            << std::endl);
      } else {
        this->SetOption("CMAKE_INSTALL_PREFIX", tempInstallDirectory.c_str());

        cmCPackLogger(cmCPackLog::LOG_DEBUG,
                      "- Using non-DESTDIR install... (this->SetOption)"
                        << std::endl);
        cmCPackLogger(cmCPackLog::LOG_DEBUG,
                      "- Setting CMAKE_INSTALL_PREFIX to '"
                        << tempInstallDirectory << "'" << std::endl);
      }

      this->SetOptionIfNotSet("CMAKE_CURRENT_BINARY_DIR",
                              tempInstallDirectory.c_str());
      this->SetOptionIfNotSet("CMAKE_CURRENT_SOURCE_DIR",
                              tempInstallDirectory.c_str());
      bool res = this->MakefileMap->ReadListFile(installScript);
      if (cmSystemTools::GetErrorOccuredFlag() || !res) {
        return 0;
      }
    }
  }
  return 1;
}

int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
  bool setDestDir, const std::string& baseTempInstallDirectory,
  const mode_t* default_dir_mode)
{
  const char* cmakeProjects = this->GetOption("CPACK_INSTALL_CMAKE_PROJECTS");
  const char* cmakeGenerator = this->GetOption("CPACK_CMAKE_GENERATOR");
  std::string absoluteDestFiles;
  if (cmakeProjects && *cmakeProjects) {
    if (!cmakeGenerator) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "CPACK_INSTALL_CMAKE_PROJECTS is specified, but "
                    "CPACK_CMAKE_GENERATOR is not. CPACK_CMAKE_GENERATOR "
                    "is required to install the project."
                      << std::endl);
      return 0;
    }
    std::vector<std::string> cmakeProjectsVector =
      cmExpandedList(cmakeProjects);
    std::vector<std::string>::iterator it;
    for (it = cmakeProjectsVector.begin(); it != cmakeProjectsVector.end();
         ++it) {
      if (it + 1 == cmakeProjectsVector.end() ||
          it + 2 == cmakeProjectsVector.end() ||
          it + 3 == cmakeProjectsVector.end()) {
        cmCPackLogger(
          cmCPackLog::LOG_ERROR,
          "Not enough items on list: CPACK_INSTALL_CMAKE_PROJECTS. "
          "CPACK_INSTALL_CMAKE_PROJECTS should hold quadruplet of install "
          "directory, install project name, install component, and install "
          "subdirectory."
            << std::endl);
        return 0;
      }
      std::string installDirectory = *it;
      ++it;
      std::string installProjectName = *it;
      ++it;
      cmCPackInstallCMakeProject project;

      project.Directory = installDirectory;
      project.ProjectName = installProjectName;
      project.Component = *it;
      ++it;
      project.SubDirectory = *it;

      std::vector<std::string> componentsVector;

      bool componentInstall = false;
      /*
       * We do a component install iff
       *    - the CPack generator support component
       *    - the user did not request Monolithic install
       *      (this works at CPack time too)
       */
      if (this->SupportsComponentInstallation() &&
          !(this->IsOn("CPACK_MONOLITHIC_INSTALL"))) {
        // Determine the installation types for this project (if provided).
        std::string installTypesVar = "CPACK_" +
          cmSystemTools::UpperCase(project.Component) + "_INSTALL_TYPES";
        const char* installTypes = this->GetOption(installTypesVar);
        if (installTypes && *installTypes) {
          std::vector<std::string> installTypesVector =
            cmExpandedList(installTypes);
          for (std::string const& installType : installTypesVector) {
            project.InstallationTypes.push_back(
              this->GetInstallationType(project.ProjectName, installType));
          }
        }

        // Determine the set of components that will be used in this project
        std::string componentsVar =
          "CPACK_COMPONENTS_" + cmSystemTools::UpperCase(project.Component);
        const char* components = this->GetOption(componentsVar);
        if (components && *components) {
          cmExpandList(components, componentsVector);
          for (std::string const& comp : componentsVector) {
            project.Components.push_back(
              this->GetComponent(project.ProjectName, comp));
          }
          componentInstall = true;
        }
      }
      if (componentsVector.empty()) {
        componentsVector.push_back(project.Component);
      }

      std::vector<std::string> buildConfigs;

      // Try get configuration names given via `-C` CLI option
      {
        const char* const buildConfigCstr =
          this->GetOption("CPACK_BUILD_CONFIG");
        auto buildConfig = buildConfigCstr ? buildConfigCstr : std::string{};
        cmExpandList(buildConfig, buildConfigs);
      }

      // Remove duplicates
      std::sort(buildConfigs.begin(), buildConfigs.end());
      buildConfigs.erase(std::unique(buildConfigs.begin(), buildConfigs.end()),
                         buildConfigs.end());

      // Ensure we have at least one configuration.
      if (buildConfigs.empty()) {
        buildConfigs.emplace_back();
      }

      std::unique_ptr<cmGlobalGenerator> globalGenerator =
        this->MakefileMap->GetCMakeInstance()->CreateGlobalGenerator(
          cmakeGenerator);
      if (!globalGenerator) {
        cmCPackLogger(cmCPackLog::LOG_ERROR,
                      "Specified package generator not found. "
                      "CPACK_CMAKE_GENERATOR value is invalid."
                        << std::endl);
        return 0;
      }
      // set the global flag for unix style paths on cmSystemTools as
      // soon as the generator is set.  This allows gmake to be used
      // on windows.
      cmSystemTools::SetForceUnixPaths(globalGenerator->GetForceUnixPaths());

      // Run the installation for the selected build configurations
      for (auto const& buildConfig : buildConfigs) {
        if (!this->RunPreinstallTarget(project.ProjectName, project.Directory,
                                       globalGenerator.get(), buildConfig)) {
          return 0;
        }

        cmCPackLogger(cmCPackLog::LOG_OUTPUT,
                      "- Install project: " << project.ProjectName << " ["
                                            << buildConfig << ']'
                                            << std::endl);
        // Run the installation for each component
        for (std::string const& component : componentsVector) {
          if (!this->InstallCMakeProject(
                setDestDir, project.Directory, baseTempInstallDirectory,
                default_dir_mode, component, componentInstall,
                project.SubDirectory, buildConfig, absoluteDestFiles)) {
            return 0;
          }
        }
      }

      this->CMakeProjects.emplace_back(std::move(project));
    }
  }
  this->SetOption("CPACK_ABSOLUTE_DESTINATION_FILES",
                  absoluteDestFiles.c_str());
  return 1;
}

int cmCPackGenerator::RunPreinstallTarget(
  const std::string& installProjectName, const std::string& installDirectory,
  cmGlobalGenerator* globalGenerator, const std::string& buildConfig)
{
  // Does this generator require pre-install?
  if (const char* preinstall = globalGenerator->GetPreinstallTargetName()) {
    std::string buildCommand = globalGenerator->GenerateCMakeBuildCommand(
      preinstall, buildConfig, "", false);
    cmCPackLogger(cmCPackLog::LOG_DEBUG,
                  "- Install command: " << buildCommand << std::endl);
    cmCPackLogger(cmCPackLog::LOG_OUTPUT,
                  "- Run preinstall target for: " << installProjectName
                                                  << std::endl);
    std::string output;
    int retVal = 1;
    bool resB = cmSystemTools::RunSingleCommand(
      buildCommand, &output, &output, &retVal, installDirectory.c_str(),
      this->GeneratorVerbose, cmDuration::zero());
    if (!resB || retVal) {
      std::string tmpFile = cmStrCat(
        this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/PreinstallOutput.log");
      cmGeneratedFileStream ofs(tmpFile);
      ofs << "# Run command: " << buildCommand << std::endl
          << "# Directory: " << installDirectory << std::endl
          << "# Output:" << std::endl
          << output << std::endl;
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "Problem running install command: "
                      << buildCommand << std::endl
                      << "Please check " << tmpFile << " for errors"
                      << std::endl);
      return 0;
    }
  }

  return 1;
}

int cmCPackGenerator::InstallCMakeProject(
  bool setDestDir, const std::string& installDirectory,
  const std::string& baseTempInstallDirectory, const mode_t* default_dir_mode,
  const std::string& component, bool componentInstall,
  const std::string& installSubDirectory, const std::string& buildConfig,
  std::string& absoluteDestFiles)
{
  std::string tempInstallDirectory = baseTempInstallDirectory;
  std::string installFile = installDirectory + "/cmake_install.cmake";

  if (componentInstall) {
    cmCPackLogger(cmCPackLog::LOG_OUTPUT,
                  "-   Install component: " << component << std::endl);
  }

  cmake cm(cmake::RoleScript, cmState::CPack);
  cm.SetHomeDirectory("");
  cm.SetHomeOutputDirectory("");
  cm.GetCurrentSnapshot().SetDefaultDefinitions();
  cm.AddCMakePaths();
  cm.SetProgressCallback([this](const std::string& msg, float prog) {
    this->DisplayVerboseOutput(msg, prog);
  });
  cm.SetTrace(this->Trace);
  cm.SetTraceExpand(this->TraceExpand);
  cmGlobalGenerator gg(&cm);
  cmMakefile mf(&gg, cm.GetCurrentSnapshot());
  if (!installSubDirectory.empty() && installSubDirectory != "/" &&
      installSubDirectory != ".") {
    tempInstallDirectory += installSubDirectory;
  }
  if (componentInstall) {
    tempInstallDirectory += "/";
    // Some CPack generators would rather chose
    // the local installation directory suffix.
    // Some (e.g. RPM) use
    //  one install directory for each component **GROUP**
    // instead of the default
    //  one install directory for each component.
    tempInstallDirectory += GetComponentInstallDirNameSuffix(component);
    if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) {
      tempInstallDirectory += "/";
      tempInstallDirectory += this->GetOption("CPACK_PACKAGE_FILE_NAME");
    }
  }

  const char* default_dir_inst_permissions =
    this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
  if (default_dir_inst_permissions && *default_dir_inst_permissions) {
    mf.AddDefinition("CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS",
                     default_dir_inst_permissions);
  }

  if (!setDestDir) {
    tempInstallDirectory += this->GetPackagingInstallPrefix();
  }

  if (setDestDir) {
    // For DESTDIR based packaging, use the *project*
    // CMAKE_INSTALL_PREFIX underneath the tempInstallDirectory. The
    // value of the project's CMAKE_INSTALL_PREFIX is sent in here as
    // the value of the CPACK_INSTALL_PREFIX variable.
    //
    // If DESTDIR has been 'internally set ON' this means that
    // the underlying CPack specific generator did ask for that
    // In this case we may override CPACK_INSTALL_PREFIX with
    // CPACK_PACKAGING_INSTALL_PREFIX
    // I know this is tricky and awkward but it's the price for
    // CPACK_SET_DESTDIR backward compatibility.
    if (cmIsInternallyOn(this->GetOption("CPACK_SET_DESTDIR"))) {
      this->SetOption("CPACK_INSTALL_PREFIX",
                      this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"));
    }
    std::string dir;
    if (this->GetOption("CPACK_INSTALL_PREFIX")) {
      dir += this->GetOption("CPACK_INSTALL_PREFIX");
    }
    mf.AddDefinition("CMAKE_INSTALL_PREFIX", dir);

    cmCPackLogger(
      cmCPackLog::LOG_DEBUG,
      "- Using DESTDIR + CPACK_INSTALL_PREFIX... (mf.AddDefinition)"
        << std::endl);
    cmCPackLogger(cmCPackLog::LOG_DEBUG,
                  "- Setting CMAKE_INSTALL_PREFIX to '" << dir << "'"
                                                        << std::endl);

    // Make sure that DESTDIR + CPACK_INSTALL_PREFIX directory
    // exists:
    //
    if (cmHasLiteralPrefix(dir, "/")) {
      dir = tempInstallDirectory + dir;
    } else {
      dir = tempInstallDirectory + "/" + dir;
    }
    /*
     *  We must re-set DESTDIR for each component
     *  We must not add the CPACK_INSTALL_PREFIX part because
     *  it will be added using the override of CMAKE_INSTALL_PREFIX
     *  The main reason for this awkward trick is that
     *  are using DESTDIR for 2 different reasons:
     *     - Because it was asked by the CPack Generator or the user
     *       using CPACK_SET_DESTDIR
     *     - Because it was already used for component install
     *       in order to put things in subdirs...
     */
    cmSystemTools::PutEnv(std::string("DESTDIR=") + tempInstallDirectory);
    cmCPackLogger(cmCPackLog::LOG_DEBUG,
                  "- Creating directory: '" << dir << "'" << std::endl);

    if (!cmsys::SystemTools::MakeDirectory(dir, default_dir_mode)) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "Problem creating temporary directory: " << dir
                                                             << std::endl);
      return 0;
    }
  } else {
    mf.AddDefinition("CMAKE_INSTALL_PREFIX", tempInstallDirectory);

    if (!cmsys::SystemTools::MakeDirectory(tempInstallDirectory,
                                           default_dir_mode)) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "Problem creating temporary directory: "
                      << tempInstallDirectory << std::endl);
      return 0;
    }

    cmCPackLogger(cmCPackLog::LOG_DEBUG,
                  "- Using non-DESTDIR install... (mf.AddDefinition)"
                    << std::endl);
    cmCPackLogger(cmCPackLog::LOG_DEBUG,
                  "- Setting CMAKE_INSTALL_PREFIX to '" << tempInstallDirectory
                                                        << "'" << std::endl);
  }

  if (!buildConfig.empty()) {
    mf.AddDefinition("BUILD_TYPE", buildConfig);
  }
  std::string installComponentLowerCase = cmSystemTools::LowerCase(component);
  if (installComponentLowerCase != "all") {
    mf.AddDefinition("CMAKE_INSTALL_COMPONENT", component);
  }

  // strip on TRUE, ON, 1, one or several file names, but not on
  // FALSE, OFF, 0 and an empty string
  if (!cmIsOff(this->GetOption("CPACK_STRIP_FILES"))) {
    mf.AddDefinition("CMAKE_INSTALL_DO_STRIP", "1");
  }
  // Remember the list of files before installation
  // of the current component (if we are in component install)
  std::string const& InstallPrefix = tempInstallDirectory;
  std::vector<std::string> filesBefore;
  std::string findExpr = tempInstallDirectory;
  if (componentInstall) {
    cmsys::Glob glB;
    findExpr += "/*";
    glB.RecurseOn();
    glB.SetRecurseListDirs(true);
    glB.SetRecurseThroughSymlinks(false);
    glB.FindFiles(findExpr);
    filesBefore = glB.GetFiles();
    std::sort(filesBefore.begin(), filesBefore.end());
  }

  // If CPack was asked to warn on ABSOLUTE INSTALL DESTINATION
  // then forward request to cmake_install.cmake script
  if (this->IsOn("CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION")) {
    mf.AddDefinition("CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION", "1");
  }
  // If current CPack generator does support
  // ABSOLUTE INSTALL DESTINATION or CPack has been asked for
  // then ask cmake_install.cmake script to error out
  // as soon as it occurs (before installing file)
  if (!SupportsAbsoluteDestination() ||
      this->IsOn("CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION")) {
    mf.AddDefinition("CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION", "1");
  }
  // do installation
  bool res = mf.ReadListFile(installFile);
  // forward definition of CMAKE_ABSOLUTE_DESTINATION_FILES
  // to CPack (may be used by generators like CPack RPM or DEB)
  // in order to transparently handle ABSOLUTE PATH
  if (const char* def = mf.GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES")) {
    mf.AddDefinition("CPACK_ABSOLUTE_DESTINATION_FILES", def);
  }

  // Now rebuild the list of files after installation
  // of the current component (if we are in component install)
  if (componentInstall) {
    cmsys::Glob glA;
    glA.RecurseOn();
    glA.SetRecurseListDirs(true);
    glA.SetRecurseThroughSymlinks(false);
    glA.FindFiles(findExpr);
    std::vector<std::string> filesAfter = glA.GetFiles();
    std::sort(filesAfter.begin(), filesAfter.end());
    std::vector<std::string>::iterator diff;
    std::vector<std::string> result(filesAfter.size());
    diff = std::set_difference(filesAfter.begin(), filesAfter.end(),
                               filesBefore.begin(), filesBefore.end(),
                               result.begin());

    std::vector<std::string>::iterator fit;
    std::string localFileName;
    // Populate the File field of each component
    for (fit = result.begin(); fit != diff; ++fit) {
      localFileName = cmSystemTools::RelativePath(InstallPrefix, *fit);
      localFileName =
        localFileName.substr(localFileName.find_first_not_of('/'));
      Components[component].Files.push_back(localFileName);
      cmCPackLogger(cmCPackLog::LOG_DEBUG,
                    "Adding file <" << localFileName << "> to component <"
                                    << component << ">" << std::endl);
    }
  }

  if (auto d = mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES")) {
    if (!absoluteDestFiles.empty()) {
      absoluteDestFiles += ";";
    }
    absoluteDestFiles += d;
    cmCPackLogger(cmCPackLog::LOG_DEBUG,
                  "Got some ABSOLUTE DESTINATION FILES: " << absoluteDestFiles
                                                          << std::endl);
    // define component specific var
    if (componentInstall) {
      std::string absoluteDestFileComponent =
        std::string("CPACK_ABSOLUTE_DESTINATION_FILES") + "_" +
        GetComponentInstallDirNameSuffix(component);
      if (nullptr != this->GetOption(absoluteDestFileComponent)) {
        std::string absoluteDestFilesListComponent =
          cmStrCat(this->GetOption(absoluteDestFileComponent), ';', d);
        this->SetOption(absoluteDestFileComponent,
                        absoluteDestFilesListComponent.c_str());
      } else {
        this->SetOption(absoluteDestFileComponent,
                        mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES"));
      }
    }
  }
  if (cmSystemTools::GetErrorOccuredFlag() || !res) {
    return 0;
  }
  return 1;
}

bool cmCPackGenerator::ReadListFile(const char* moduleName)
{
  bool retval;
  std::string fullPath = this->MakefileMap->GetModulesFile(moduleName);
  retval = this->MakefileMap->ReadListFile(fullPath);
  // include FATAL_ERROR and ERROR in the return status
  retval = retval && (!cmSystemTools::GetErrorOccuredFlag());
  return retval;
}

void cmCPackGenerator::SetOptionIfNotSet(const std::string& op,
                                         const char* value)
{
  const char* def = this->MakefileMap->GetDefinition(op);
  if (def && *def) {
    return;
  }
  this->SetOption(op, value);
}

void cmCPackGenerator::SetOption(const std::string& op, const char* value)
{
  if (!value) {
    this->MakefileMap->RemoveDefinition(op);
    return;
  }
  cmCPackLogger(cmCPackLog::LOG_DEBUG,
                this->GetNameOfClass() << "::SetOption(" << op << ", " << value
                                       << ")" << std::endl);
  this->MakefileMap->AddDefinition(op, value);
}

int cmCPackGenerator::DoPackage()
{
  cmCPackLogger(cmCPackLog::LOG_OUTPUT,
                "Create package using " << this->Name << std::endl);

  // Prepare CPack internal name and check
  // values for many CPACK_xxx vars
  if (!this->PrepareNames()) {
    return 0;
  }

  // Digest Component grouping specification
  if (!this->PrepareGroupingKind()) {
    return 0;
  }

  if (cmIsOn(this->GetOption("CPACK_REMOVE_TOPLEVEL_DIRECTORY"))) {
    const char* toplevelDirectory =
      this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
    if (cmSystemTools::FileExists(toplevelDirectory)) {
      cmCPackLogger(cmCPackLog::LOG_VERBOSE,
                    "Remove toplevel directory: " << toplevelDirectory
                                                  << std::endl);
      if (!cmSystemTools::RepeatedRemoveDirectory(toplevelDirectory)) {
        cmCPackLogger(cmCPackLog::LOG_ERROR,
                      "Problem removing toplevel directory: "
                        << toplevelDirectory << std::endl);
        return 0;
      }
    }
  }
  cmCPackLogger(cmCPackLog::LOG_DEBUG,
                "About to install project " << std::endl);

  if (!this->InstallProject()) {
    return 0;
  }
  cmCPackLogger(cmCPackLog::LOG_DEBUG, "Done install project " << std::endl);

  const char* tempPackageFileName =
    this->GetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME");
  const char* tempDirectory = this->GetOption("CPACK_TEMPORARY_DIRECTORY");

  cmCPackLogger(cmCPackLog::LOG_DEBUG, "Find files" << std::endl);
  cmsys::Glob gl;
  std::string findExpr = cmStrCat(tempDirectory, "/*");
  gl.RecurseOn();
  gl.SetRecurseListDirs(true);
  gl.SetRecurseThroughSymlinks(false);
  if (!gl.FindFiles(findExpr)) {
    cmCPackLogger(cmCPackLog::LOG_ERROR,
                  "Cannot find any files in the packaging tree" << std::endl);
    return 0;
  }

  cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Create package" << std::endl);
  cmCPackLogger(cmCPackLog::LOG_VERBOSE,
                "Package files to: "
                  << (tempPackageFileName ? tempPackageFileName : "(NULL)")
                  << std::endl);
  if (cmSystemTools::FileExists(tempPackageFileName)) {
    cmCPackLogger(cmCPackLog::LOG_VERBOSE,
                  "Remove old package file" << std::endl);
    cmSystemTools::RemoveFile(tempPackageFileName);
  }
  if (cmIsOn(this->GetOption("CPACK_INCLUDE_TOPLEVEL_DIRECTORY"))) {
    tempDirectory = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
  }

  // The files to be installed
  files = gl.GetFiles();

  packageFileNames.clear();
  /* Put at least one file name into the list of
   * wanted packageFileNames. The specific generator
   * may update this during PackageFiles.
   * (either putting several names or updating the provided one)
   */
  packageFileNames.emplace_back(tempPackageFileName ? tempPackageFileName
                                                    : "");
  toplevel = tempDirectory;
  { // scope that enables package generators to run internal scripts with
    // latest CMake policies enabled
    cmMakefile::ScopePushPop pp{ this->MakefileMap };
    this->MakefileMap->SetPolicyVersion(cmVersion::GetCMakeVersion(),
                                        std::string());

    if (!this->PackageFiles() || cmSystemTools::GetErrorOccuredFlag()) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "Problem compressing the directory" << std::endl);
      return 0;
    }
  }
  // Run post-build actions
  const char* postBuildScripts = this->GetOption("CPACK_POST_BUILD_SCRIPTS");
  if (postBuildScripts) {
    this->MakefileMap->AddDefinition("CPACK_PACKAGE_FILES",
                                     cmJoin(this->packageFileNames, ";"));

    const auto scripts = cmExpandedList(postBuildScripts, false);
    for (const auto& script : scripts) {
      cmCPackLogger(cmCPackLog::LOG_OUTPUT,
                    "Executing post-build script: " << script << std::endl);

      if (!this->MakefileMap->ReadListFile(script)) {
        cmCPackLogger(cmCPackLog::LOG_ERROR,
                      "The post-build script not found: " << script
                                                          << std::endl);
        return 0;
      }
    }
  }

  /* Prepare checksum algorithm*/
  const char* algo = this->GetOption("CPACK_PACKAGE_CHECKSUM");
  std::unique_ptr<cmCryptoHash> crypto = cmCryptoHash::New(algo ? algo : "");

  /*
   * Copy the generated packages to final destination
   *  - there may be several of them
   *  - the initially provided name may have changed
   *    (because the specific generator did 'normalize' it)
   */
  cmCPackLogger(cmCPackLog::LOG_VERBOSE,
                "Copying final package(s) [" << packageFileNames.size()
                                             << "]:" << std::endl);
  /* now copy package one by one */
  for (std::string const& pkgFileName : packageFileNames) {
    std::string tmpPF(this->GetOption("CPACK_OUTPUT_FILE_PREFIX"));
    std::string filename(cmSystemTools::GetFilenameName(pkgFileName));
    tempPackageFileName = pkgFileName.c_str();
    tmpPF += "/" + filename;
    const char* packageFileName = tmpPF.c_str();
    cmCPackLogger(cmCPackLog::LOG_DEBUG,
                  "Copy final package(s): "
                    << (tempPackageFileName ? tempPackageFileName : "(NULL)")
                    << " to " << (packageFileName ? packageFileName : "(NULL)")
                    << std::endl);
    if (!cmSystemTools::CopyFileIfDifferent(pkgFileName, tmpPF)) {
      cmCPackLogger(
        cmCPackLog::LOG_ERROR,
        "Problem copying the package: "
          << (tempPackageFileName ? tempPackageFileName : "(NULL)") << " to "
          << (packageFileName ? packageFileName : "(NULL)") << std::endl);
      return 0;
    }
    cmCPackLogger(cmCPackLog::LOG_OUTPUT,
                  "- package: " << packageFileName << " generated."
                                << std::endl);

    /* Generate checksum file */
    if (crypto) {
      std::string hashFile(this->GetOption("CPACK_OUTPUT_FILE_PREFIX"));
      hashFile += "/" + filename;
      hashFile += "." + cmSystemTools::LowerCase(algo);
      cmsys::ofstream outF(hashFile.c_str());
      if (!outF) {
        cmCPackLogger(cmCPackLog::LOG_ERROR,
                      "Cannot create checksum file: " << hashFile
                                                      << std::endl);
        return 0;
      }
      outF << crypto->HashFile(packageFileName) << "  " << filename << "\n";
      cmCPackLogger(cmCPackLog::LOG_OUTPUT,
                    "- checksum file: " << hashFile << " generated."
                                        << std::endl);
    }
  }

  return 1;
}

int cmCPackGenerator::Initialize(const std::string& name, cmMakefile* mf)
{
  this->MakefileMap = mf;
  this->Name = name;
  // set the running generator name
  this->SetOption("CPACK_GENERATOR", this->Name.c_str());
  // Load the project specific config file
  const char* config = this->GetOption("CPACK_PROJECT_CONFIG_FILE");
  if (config) {
    mf->ReadListFile(config);
  }
  int result = this->InitializeInternal();
  if (cmSystemTools::GetErrorOccuredFlag()) {
    return 0;
  }

  // If a generator subclass did not already set this option in its
  // InitializeInternal implementation, and the project did not already set
  // it, the default value should be:
  this->SetOptionIfNotSet("CPACK_PACKAGING_INSTALL_PREFIX", "/");

  return result;
}

int cmCPackGenerator::InitializeInternal()
{
  return 1;
}

bool cmCPackGenerator::IsSet(const std::string& name) const
{
  return this->MakefileMap->IsSet(name);
}

bool cmCPackGenerator::IsOn(const std::string& name) const
{
  return cmIsOn(GetOption(name));
}

bool cmCPackGenerator::IsSetToOff(const std::string& op) const
{
  const char* ret = this->MakefileMap->GetDefinition(op);
  if (ret && *ret) {
    return cmIsOff(ret);
  }
  return false;
}

bool cmCPackGenerator::IsSetToEmpty(const std::string& op) const
{
  const char* ret = this->MakefileMap->GetDefinition(op);
  if (ret) {
    return !*ret;
  }
  return false;
}

const char* cmCPackGenerator::GetOption(const std::string& op) const
{
  const char* ret = this->MakefileMap->GetDefinition(op);
  if (!ret) {
    cmCPackLogger(cmCPackLog::LOG_DEBUG,
                  "Warning, GetOption return NULL for: " << op << std::endl);
  }
  return ret;
}

std::vector<std::string> cmCPackGenerator::GetOptions() const
{
  return this->MakefileMap->GetDefinitions();
}

int cmCPackGenerator::PackageFiles()
{
  return 0;
}

const char* cmCPackGenerator::GetInstallPath()
{
  if (!this->InstallPath.empty()) {
    return this->InstallPath.c_str();
  }
#if defined(_WIN32) && !defined(__CYGWIN__)
  std::string prgfiles;
  std::string sysDrive;
  if (cmsys::SystemTools::GetEnv("ProgramFiles", prgfiles)) {
    this->InstallPath = prgfiles;
  } else if (cmsys::SystemTools::GetEnv("SystemDrive", sysDrive)) {
    this->InstallPath = cmStrCat(sysDrive, "/Program Files");
  } else {
    this->InstallPath = "c:/Program Files";
  }
  this->InstallPath += "/";
  this->InstallPath += this->GetOption("CPACK_PACKAGE_NAME");
  this->InstallPath += "-";
  this->InstallPath += this->GetOption("CPACK_PACKAGE_VERSION");
#elif defined(__HAIKU__)
  char dir[B_PATH_NAME_LENGTH];
  if (find_directory(B_SYSTEM_DIRECTORY, -1, false, dir, sizeof(dir)) ==
      B_OK) {
    this->InstallPath = dir;
  } else {
    this->InstallPath = "/boot/system";
  }
#else
  this->InstallPath = "/usr/local/";
#endif
  return this->InstallPath.c_str();
}

const char* cmCPackGenerator::GetPackagingInstallPrefix()
{
  cmCPackLogger(cmCPackLog::LOG_DEBUG,
                "GetPackagingInstallPrefix: '"
                  << this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX") << "'"
                  << std::endl);

  return this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX");
}

std::string cmCPackGenerator::FindTemplate(const char* name)
{
  cmCPackLogger(cmCPackLog::LOG_DEBUG,
                "Look for template: " << (name ? name : "(NULL)")
                                      << std::endl);
  // Search CMAKE_MODULE_PATH for a custom template.
  std::string ffile = this->MakefileMap->GetModulesFile(name);
  if (ffile.empty()) {
    // Fall back to our internal builtin default.
    ffile = cmStrCat(cmSystemTools::GetCMakeRoot(), "/Modules/Internal/CPack/",
                     name);
    cmSystemTools::ConvertToUnixSlashes(ffile);
    if (!cmSystemTools::FileExists(ffile)) {
      ffile.clear();
    }
  }
  cmCPackLogger(cmCPackLog::LOG_DEBUG,
                "Found template: " << ffile << std::endl);
  return ffile;
}

bool cmCPackGenerator::ConfigureString(const std::string& inString,
                                       std::string& outString)
{
  this->MakefileMap->ConfigureString(inString, outString, true, false);
  return true;
}

bool cmCPackGenerator::ConfigureFile(const std::string& inName,
                                     const std::string& outName,
                                     bool copyOnly /* = false */)
{
  return this->MakefileMap->ConfigureFile(inName, outName, copyOnly, true,
                                          false) == 1;
}

int cmCPackGenerator::CleanTemporaryDirectory()
{
  std::string tempInstallDirectory =
    this->GetOption("CPACK_TEMPORARY_INSTALL_DIRECTORY");
  if (cmsys::SystemTools::FileExists(tempInstallDirectory)) {
    cmCPackLogger(cmCPackLog::LOG_OUTPUT,
                  "- Clean temporary : " << tempInstallDirectory << std::endl);
    if (!cmSystemTools::RepeatedRemoveDirectory(tempInstallDirectory)) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "Problem removing temporary directory: "
                      << tempInstallDirectory << std::endl);
      return 0;
    }
  }
  return 1;
}

cmInstalledFile const* cmCPackGenerator::GetInstalledFile(
  std::string const& name) const
{
  cmake const* cm = this->MakefileMap->GetCMakeInstance();
  return cm->GetInstalledFile(name);
}

int cmCPackGenerator::PrepareGroupingKind()
{
  // find a component package method specified by the user
  ComponentPackageMethod method = UNKNOWN_COMPONENT_PACKAGE_METHOD;

  if (this->GetOption("CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE")) {
    method = ONE_PACKAGE;
  }

  if (this->GetOption("CPACK_COMPONENTS_IGNORE_GROUPS")) {
    method = ONE_PACKAGE_PER_COMPONENT;
  }

  if (this->GetOption("CPACK_COMPONENTS_ONE_PACKAGE_PER_GROUP")) {
    method = ONE_PACKAGE_PER_GROUP;
  }

  std::string groupingType;

  // Second way to specify grouping
  if (nullptr != this->GetOption("CPACK_COMPONENTS_GROUPING")) {
    groupingType = this->GetOption("CPACK_COMPONENTS_GROUPING");
  }

  if (!groupingType.empty()) {
    cmCPackLogger(cmCPackLog::LOG_VERBOSE,
                  "[" << this->Name << "]"
                      << " requested component grouping = " << groupingType
                      << std::endl);
    if (groupingType == "ALL_COMPONENTS_IN_ONE") {
      method = ONE_PACKAGE;
    } else if (groupingType == "IGNORE") {
      method = ONE_PACKAGE_PER_COMPONENT;
    } else if (groupingType == "ONE_PER_GROUP") {
      method = ONE_PACKAGE_PER_GROUP;
    } else {
      cmCPackLogger(
        cmCPackLog::LOG_WARNING,
        "[" << this->Name << "]"
            << " requested component grouping type <" << groupingType
            << "> UNKNOWN not in (ALL_COMPONENTS_IN_ONE,IGNORE,ONE_PER_GROUP)"
            << std::endl);
    }
  }

  // Some components were defined but NO group
  // fallback to default if not group based
  if (method == ONE_PACKAGE_PER_GROUP && this->ComponentGroups.empty() &&
      !this->Components.empty()) {
    if (componentPackageMethod == ONE_PACKAGE) {
      method = ONE_PACKAGE;
    } else {
      method = ONE_PACKAGE_PER_COMPONENT;
    }
    cmCPackLogger(
      cmCPackLog::LOG_WARNING,
      "[" << this->Name << "]"
          << " One package per component group requested, "
          << "but NO component groups exist: Ignoring component group."
          << std::endl);
  }

  // if user specified packaging method, override the default packaging
  // method
  if (method != UNKNOWN_COMPONENT_PACKAGE_METHOD) {
    componentPackageMethod = method;
  }

  const char* method_names[] = { "ALL_COMPONENTS_IN_ONE", "IGNORE_GROUPS",
                                 "ONE_PER_GROUP" };

  cmCPackLogger(cmCPackLog::LOG_VERBOSE,
                "[" << this->Name << "]"
                    << " requested component grouping = "
                    << method_names[componentPackageMethod] << std::endl);

  return 1;
}

std::string cmCPackGenerator::GetComponentInstallDirNameSuffix(
  const std::string& componentName)
{
  return componentName;
}
std::string cmCPackGenerator::GetComponentPackageFileName(
  const std::string& initialPackageFileName,
  const std::string& groupOrComponentName, bool isGroupName)
{

  /*
   * the default behavior is to use the
   * component [group] name as a suffix
   */
  std::string suffix = "-" + groupOrComponentName;
  /* check if we should use DISPLAY name */
  std::string dispNameVar = "CPACK_" + Name + "_USE_DISPLAY_NAME_IN_FILENAME";
  if (IsOn(dispNameVar)) {
    /* the component Group case */
    if (isGroupName) {
      std::string groupDispVar = "CPACK_COMPONENT_GROUP_" +
        cmSystemTools::UpperCase(groupOrComponentName) + "_DISPLAY_NAME";
      const char* groupDispName = GetOption(groupDispVar);
      if (groupDispName) {
        suffix = "-" + std::string(groupDispName);
      }
    }
    /* the [single] component case */
    else {
      std::string dispVar = "CPACK_COMPONENT_" +
        cmSystemTools::UpperCase(groupOrComponentName) + "_DISPLAY_NAME";
      const char* dispName = GetOption(dispVar);
      if (dispName) {
        suffix = "-" + std::string(dispName);
      }
    }
  }
  return initialPackageFileName + suffix;
}

enum cmCPackGenerator::CPackSetDestdirSupport
cmCPackGenerator::SupportsSetDestdir() const
{
  return cmCPackGenerator::SETDESTDIR_SUPPORTED;
}

bool cmCPackGenerator::SupportsAbsoluteDestination() const
{
  return true;
}

bool cmCPackGenerator::SupportsComponentInstallation() const
{
  return false;
}

bool cmCPackGenerator::WantsComponentInstallation() const
{
  return (!IsOn("CPACK_MONOLITHIC_INSTALL") &&
          SupportsComponentInstallation()
          // check that we have at least one group or component
          && (!this->ComponentGroups.empty() || !this->Components.empty()));
}

cmCPackInstallationType* cmCPackGenerator::GetInstallationType(
  const std::string& projectName, const std::string& name)
{
  (void)projectName;
  bool hasInstallationType = this->InstallationTypes.count(name) != 0;
  cmCPackInstallationType* installType = &this->InstallationTypes[name];
  if (!hasInstallationType) {
    // Define the installation type
    std::string macroPrefix =
      "CPACK_INSTALL_TYPE_" + cmsys::SystemTools::UpperCase(name);
    installType->Name = name;

    const char* displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME");
    if (displayName && *displayName) {
      installType->DisplayName = displayName;
    } else {
      installType->DisplayName = installType->Name;
    }

    installType->Index = static_cast<unsigned>(this->InstallationTypes.size());
  }
  return installType;
}

cmCPackComponent* cmCPackGenerator::GetComponent(
  const std::string& projectName, const std::string& name)
{
  bool hasComponent = this->Components.count(name) != 0;
  cmCPackComponent* component = &this->Components[name];
  if (!hasComponent) {
    // Define the component
    std::string macroPrefix =
      "CPACK_COMPONENT_" + cmsys::SystemTools::UpperCase(name);
    component->Name = name;
    const char* displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME");
    if (displayName && *displayName) {
      component->DisplayName = displayName;
    } else {
      component->DisplayName = component->Name;
    }
    component->IsHidden = this->IsOn(macroPrefix + "_HIDDEN");
    component->IsRequired = this->IsOn(macroPrefix + "_REQUIRED");
    component->IsDisabledByDefault = this->IsOn(macroPrefix + "_DISABLED");
    component->IsDownloaded = this->IsOn(macroPrefix + "_DOWNLOADED") ||
      cmIsOn(this->GetOption("CPACK_DOWNLOAD_ALL"));

    const char* archiveFile = this->GetOption(macroPrefix + "_ARCHIVE_FILE");
    if (archiveFile && *archiveFile) {
      component->ArchiveFile = archiveFile;
    }

    const char* plist = this->GetOption(macroPrefix + "_PLIST");
    if (plist && *plist) {
      component->Plist = plist;
    }

    const char* groupName = this->GetOption(macroPrefix + "_GROUP");
    if (groupName && *groupName) {
      component->Group = GetComponentGroup(projectName, groupName);
      component->Group->Components.push_back(component);
    } else {
      component->Group = nullptr;
    }

    const char* description = this->GetOption(macroPrefix + "_DESCRIPTION");
    if (description && *description) {
      component->Description = description;
    }

    // Determine the installation types.
    const char* installTypes = this->GetOption(macroPrefix + "_INSTALL_TYPES");
    if (installTypes && *installTypes) {
      std::vector<std::string> installTypesVector =
        cmExpandedList(installTypes);
      for (std::string const& installType : installTypesVector) {
        component->InstallationTypes.push_back(
          this->GetInstallationType(projectName, installType));
      }
    }

    // Determine the component dependencies.
    const char* depends = this->GetOption(macroPrefix + "_DEPENDS");
    if (depends && *depends) {
      std::vector<std::string> dependsVector = cmExpandedList(depends);
      for (std::string const& depend : dependsVector) {
        cmCPackComponent* child = GetComponent(projectName, depend);
        component->Dependencies.push_back(child);
        child->ReverseDependencies.push_back(component);
      }
    }
  }
  return component;
}

cmCPackComponentGroup* cmCPackGenerator::GetComponentGroup(
  const std::string& projectName, const std::string& name)
{
  (void)projectName;
  std::string macroPrefix =
    "CPACK_COMPONENT_GROUP_" + cmsys::SystemTools::UpperCase(name);
  bool hasGroup = this->ComponentGroups.count(name) != 0;
  cmCPackComponentGroup* group = &this->ComponentGroups[name];
  if (!hasGroup) {
    // Define the group
    group->Name = name;
    const char* displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME");
    if (displayName && *displayName) {
      group->DisplayName = displayName;
    } else {
      group->DisplayName = group->Name;
    }

    const char* description = this->GetOption(macroPrefix + "_DESCRIPTION");
    if (description && *description) {
      group->Description = description;
    }
    group->IsBold = this->IsOn(macroPrefix + "_BOLD_TITLE");
    group->IsExpandedByDefault = this->IsOn(macroPrefix + "_EXPANDED");
    const char* parentGroupName =
      this->GetOption(macroPrefix + "_PARENT_GROUP");
    if (parentGroupName && *parentGroupName) {
      group->ParentGroup = GetComponentGroup(projectName, parentGroupName);
      group->ParentGroup->Subgroups.push_back(group);
    } else {
      group->ParentGroup = nullptr;
    }
  }
  return group;
}
