diff options
Diffstat (limited to 'Source/CPack/IFW')
-rw-r--r-- | Source/CPack/IFW/cmCPackIFWGenerator.cxx | 584 | ||||
-rw-r--r-- | Source/CPack/IFW/cmCPackIFWGenerator.h | 164 | ||||
-rw-r--r-- | Source/CPack/IFW/cmCPackIFWInstaller.cxx | 546 | ||||
-rw-r--r-- | Source/CPack/IFW/cmCPackIFWInstaller.h | 140 | ||||
-rw-r--r-- | Source/CPack/IFW/cmCPackIFWPackage.cxx | 725 | ||||
-rw-r--r-- | Source/CPack/IFW/cmCPackIFWPackage.h | 160 | ||||
-rw-r--r-- | Source/CPack/IFW/cmCPackIFWRepository.cxx | 334 | ||||
-rw-r--r-- | Source/CPack/IFW/cmCPackIFWRepository.h | 98 |
8 files changed, 2751 insertions, 0 deletions
diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx new file mode 100644 index 0000000..ee46d86 --- /dev/null +++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx @@ -0,0 +1,584 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmCPackIFWGenerator.h" + +#include "CPack/cmCPackComponentGroup.h" +#include "CPack/cmCPackGenerator.h" +#include "CPack/cmCPackLog.h" +#include "cmCPackIFWInstaller.h" +#include "cmCPackIFWPackage.h" +#include "cmCPackIFWRepository.h" +#include "cmGeneratedFileStream.h" +#include "cmSystemTools.h" +#include "cmTimestamp.h" +#include "cmVersionConfig.h" +#include "cmXMLWriter.h" + +#include <sstream> +#include <utility> + +cmCPackIFWGenerator::cmCPackIFWGenerator() +{ +} + +cmCPackIFWGenerator::~cmCPackIFWGenerator() +{ +} + +bool cmCPackIFWGenerator::IsVersionLess(const char* version) +{ + return cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, + FrameworkVersion.data(), version); +} + +bool cmCPackIFWGenerator::IsVersionGreater(const char* version) +{ + return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER, + FrameworkVersion.data(), version); +} + +bool cmCPackIFWGenerator::IsVersionEqual(const char* version) +{ + return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL, + FrameworkVersion.data(), version); +} + +int cmCPackIFWGenerator::PackageFiles() +{ + cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Configuration" << std::endl); + + // Installer configuragion + Installer.GenerateInstallerFile(); + + // Packages configuration + Installer.GeneratePackageFiles(); + + std::string ifwTLD = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); + std::string ifwTmpFile = ifwTLD; + ifwTmpFile += "/IFWOutput.log"; + + // Run repogen + if (!Installer.RemoteRepositories.empty()) { + std::string ifwCmd = RepoGen; + + if (IsVersionLess("2.0.0")) { + ifwCmd += " -c " + this->toplevel + "/config/config.xml"; + } + + ifwCmd += " -p " + this->toplevel + "/packages"; + + if (!PkgsDirsVector.empty()) { + for (std::vector<std::string>::iterator it = PkgsDirsVector.begin(); + it != PkgsDirsVector.end(); ++it) { + ifwCmd += " -p " + *it; + } + } + + if (!OnlineOnly && !DownloadedPackages.empty()) { + ifwCmd += " -i "; + std::set<cmCPackIFWPackage*>::iterator it = DownloadedPackages.begin(); + ifwCmd += (*it)->Name; + ++it; + while (it != DownloadedPackages.end()) { + ifwCmd += "," + (*it)->Name; + ++it; + } + } + ifwCmd += " " + this->toplevel + "/repository"; + cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << ifwCmd << std::endl); + std::string output; + int retVal = 1; + cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Generate repository" + << std::endl); + bool res = cmSystemTools::RunSingleCommand(ifwCmd.c_str(), &output, + &output, &retVal, CM_NULLPTR, + this->GeneratorVerbose, 0); + if (!res || retVal) { + cmGeneratedFileStream ofs(ifwTmpFile.c_str()); + ofs << "# Run command: " << ifwCmd << std::endl + << "# Output:" << std::endl + << output << std::endl; + cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running IFW command: " + << ifwCmd << std::endl + << "Please check " << ifwTmpFile << " for errors" + << std::endl); + return 0; + } + + if (!Repository.RepositoryUpdate.empty() && + !Repository.PatchUpdatesXml()) { + cmCPackLogger(cmCPackLog::LOG_WARNING, "Problem patch IFW \"Updates\" " + << "file: " << this->toplevel + "/repository/Updates.xml" + << std::endl); + } + + cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- repository: " + << this->toplevel << "/repository generated" << std::endl); + } + + // Run binary creator + { + std::string ifwCmd = BinCreator; + ifwCmd += " -c " + this->toplevel + "/config/config.xml"; + + if (!Installer.Resources.empty()) { + ifwCmd += " -r "; + std::vector<std::string>::iterator it = Installer.Resources.begin(); + std::string path = this->toplevel + "/resources/"; + ifwCmd += path + *it; + ++it; + while (it != Installer.Resources.end()) { + ifwCmd += "," + path + *it; + ++it; + } + } + + ifwCmd += " -p " + this->toplevel + "/packages"; + + if (!PkgsDirsVector.empty()) { + for (std::vector<std::string>::iterator it = PkgsDirsVector.begin(); + it != PkgsDirsVector.end(); ++it) { + ifwCmd += " -p " + *it; + } + } + + if (OnlineOnly) { + ifwCmd += " --online-only"; + } else if (!DownloadedPackages.empty() && + !Installer.RemoteRepositories.empty()) { + ifwCmd += " -e "; + std::set<cmCPackIFWPackage*>::iterator it = DownloadedPackages.begin(); + ifwCmd += (*it)->Name; + ++it; + while (it != DownloadedPackages.end()) { + ifwCmd += "," + (*it)->Name; + ++it; + } + } else if (!DependentPackages.empty()) { + ifwCmd += " -i "; + // Binary + std::set<cmCPackIFWPackage*>::iterator bit = BinaryPackages.begin(); + while (bit != BinaryPackages.end()) { + ifwCmd += (*bit)->Name + ","; + ++bit; + } + // Depend + DependenceMap::iterator it = DependentPackages.begin(); + ifwCmd += it->second.Name; + ++it; + while (it != DependentPackages.end()) { + ifwCmd += "," + it->second.Name; + ++it; + } + } + // TODO: set correct name for multipackages + if (!this->packageFileNames.empty()) { + ifwCmd += " " + packageFileNames[0]; + } else { + ifwCmd += " installer"; + } + cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << ifwCmd << std::endl); + std::string output; + int retVal = 1; + cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Generate package" << std::endl); + bool res = cmSystemTools::RunSingleCommand(ifwCmd.c_str(), &output, + &output, &retVal, CM_NULLPTR, + this->GeneratorVerbose, 0); + if (!res || retVal) { + cmGeneratedFileStream ofs(ifwTmpFile.c_str()); + ofs << "# Run command: " << ifwCmd << std::endl + << "# Output:" << std::endl + << output << std::endl; + cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running IFW command: " + << ifwCmd << std::endl + << "Please check " << ifwTmpFile << " for errors" + << std::endl); + return 0; + } + } + + return 1; +} + +const char* cmCPackIFWGenerator::GetPackagingInstallPrefix() +{ + const char* defPrefix = cmCPackGenerator::GetPackagingInstallPrefix(); + + std::string tmpPref = defPrefix ? defPrefix : ""; + + if (this->Components.empty()) { + tmpPref += "packages/" + GetRootPackageName() + "/data"; + } + + this->SetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX", tmpPref.c_str()); + + return this->GetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX"); +} + +const char* cmCPackIFWGenerator::GetOutputExtension() +{ + return ExecutableSuffix.c_str(); +} + +int cmCPackIFWGenerator::InitializeInternal() +{ + // Search Qt Installer Framework tools + + const std::string BinCreatorOpt = "CPACK_IFW_BINARYCREATOR_EXECUTABLE"; + const std::string RepoGenOpt = "CPACK_IFW_REPOGEN_EXECUTABLE"; + const std::string FrameworkVersionOpt = "CPACK_IFW_FRAMEWORK_VERSION"; + + if (!this->IsSet(BinCreatorOpt) || !this->IsSet(RepoGenOpt) || + !this->IsSet(FrameworkVersionOpt)) { + this->ReadListFile("CPackIFW.cmake"); + } + + // Look 'binarycreator' executable (needs) + + const char* BinCreatorStr = this->GetOption(BinCreatorOpt); + if (!BinCreatorStr || cmSystemTools::IsNOTFOUND(BinCreatorStr)) { + BinCreator = ""; + } else { + BinCreator = BinCreatorStr; + } + + if (BinCreator.empty()) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Cannot find QtIFW compiler \"binarycreator\": " + "likely it is not installed, or not in your PATH" + << std::endl); + return 0; + } + + // Look 'repogen' executable (optional) + + const char* RepoGenStr = this->GetOption(RepoGenOpt); + if (!RepoGenStr || cmSystemTools::IsNOTFOUND(RepoGenStr)) { + RepoGen = ""; + } else { + RepoGen = RepoGenStr; + } + + // Framework version + if (const char* FrameworkVersionSrt = this->GetOption(FrameworkVersionOpt)) { + FrameworkVersion = FrameworkVersionSrt; + } else { + FrameworkVersion = "1.9.9"; + } + + // Variables that Change Behavior + + // Resolve duplicate names + ResolveDuplicateNames = this->IsOn("CPACK_IFW_RESOLVE_DUPLICATE_NAMES"); + + // Additional packages dirs + PkgsDirsVector.clear(); + if (const char* dirs = this->GetOption("CPACK_IFW_PACKAGES_DIRECTORIES")) { + cmSystemTools::ExpandListArgument(dirs, PkgsDirsVector); + } + + // Installer + Installer.Generator = this; + Installer.ConfigureFromOptions(); + + // Repository + Repository.Generator = this; + Repository.Name = "Unspecified"; + if (const char* site = this->GetOption("CPACK_DOWNLOAD_SITE")) { + Repository.Url = site; + Installer.RemoteRepositories.push_back(&Repository); + } + + // Repositories + if (const char* RepoAllStr = this->GetOption("CPACK_IFW_REPOSITORIES_ALL")) { + std::vector<std::string> RepoAllVector; + cmSystemTools::ExpandListArgument(RepoAllStr, RepoAllVector); + for (std::vector<std::string>::iterator rit = RepoAllVector.begin(); + rit != RepoAllVector.end(); ++rit) { + GetRepository(*rit); + } + } + + if (const char* ifwDownloadAll = this->GetOption("CPACK_IFW_DOWNLOAD_ALL")) { + OnlineOnly = cmSystemTools::IsOn(ifwDownloadAll); + } else if (const char* cpackDownloadAll = + this->GetOption("CPACK_DOWNLOAD_ALL")) { + OnlineOnly = cmSystemTools::IsOn(cpackDownloadAll); + } else { + OnlineOnly = false; + } + + if (!Installer.RemoteRepositories.empty() && RepoGen.empty()) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Cannot find QtIFW repository generator \"repogen\": " + "likely it is not installed, or not in your PATH" + << std::endl); + return 0; + } + + // Executable suffix + if (const char* optExeSuffix = this->GetOption("CMAKE_EXECUTABLE_SUFFIX")) { + ExecutableSuffix = optExeSuffix; + if (ExecutableSuffix.empty()) { + std::string sysName(this->GetOption("CMAKE_SYSTEM_NAME")); + if (sysName == "Linux") { + ExecutableSuffix = ".run"; + } + } + } else { + ExecutableSuffix = cmCPackGenerator::GetOutputExtension(); + } + + return this->Superclass::InitializeInternal(); +} + +std::string cmCPackIFWGenerator::GetComponentInstallDirNameSuffix( + const std::string& componentName) +{ + const std::string prefix = "packages/"; + const std::string suffix = "/data"; + + if (componentPackageMethod == ONE_PACKAGE) { + return std::string(prefix + GetRootPackageName() + suffix); + } + + return prefix + GetComponentPackageName(&Components[componentName]) + suffix; +} + +cmCPackComponent* cmCPackIFWGenerator::GetComponent( + const std::string& projectName, const std::string& componentName) +{ + ComponentsMap::iterator cit = Components.find(componentName); + if (cit != Components.end()) { + return &(cit->second); + } + + cmCPackComponent* component = + cmCPackGenerator::GetComponent(projectName, componentName); + if (!component) { + return component; + } + + std::string name = GetComponentPackageName(component); + PackagesMap::iterator pit = Packages.find(name); + if (pit != Packages.end()) { + return component; + } + + cmCPackIFWPackage* package = &Packages[name]; + package->Name = name; + package->Generator = this; + if (package->ConfigureFromComponent(component)) { + package->Installer = &Installer; + Installer.Packages.insert( + std::pair<std::string, cmCPackIFWPackage*>(name, package)); + ComponentPackages.insert( + std::pair<cmCPackComponent*, cmCPackIFWPackage*>(component, package)); + if (component->IsDownloaded) { + DownloadedPackages.insert(package); + } else { + BinaryPackages.insert(package); + } + } else { + Packages.erase(name); + cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot configure package \"" + << name << "\" for component \"" << component->Name << "\"" + << std::endl); + } + + return component; +} + +cmCPackComponentGroup* cmCPackIFWGenerator::GetComponentGroup( + const std::string& projectName, const std::string& groupName) +{ + cmCPackComponentGroup* group = + cmCPackGenerator::GetComponentGroup(projectName, groupName); + if (!group) { + return group; + } + + std::string name = GetGroupPackageName(group); + PackagesMap::iterator pit = Packages.find(name); + if (pit != Packages.end()) { + return group; + } + + cmCPackIFWPackage* package = &Packages[name]; + package->Name = name; + package->Generator = this; + if (package->ConfigureFromGroup(group)) { + package->Installer = &Installer; + Installer.Packages.insert( + std::pair<std::string, cmCPackIFWPackage*>(name, package)); + GroupPackages.insert( + std::pair<cmCPackComponentGroup*, cmCPackIFWPackage*>(group, package)); + BinaryPackages.insert(package); + } else { + Packages.erase(name); + cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot configure package \"" + << name << "\" for component group \"" << group->Name + << "\"" << std::endl); + } + return group; +} + +enum cmCPackGenerator::CPackSetDestdirSupport +cmCPackIFWGenerator::SupportsSetDestdir() const +{ + return cmCPackGenerator::SETDESTDIR_SHOULD_NOT_BE_USED; +} + +bool cmCPackIFWGenerator::SupportsAbsoluteDestination() const +{ + return false; +} + +bool cmCPackIFWGenerator::SupportsComponentInstallation() const +{ + return true; +} + +bool cmCPackIFWGenerator::IsOnePackage() const +{ + return componentPackageMethod == ONE_PACKAGE; +} + +std::string cmCPackIFWGenerator::GetRootPackageName() +{ + // Default value + std::string name = "root"; + if (const char* optIFW_PACKAGE_GROUP = + this->GetOption("CPACK_IFW_PACKAGE_GROUP")) { + // Configure from root group + cmCPackIFWPackage package; + package.Generator = this; + package.ConfigureFromGroup(optIFW_PACKAGE_GROUP); + name = package.Name; + } else if (const char* optIFW_PACKAGE_NAME = + this->GetOption("CPACK_IFW_PACKAGE_NAME")) { + // Configure from root package name + name = optIFW_PACKAGE_NAME; + } else if (const char* optPACKAGE_NAME = + this->GetOption("CPACK_PACKAGE_NAME")) { + // Configure from package name + name = optPACKAGE_NAME; + } + return name; +} + +std::string cmCPackIFWGenerator::GetGroupPackageName( + cmCPackComponentGroup* group) const +{ + std::string name; + if (!group) { + return name; + } + if (cmCPackIFWPackage* package = GetGroupPackage(group)) { + return package->Name; + } + const char* option = + GetOption("CPACK_IFW_COMPONENT_GROUP_" + + cmsys::SystemTools::UpperCase(group->Name) + "_NAME"); + name = option ? option : group->Name; + if (group->ParentGroup) { + cmCPackIFWPackage* package = GetGroupPackage(group->ParentGroup); + bool dot = !ResolveDuplicateNames; + if (dot && name.substr(0, package->Name.size()) == package->Name) { + dot = false; + } + if (dot) { + name = package->Name + "." + name; + } + } + return name; +} + +std::string cmCPackIFWGenerator::GetComponentPackageName( + cmCPackComponent* component) const +{ + std::string name; + if (!component) { + return name; + } + if (cmCPackIFWPackage* package = GetComponentPackage(component)) { + return package->Name; + } + std::string prefix = "CPACK_IFW_COMPONENT_" + + cmsys::SystemTools::UpperCase(component->Name) + "_"; + const char* option = GetOption(prefix + "NAME"); + name = option ? option : component->Name; + if (component->Group) { + cmCPackIFWPackage* package = GetGroupPackage(component->Group); + if ((componentPackageMethod == ONE_PACKAGE_PER_GROUP) || + IsOn(prefix + "COMMON")) { + return package->Name; + } + bool dot = !ResolveDuplicateNames; + if (dot && name.substr(0, package->Name.size()) == package->Name) { + dot = false; + } + if (dot) { + name = package->Name + "." + name; + } + } + return name; +} + +cmCPackIFWPackage* cmCPackIFWGenerator::GetGroupPackage( + cmCPackComponentGroup* group) const +{ + std::map<cmCPackComponentGroup*, cmCPackIFWPackage*>::const_iterator pit = + GroupPackages.find(group); + return pit != GroupPackages.end() ? pit->second : CM_NULLPTR; +} + +cmCPackIFWPackage* cmCPackIFWGenerator::GetComponentPackage( + cmCPackComponent* component) const +{ + std::map<cmCPackComponent*, cmCPackIFWPackage*>::const_iterator pit = + ComponentPackages.find(component); + return pit != ComponentPackages.end() ? pit->second : CM_NULLPTR; +} + +cmCPackIFWRepository* cmCPackIFWGenerator::GetRepository( + const std::string& repositoryName) +{ + RepositoriesMap::iterator rit = Repositories.find(repositoryName); + if (rit != Repositories.end()) { + return &(rit->second); + } + + cmCPackIFWRepository* repository = &Repositories[repositoryName]; + repository->Name = repositoryName; + repository->Generator = this; + if (repository->ConfigureFromOptions()) { + if (repository->Update == cmCPackIFWRepository::None) { + Installer.RemoteRepositories.push_back(repository); + } else { + Repository.RepositoryUpdate.push_back(repository); + } + } else { + Repositories.erase(repositoryName); + repository = CM_NULLPTR; + cmCPackLogger(cmCPackLog::LOG_WARNING, "Invalid repository \"" + << repositoryName << "\"" + << " configuration. Repository will be skipped." + << std::endl); + } + return repository; +} + +void cmCPackIFWGenerator::WriteGeneratedByToStrim(cmXMLWriter& xout) +{ + std::ostringstream comment; + comment << "Generated by CPack " << CMake_VERSION << " IFW generator " + << "for QtIFW "; + if (IsVersionLess("2.0")) { + comment << "less 2.0"; + } else { + comment << FrameworkVersion; + } + comment << " tools at " << cmTimestamp().CurrentTime("", true); + xout.Comment(comment.str().c_str()); +} diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.h b/Source/CPack/IFW/cmCPackIFWGenerator.h new file mode 100644 index 0000000..d656063 --- /dev/null +++ b/Source/CPack/IFW/cmCPackIFWGenerator.h @@ -0,0 +1,164 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmCPackIFWGenerator_h +#define cmCPackIFWGenerator_h + +#include <cmConfigure.h> + +#include "CPack/cmCPackComponentGroup.h" +#include "CPack/cmCPackGenerator.h" +#include "cmCPackIFWInstaller.h" +#include "cmCPackIFWPackage.h" +#include "cmCPackIFWRepository.h" + +#include <map> +#include <set> +#include <string> +#include <vector> + +class cmXMLWriter; + +/** \class cmCPackIFWGenerator + * \brief A generator for Qt Installer Framework tools + * + * http://qt-project.org/doc/qtinstallerframework/index.html + */ +class cmCPackIFWGenerator : public cmCPackGenerator +{ +public: + cmCPackTypeMacro(cmCPackIFWGenerator, cmCPackGenerator); + + typedef std::map<std::string, cmCPackIFWPackage> PackagesMap; + typedef std::map<std::string, cmCPackIFWRepository> RepositoriesMap; + typedef std::map<std::string, cmCPackComponent> ComponentsMap; + typedef std::map<std::string, cmCPackComponentGroup> ComponentGoupsMap; + typedef std::map<std::string, cmCPackIFWPackage::DependenceStruct> + DependenceMap; + + /** + * Construct IFW generator + */ + cmCPackIFWGenerator(); + + /** + * Destruct IFW generator + */ + ~cmCPackIFWGenerator() CM_OVERRIDE; + + /** + * Compare \a version with QtIFW framework version + */ + bool IsVersionLess(const char* version); + + /** + * Compare \a version with QtIFW framework version + */ + bool IsVersionGreater(const char* version); + + /** + * Compare \a version with QtIFW framework version + */ + bool IsVersionEqual(const char* version); + +protected: + // cmCPackGenerator reimplementation + + /** + * @brief Initialize generator + * @return 0 on failure + */ + int InitializeInternal() CM_OVERRIDE; + int PackageFiles() CM_OVERRIDE; + const char* GetPackagingInstallPrefix() CM_OVERRIDE; + + /** + * @brief Extension of binary installer + * @return Executable suffix or value from default implementation + */ + const char* GetOutputExtension() CM_OVERRIDE; + + std::string GetComponentInstallDirNameSuffix( + const std::string& componentName) CM_OVERRIDE; + + /** + * @brief Get Component + * @param projectName Project name + * @param componentName Component name + * + * This method calls the base implementation. + * + * @return Pointer to component + */ + cmCPackComponent* GetComponent(const std::string& projectName, + const std::string& componentName) CM_OVERRIDE; + + /** + * @brief Get group of component + * @param projectName Project name + * @param groupName Component group name + * + * This method calls the base implementation. + * + * @return Pointer to component group + */ + cmCPackComponentGroup* GetComponentGroup( + const std::string& projectName, const std::string& groupName) CM_OVERRIDE; + + enum cmCPackGenerator::CPackSetDestdirSupport SupportsSetDestdir() const + CM_OVERRIDE; + bool SupportsAbsoluteDestination() const CM_OVERRIDE; + bool SupportsComponentInstallation() const CM_OVERRIDE; + +protected: + // Methods + + bool IsOnePackage() const; + + std::string GetRootPackageName(); + + std::string GetGroupPackageName(cmCPackComponentGroup* group) const; + std::string GetComponentPackageName(cmCPackComponent* component) const; + + cmCPackIFWPackage* GetGroupPackage(cmCPackComponentGroup* group) const; + cmCPackIFWPackage* GetComponentPackage(cmCPackComponent* component) const; + + cmCPackIFWRepository* GetRepository(const std::string& repositoryName); + + void WriteGeneratedByToStrim(cmXMLWriter& xout); + +protected: + // Data + + friend class cmCPackIFWPackage; + friend class cmCPackIFWInstaller; + friend class cmCPackIFWRepository; + + // Installer + cmCPackIFWInstaller Installer; + // Repository + cmCPackIFWRepository Repository; + // Collection of packages + PackagesMap Packages; + // Collection of repositories + RepositoriesMap Repositories; + // Collection of binary packages + std::set<cmCPackIFWPackage*> BinaryPackages; + // Collection of downloaded packages + std::set<cmCPackIFWPackage*> DownloadedPackages; + // Dependent packages + DependenceMap DependentPackages; + std::map<cmCPackComponent*, cmCPackIFWPackage*> ComponentPackages; + std::map<cmCPackComponentGroup*, cmCPackIFWPackage*> GroupPackages; + +private: + std::string RepoGen; + std::string BinCreator; + std::string FrameworkVersion; + std::string ExecutableSuffix; + + bool OnlineOnly; + bool ResolveDuplicateNames; + std::vector<std::string> PkgsDirsVector; +}; + +#endif diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx new file mode 100644 index 0000000..d8bafee --- /dev/null +++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx @@ -0,0 +1,546 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmCPackIFWInstaller.h" + +#include <cmConfigure.h> +#include <sstream> +#include <stddef.h> +#include <utility> + +#include "CPack/cmCPackGenerator.h" +#include "CPack/cmCPackLog.h" +#include "cmCPackIFWGenerator.h" +#include "cmCPackIFWPackage.h" +#include "cmCPackIFWRepository.h" +#include "cmGeneratedFileStream.h" +#include "cmSystemTools.h" +#include "cmXMLParser.h" +#include "cmXMLWriter.h" + +#ifdef cmCPackLogger +#undef cmCPackLogger +#endif +#define cmCPackLogger(logType, msg) \ + do { \ + std::ostringstream cmCPackLog_msg; \ + cmCPackLog_msg << msg; \ + if (Generator) { \ + Generator->Logger->Log(logType, __FILE__, __LINE__, \ + cmCPackLog_msg.str().c_str()); \ + } \ + } while (false) + +cmCPackIFWInstaller::cmCPackIFWInstaller() + : Generator(CM_NULLPTR) +{ +} + +const char* cmCPackIFWInstaller::GetOption(const std::string& op) const +{ + return Generator ? Generator->GetOption(op) : CM_NULLPTR; +} + +bool cmCPackIFWInstaller::IsOn(const std::string& op) const +{ + return Generator ? Generator->IsOn(op) : false; +} + +bool cmCPackIFWInstaller::IsVersionLess(const char* version) +{ + return Generator ? Generator->IsVersionLess(version) : false; +} + +bool cmCPackIFWInstaller::IsVersionGreater(const char* version) +{ + return Generator ? Generator->IsVersionGreater(version) : false; +} + +bool cmCPackIFWInstaller::IsVersionEqual(const char* version) +{ + return Generator ? Generator->IsVersionEqual(version) : false; +} + +void cmCPackIFWInstaller::printSkippedOptionWarning( + const std::string& optionName, const std::string& optionValue) +{ + cmCPackLogger( + cmCPackLog::LOG_WARNING, "Option " + << optionName << " is set to \"" << optionValue + << "\" but will be skipped because the specified file does not exist." + << std::endl); +} + +void cmCPackIFWInstaller::ConfigureFromOptions() +{ + // Name; + if (const char* optIFW_PACKAGE_NAME = + this->GetOption("CPACK_IFW_PACKAGE_NAME")) { + Name = optIFW_PACKAGE_NAME; + } else if (const char* optPACKAGE_NAME = + this->GetOption("CPACK_PACKAGE_NAME")) { + Name = optPACKAGE_NAME; + } else { + Name = "Your package"; + } + + // Title; + if (const char* optIFW_PACKAGE_TITLE = + GetOption("CPACK_IFW_PACKAGE_TITLE")) { + Title = optIFW_PACKAGE_TITLE; + } else if (const char* optPACKAGE_DESCRIPTION_SUMMARY = + GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) { + Title = optPACKAGE_DESCRIPTION_SUMMARY; + } else { + Title = "Your package description"; + } + + // Version; + if (const char* option = GetOption("CPACK_PACKAGE_VERSION")) { + Version = option; + } else { + Version = "1.0.0"; + } + + // Publisher + if (const char* optIFW_PACKAGE_PUBLISHER = + GetOption("CPACK_IFW_PACKAGE_PUBLISHER")) { + Publisher = optIFW_PACKAGE_PUBLISHER; + } else if (const char* optPACKAGE_VENDOR = + GetOption("CPACK_PACKAGE_VENDOR")) { + Publisher = optPACKAGE_VENDOR; + } + + // ProductUrl + if (const char* option = GetOption("CPACK_IFW_PRODUCT_URL")) { + ProductUrl = option; + } + + // ApplicationIcon + if (const char* option = GetOption("CPACK_IFW_PACKAGE_ICON")) { + if (cmSystemTools::FileExists(option)) { + InstallerApplicationIcon = option; + } else { + printSkippedOptionWarning("CPACK_IFW_PACKAGE_ICON", option); + } + } + + // WindowIcon + if (const char* option = GetOption("CPACK_IFW_PACKAGE_WINDOW_ICON")) { + if (cmSystemTools::FileExists(option)) { + InstallerWindowIcon = option; + } else { + printSkippedOptionWarning("CPACK_IFW_PACKAGE_WINDOW_ICON", option); + } + } + + // Logo + if (const char* option = GetOption("CPACK_IFW_PACKAGE_LOGO")) { + if (cmSystemTools::FileExists(option)) { + Logo = option; + } else { + printSkippedOptionWarning("CPACK_IFW_PACKAGE_LOGO", option); + } + } + + // Watermark + if (const char* option = GetOption("CPACK_IFW_PACKAGE_WATERMARK")) { + if (cmSystemTools::FileExists(option)) { + Watermark = option; + } else { + printSkippedOptionWarning("CPACK_IFW_PACKAGE_WATERMARK", option); + } + } + + // Banner + if (const char* option = GetOption("CPACK_IFW_PACKAGE_BANNER")) { + if (cmSystemTools::FileExists(option)) { + Banner = option; + } else { + printSkippedOptionWarning("CPACK_IFW_PACKAGE_BANNER", option); + } + } + + // Background + if (const char* option = GetOption("CPACK_IFW_PACKAGE_BACKGROUND")) { + if (cmSystemTools::FileExists(option)) { + Background = option; + } else { + printSkippedOptionWarning("CPACK_IFW_PACKAGE_BACKGROUND", option); + } + } + + // WizardStyle + if (const char* option = GetOption("CPACK_IFW_PACKAGE_WIZARD_STYLE")) { + if (WizardStyle.compare("Modern") == 0 && + WizardStyle.compare("Aero") == 0 && WizardStyle.compare("Mac") == 0 && + WizardStyle.compare("Classic") == 0) { + cmCPackLogger( + cmCPackLog::LOG_WARNING, + "Option CPACK_IFW_PACKAGE_WIZARD_STYLE has unknown value \"" + << option << "\". Expected values are: Modern, Aero, Mac, Classic." + << std::endl); + } + + WizardStyle = option; + } + + // WizardDefaultWidth + if (const char* option = + GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_WIDTH")) { + WizardDefaultWidth = option; + } + + // WizardDefaultHeight + if (const char* option = + GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_HEIGHT")) { + WizardDefaultHeight = option; + } + + // TitleColor + if (const char* option = GetOption("CPACK_IFW_PACKAGE_TITLE_COLOR")) { + TitleColor = option; + } + + // Start menu + if (const char* optIFW_START_MENU_DIR = + this->GetOption("CPACK_IFW_PACKAGE_START_MENU_DIRECTORY")) { + StartMenuDir = optIFW_START_MENU_DIR; + } else { + StartMenuDir = Name; + } + + // Default target directory for installation + if (const char* optIFW_TARGET_DIRECTORY = + GetOption("CPACK_IFW_TARGET_DIRECTORY")) { + TargetDir = optIFW_TARGET_DIRECTORY; + } else if (const char* optPACKAGE_INSTALL_DIRECTORY = + GetOption("CPACK_PACKAGE_INSTALL_DIRECTORY")) { + TargetDir = "@ApplicationsDir@/"; + TargetDir += optPACKAGE_INSTALL_DIRECTORY; + } else { + TargetDir = "@RootDir@/usr/local"; + } + + // Default target directory for installation with administrator rights + if (const char* option = GetOption("CPACK_IFW_ADMIN_TARGET_DIRECTORY")) { + AdminTargetDir = option; + } + + // Maintenance tool + if (const char* optIFW_MAINTENANCE_TOOL = + this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_NAME")) { + MaintenanceToolName = optIFW_MAINTENANCE_TOOL; + } + + // Maintenance tool ini file + if (const char* optIFW_MAINTENANCE_TOOL_INI = + this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_INI_FILE")) { + MaintenanceToolIniFile = optIFW_MAINTENANCE_TOOL_INI; + } + + // Allow non-ASCII characters + if (this->GetOption("CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS")) { + if (IsOn("CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS")) { + AllowNonAsciiCharacters = "true"; + } else { + AllowNonAsciiCharacters = "false"; + } + } + + // Space in path + if (this->GetOption("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) { + if (IsOn("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) { + AllowSpaceInPath = "true"; + } else { + AllowSpaceInPath = "false"; + } + } + + // Control script + if (const char* optIFW_CONTROL_SCRIPT = + this->GetOption("CPACK_IFW_PACKAGE_CONTROL_SCRIPT")) { + ControlScript = optIFW_CONTROL_SCRIPT; + } + + // Resources + if (const char* optIFW_PACKAGE_RESOURCES = + this->GetOption("CPACK_IFW_PACKAGE_RESOURCES")) { + Resources.clear(); + cmSystemTools::ExpandListArgument(optIFW_PACKAGE_RESOURCES, Resources); + } +} + +/** \class cmCPackIFWResourcesParser + * \brief Helper class that parse resources form .qrc (Qt) + */ +class cmCPackIFWResourcesParser : public cmXMLParser +{ +public: + cmCPackIFWResourcesParser(cmCPackIFWInstaller* i) + : installer(i) + , file(false) + { + path = i->Directory + "/resources"; + } + + bool ParseResource(size_t r) + { + hasFiles = false; + hasErrors = false; + + basePath = cmSystemTools::GetFilenamePath(installer->Resources[r].data()); + + ParseFile(installer->Resources[r].data()); + + return hasFiles && !hasErrors; + } + + cmCPackIFWInstaller* installer; + bool file, hasFiles, hasErrors; + std::string path, basePath; + +protected: + void StartElement(const std::string& name, const char** /*atts*/) CM_OVERRIDE + { + file = name == "file"; + if (file) { + hasFiles = true; + } + } + + void CharacterDataHandler(const char* data, int length) CM_OVERRIDE + { + if (file) { + std::string content(data, data + length); + content = cmSystemTools::TrimWhitespace(content); + std::string source = basePath + "/" + content; + std::string destination = path + "/" + content; + if (!cmSystemTools::CopyFileIfDifferent(source.data(), + destination.data())) { + hasErrors = true; + } + } + } + + void EndElement(const std::string& /*name*/) CM_OVERRIDE {} +}; + +void cmCPackIFWInstaller::GenerateInstallerFile() +{ + // Lazy directory initialization + if (Directory.empty() && Generator) { + Directory = Generator->toplevel; + } + + // Output stream + cmGeneratedFileStream fout((Directory + "/config/config.xml").data()); + cmXMLWriter xout(fout); + + xout.StartDocument(); + + WriteGeneratedByToStrim(xout); + + xout.StartElement("Installer"); + + xout.Element("Name", Name); + xout.Element("Version", Version); + xout.Element("Title", Title); + + if (!Publisher.empty()) { + xout.Element("Publisher", Publisher); + } + + if (!ProductUrl.empty()) { + xout.Element("ProductUrl", ProductUrl); + } + + // ApplicationIcon + if (!InstallerApplicationIcon.empty()) { + std::string name = + cmSystemTools::GetFilenameName(InstallerApplicationIcon); + std::string path = Directory + "/config/" + name; + name = cmSystemTools::GetFilenameWithoutExtension(name); + cmsys::SystemTools::CopyFileIfDifferent(InstallerApplicationIcon.data(), + path.data()); + xout.Element("InstallerApplicationIcon", name); + } + + // WindowIcon + if (!InstallerWindowIcon.empty()) { + std::string name = cmSystemTools::GetFilenameName(InstallerWindowIcon); + std::string path = Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent(InstallerWindowIcon.data(), + path.data()); + xout.Element("InstallerWindowIcon", name); + } + + // Logo + if (!Logo.empty()) { + std::string name = cmSystemTools::GetFilenameName(Logo); + std::string path = Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent(Logo.data(), path.data()); + xout.Element("Logo", name); + } + + // Banner + if (!Banner.empty()) { + std::string name = cmSystemTools::GetFilenameName(Banner); + std::string path = Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent(Banner.data(), path.data()); + xout.Element("Banner", name); + } + + // Watermark + if (!Watermark.empty()) { + std::string name = cmSystemTools::GetFilenameName(Watermark); + std::string path = Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent(Watermark.data(), path.data()); + xout.Element("Watermark", name); + } + + // Background + if (!Background.empty()) { + std::string name = cmSystemTools::GetFilenameName(Background); + std::string path = Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent(Background.data(), path.data()); + xout.Element("Background", name); + } + + // WizardStyle + if (!WizardStyle.empty()) { + xout.Element("WizardStyle", WizardStyle); + } + + // WizardDefaultWidth + if (!WizardDefaultWidth.empty()) { + xout.Element("WizardDefaultWidth", WizardDefaultWidth); + } + + // WizardDefaultHeight + if (!WizardDefaultHeight.empty()) { + xout.Element("WizardDefaultHeight", WizardDefaultHeight); + } + + // TitleColor + if (!TitleColor.empty()) { + xout.Element("TitleColor", TitleColor); + } + + // Start menu + if (!IsVersionLess("2.0")) { + xout.Element("StartMenuDir", StartMenuDir); + } + + // Target dir + if (!TargetDir.empty()) { + xout.Element("TargetDir", TargetDir); + } + + // Admin target dir + if (!AdminTargetDir.empty()) { + xout.Element("AdminTargetDir", AdminTargetDir); + } + + // Remote repositories + if (!RemoteRepositories.empty()) { + xout.StartElement("RemoteRepositories"); + for (RepositoriesVector::iterator rit = RemoteRepositories.begin(); + rit != RemoteRepositories.end(); ++rit) { + (*rit)->WriteRepositoryConfig(xout); + } + xout.EndElement(); + } + + // Maintenance tool + if (!IsVersionLess("2.0") && !MaintenanceToolName.empty()) { + xout.Element("MaintenanceToolName", MaintenanceToolName); + } + + // Maintenance tool ini file + if (!IsVersionLess("2.0") && !MaintenanceToolIniFile.empty()) { + xout.Element("MaintenanceToolIniFile", MaintenanceToolIniFile); + } + + // Different allows + if (IsVersionLess("2.0")) { + // CPack IFW default policy + xout.Comment("CPack IFW default policy for QtIFW less 2.0"); + xout.Element("AllowNonAsciiCharacters", "true"); + xout.Element("AllowSpaceInPath", "true"); + } else { + if (!AllowNonAsciiCharacters.empty()) { + xout.Element("AllowNonAsciiCharacters", AllowNonAsciiCharacters); + } + if (!AllowSpaceInPath.empty()) { + xout.Element("AllowSpaceInPath", AllowSpaceInPath); + } + } + + // Control script (copy to config dir) + if (!IsVersionLess("2.0") && !ControlScript.empty()) { + std::string name = cmSystemTools::GetFilenameName(ControlScript); + std::string path = Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent(ControlScript.data(), path.data()); + xout.Element("ControlScript", name); + } + + // Resources (copy to resources dir) + if (!Resources.empty()) { + std::vector<std::string> resources; + cmCPackIFWResourcesParser parser(this); + for (size_t i = 0; i < Resources.size(); i++) { + if (parser.ParseResource(i)) { + std::string name = cmSystemTools::GetFilenameName(Resources[i]); + std::string path = Directory + "/resources/" + name; + cmsys::SystemTools::CopyFileIfDifferent(Resources[i].data(), + path.data()); + resources.push_back(name); + } else { + cmCPackLogger(cmCPackLog::LOG_WARNING, "Can't copy resources from \"" + << Resources[i] << "\". Resource will be skipped." + << std::endl); + } + } + Resources = resources; + } + + xout.EndElement(); + xout.EndDocument(); +} + +void cmCPackIFWInstaller::GeneratePackageFiles() +{ + if (Packages.empty() || Generator->IsOnePackage()) { + // Generate default package + cmCPackIFWPackage package; + package.Generator = Generator; + package.Installer = this; + // Check package group + if (const char* option = GetOption("CPACK_IFW_PACKAGE_GROUP")) { + package.ConfigureFromGroup(option); + std::string forcedOption = "CPACK_IFW_COMPONENT_GROUP_" + + cmsys::SystemTools::UpperCase(option) + "_FORCED_INSTALLATION"; + if (!GetOption(forcedOption)) { + package.ForcedInstallation = "true"; + } + } else { + package.ConfigureFromOptions(); + } + package.GeneratePackageFile(); + return; + } + + // Generate packages meta information + for (PackagesMap::iterator pit = Packages.begin(); pit != Packages.end(); + ++pit) { + cmCPackIFWPackage* package = pit->second; + package->GeneratePackageFile(); + } +} + +void cmCPackIFWInstaller::WriteGeneratedByToStrim(cmXMLWriter& xout) +{ + if (Generator) { + Generator->WriteGeneratedByToStrim(xout); + } +} diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.h b/Source/CPack/IFW/cmCPackIFWInstaller.h new file mode 100644 index 0000000..4ec3e70 --- /dev/null +++ b/Source/CPack/IFW/cmCPackIFWInstaller.h @@ -0,0 +1,140 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmCPackIFWInstaller_h +#define cmCPackIFWInstaller_h + +#include <cmConfigure.h> // IWYU pragma: keep + +#include <map> +#include <string> +#include <vector> + +class cmCPackIFWGenerator; +class cmCPackIFWPackage; +class cmCPackIFWRepository; +class cmXMLWriter; + +/** \class cmCPackIFWInstaller + * \brief A binary installer to be created CPack IFW generator + */ +class cmCPackIFWInstaller +{ +public: + // Types + + typedef std::map<std::string, cmCPackIFWPackage*> PackagesMap; + typedef std::vector<cmCPackIFWRepository*> RepositoriesVector; + +public: + // Constructor + + /** + * Construct installer + */ + cmCPackIFWInstaller(); + +public: + // Configuration + + /// Name of the product being installed + std::string Name; + + /// Version number of the product being installed + std::string Version; + + /// Name of the installer as displayed on the title bar + std::string Title; + + /// Publisher of the software (as shown in the Windows Control Panel) + std::string Publisher; + + /// URL to a page that contains product information on your web site + std::string ProductUrl; + + /// Filename for a custom installer icon + std::string InstallerApplicationIcon; + + /// Filename for a custom window icon + std::string InstallerWindowIcon; + + /// Filename for a logo + std::string Logo; + + /// Filename for a watermark + std::string Watermark; + + /// Filename for a banner + std::string Banner; + + /// Filename for a background + std::string Background; + + /// Wizard style name + std::string WizardStyle; + + /// Wizard width + std::string WizardDefaultWidth; + + /// Wizard height + std::string WizardDefaultHeight; + + /// Title color + std::string TitleColor; + + /// Name of the default program group in the Windows Start menu + std::string StartMenuDir; + + /// Default target directory for installation + std::string TargetDir; + + /// Default target directory for installation with administrator rights + std::string AdminTargetDir; + + /// Filename of the generated maintenance tool + std::string MaintenanceToolName; + + /// Filename for the configuration of the generated maintenance tool + std::string MaintenanceToolIniFile; + + /// Set to true if the installation path can contain non-ASCII characters + std::string AllowNonAsciiCharacters; + + /// Set to false if the installation path cannot contain space characters + std::string AllowSpaceInPath; + + /// Filename for a custom installer control script + std::string ControlScript; + + /// List of resources to include in the installer binary + std::vector<std::string> Resources; + +public: + // Internal implementation + + const char* GetOption(const std::string& op) const; + bool IsOn(const std::string& op) const; + + bool IsVersionLess(const char* version); + bool IsVersionGreater(const char* version); + bool IsVersionEqual(const char* version); + + void ConfigureFromOptions(); + + void GenerateInstallerFile(); + + void GeneratePackageFiles(); + + cmCPackIFWGenerator* Generator; + PackagesMap Packages; + RepositoriesVector RemoteRepositories; + std::string Directory; + +protected: + void WriteGeneratedByToStrim(cmXMLWriter& xout); + +private: + void printSkippedOptionWarning(const std::string& optionName, + const std::string& optionValue); +}; + +#endif // cmCPackIFWInstaller_h diff --git a/Source/CPack/IFW/cmCPackIFWPackage.cxx b/Source/CPack/IFW/cmCPackIFWPackage.cxx new file mode 100644 index 0000000..e23b1b9 --- /dev/null +++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx @@ -0,0 +1,725 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmCPackIFWPackage.h" + +#include "CPack/cmCPackComponentGroup.h" +#include "CPack/cmCPackGenerator.h" +#include "CPack/cmCPackLog.h" +#include "cmCPackIFWGenerator.h" +#include "cmCPackIFWInstaller.h" +#include "cmGeneratedFileStream.h" +#include "cmSystemTools.h" +#include "cmTimestamp.h" +#include "cmXMLWriter.h" + +#include <cmConfigure.h> +#include <map> +#include <sstream> +#include <stddef.h> + +//----------------------------------------------------------------- Logger --- +#ifdef cmCPackLogger +#undef cmCPackLogger +#endif +#define cmCPackLogger(logType, msg) \ + do { \ + std::ostringstream cmCPackLog_msg; \ + cmCPackLog_msg << msg; \ + if (Generator) { \ + Generator->Logger->Log(logType, __FILE__, __LINE__, \ + cmCPackLog_msg.str().c_str()); \ + } \ + } while (false) + +//---------------------------------------------------------- CompareStruct --- +cmCPackIFWPackage::CompareStruct::CompareStruct() + : Type(CompareNone) +{ +} + +//------------------------------------------------------- DependenceStruct --- +cmCPackIFWPackage::DependenceStruct::DependenceStruct() +{ +} + +cmCPackIFWPackage::DependenceStruct::DependenceStruct( + const std::string& dependence) +{ + // Search compare section + size_t pos = std::string::npos; + if ((pos = dependence.find("<=")) != std::string::npos) { + Compare.Type = CompareLessOrEqual; + Compare.Value = dependence.substr(pos + 2); + } else if ((pos = dependence.find(">=")) != std::string::npos) { + Compare.Type = CompareGreaterOrEqual; + Compare.Value = dependence.substr(pos + 2); + } else if ((pos = dependence.find('<')) != std::string::npos) { + Compare.Type = CompareLess; + Compare.Value = dependence.substr(pos + 1); + } else if ((pos = dependence.find('=')) != std::string::npos) { + Compare.Type = CompareEqual; + Compare.Value = dependence.substr(pos + 1); + } else if ((pos = dependence.find('>')) != std::string::npos) { + Compare.Type = CompareGreater; + Compare.Value = dependence.substr(pos + 1); + } else if ((pos = dependence.find('-')) != std::string::npos) { + Compare.Type = CompareNone; + Compare.Value = dependence.substr(pos + 1); + } + size_t dashPos = dependence.find('-'); + if (dashPos != std::string::npos) { + pos = dashPos; + } + Name = pos == std::string::npos ? dependence : dependence.substr(0, pos); +} + +std::string cmCPackIFWPackage::DependenceStruct::NameWithCompare() const +{ + if (Compare.Type == CompareNone) { + return Name; + } + + std::string result = Name; + + if (Compare.Type != CompareNone || !Compare.Value.empty()) { + result += "-"; + } + + if (Compare.Type == CompareLessOrEqual) { + result += "<="; + } else if (Compare.Type == CompareGreaterOrEqual) { + result += ">="; + } else if (Compare.Type == CompareLess) { + result += "<"; + } else if (Compare.Type == CompareEqual) { + result += "="; + } else if (Compare.Type == CompareGreater) { + result += ">"; + } + + result += Compare.Value; + + return result; +} + +//------------------------------------------------------ cmCPackIFWPackage --- +cmCPackIFWPackage::cmCPackIFWPackage() + : Generator(CM_NULLPTR) + , Installer(CM_NULLPTR) +{ +} + +const char* cmCPackIFWPackage::GetOption(const std::string& op) const +{ + const char* option = Generator ? Generator->GetOption(op) : CM_NULLPTR; + return option && *option ? option : CM_NULLPTR; +} + +bool cmCPackIFWPackage::IsOn(const std::string& op) const +{ + return Generator ? Generator->IsOn(op) : false; +} + +bool cmCPackIFWPackage::IsSetToOff(const std::string& op) const +{ + return Generator ? Generator->IsSetToOff(op) : false; +} + +bool cmCPackIFWPackage::IsSetToEmpty(const std::string& op) const +{ + return Generator ? Generator->IsSetToEmpty(op) : false; +} + +bool cmCPackIFWPackage::IsVersionLess(const char* version) +{ + return Generator ? Generator->IsVersionLess(version) : false; +} + +bool cmCPackIFWPackage::IsVersionGreater(const char* version) +{ + return Generator ? Generator->IsVersionGreater(version) : false; +} + +bool cmCPackIFWPackage::IsVersionEqual(const char* version) +{ + return Generator ? Generator->IsVersionEqual(version) : false; +} + +std::string cmCPackIFWPackage::GetComponentName(cmCPackComponent* component) +{ + if (!component) { + return ""; + } + const char* option = + GetOption("CPACK_IFW_COMPONENT_" + + cmsys::SystemTools::UpperCase(component->Name) + "_NAME"); + return option ? option : component->Name; +} + +void cmCPackIFWPackage::DefaultConfiguration() +{ + DisplayName = ""; + Description = ""; + Version = ""; + ReleaseDate = ""; + Script = ""; + Licenses.clear(); + UserInterfaces.clear(); + Translations.clear(); + SortingPriority = ""; + UpdateText = ""; + Default = ""; + Essential = ""; + Virtual = ""; + ForcedInstallation = ""; + RequiresAdminRights = ""; +} + +// Defaul configuration (all in one package) +int cmCPackIFWPackage::ConfigureFromOptions() +{ + // Restore defaul configuration + DefaultConfiguration(); + + // Name + Name = Generator->GetRootPackageName(); + + // Display name + if (const char* option = this->GetOption("CPACK_PACKAGE_NAME")) { + DisplayName = option; + } else { + DisplayName = "Your package"; + } + + // Description + if (const char* option = + this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) { + Description = option; + } else { + Description = "Your package description"; + } + + // Version + if (const char* option = GetOption("CPACK_PACKAGE_VERSION")) { + Version = option; + } else { + Version = "1.0.0"; + } + + ForcedInstallation = "true"; + + return 1; +} + +int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component) +{ + if (!component) { + return 0; + } + + // Restore defaul configuration + DefaultConfiguration(); + + std::string prefix = "CPACK_IFW_COMPONENT_" + + cmsys::SystemTools::UpperCase(component->Name) + "_"; + + // Display name + DisplayName = component->DisplayName; + + // Description + Description = component->Description; + + // Version + if (const char* optVERSION = GetOption(prefix + "VERSION")) { + Version = optVERSION; + } else if (const char* optPACKAGE_VERSION = + GetOption("CPACK_PACKAGE_VERSION")) { + Version = optPACKAGE_VERSION; + } else { + Version = "1.0.0"; + } + + // Script + if (const char* option = GetOption(prefix + "SCRIPT")) { + Script = option; + } + + // User interfaces + if (const char* option = this->GetOption(prefix + "USER_INTERFACES")) { + UserInterfaces.clear(); + cmSystemTools::ExpandListArgument(option, UserInterfaces); + } + + // CMake dependencies + if (!component->Dependencies.empty()) { + std::vector<cmCPackComponent*>::iterator dit; + for (dit = component->Dependencies.begin(); + dit != component->Dependencies.end(); ++dit) { + Dependencies.insert(Generator->ComponentPackages[*dit]); + } + } + + // Licenses + if (const char* option = this->GetOption(prefix + "LICENSES")) { + Licenses.clear(); + cmSystemTools::ExpandListArgument(option, Licenses); + if (Licenses.size() % 2 != 0) { + cmCPackLogger( + cmCPackLog::LOG_WARNING, prefix + << "LICENSES" + << " should contain pairs of <display_name> and <file_path>." + << std::endl); + Licenses.clear(); + } + } + + // Priority + if (const char* option = this->GetOption(prefix + "PRIORITY")) { + SortingPriority = option; + cmCPackLogger( + cmCPackLog::LOG_WARNING, "The \"PRIORITY\" option is set " + << "for component \"" << component->Name << "\", but there option is " + << "deprecated. Please use \"SORTING_PRIORITY\" option instead." + << std::endl); + } + + // Default + Default = component->IsDisabledByDefault ? "false" : "true"; + + // Essential + if (this->IsOn(prefix + "ESSENTIAL")) { + Essential = "true"; + } + + // Virtual + Virtual = component->IsHidden ? "true" : ""; + + // ForcedInstallation + ForcedInstallation = component->IsRequired ? "true" : "false"; + + return ConfigureFromPrefix(prefix); +} + +int cmCPackIFWPackage::ConfigureFromGroup(cmCPackComponentGroup* group) +{ + if (!group) { + return 0; + } + + // Restore defaul configuration + DefaultConfiguration(); + + std::string prefix = "CPACK_IFW_COMPONENT_GROUP_" + + cmsys::SystemTools::UpperCase(group->Name) + "_"; + + DisplayName = group->DisplayName; + Description = group->Description; + + // Version + if (const char* optVERSION = GetOption(prefix + "VERSION")) { + Version = optVERSION; + } else if (const char* optPACKAGE_VERSION = + GetOption("CPACK_PACKAGE_VERSION")) { + Version = optPACKAGE_VERSION; + } else { + Version = "1.0.0"; + } + + // Script + if (const char* option = GetOption(prefix + "SCRIPT")) { + Script = option; + } + + // User interfaces + if (const char* option = this->GetOption(prefix + "USER_INTERFACES")) { + UserInterfaces.clear(); + cmSystemTools::ExpandListArgument(option, UserInterfaces); + } + + // Licenses + if (const char* option = this->GetOption(prefix + "LICENSES")) { + Licenses.clear(); + cmSystemTools::ExpandListArgument(option, Licenses); + if (Licenses.size() % 2 != 0) { + cmCPackLogger( + cmCPackLog::LOG_WARNING, prefix + << "LICENSES" + << " should contain pairs of <display_name> and <file_path>." + << std::endl); + Licenses.clear(); + } + } + + // Priority + if (const char* option = this->GetOption(prefix + "PRIORITY")) { + SortingPriority = option; + cmCPackLogger( + cmCPackLog::LOG_WARNING, "The \"PRIORITY\" option is set " + << "for component group \"" << group->Name + << "\", but there option is " + << "deprecated. Please use \"SORTING_PRIORITY\" option instead." + << std::endl); + } + + return ConfigureFromPrefix(prefix); +} + +int cmCPackIFWPackage::ConfigureFromGroup(const std::string& groupName) +{ + // Group configuration + + cmCPackComponentGroup group; + std::string prefix = + "CPACK_COMPONENT_GROUP_" + cmsys::SystemTools::UpperCase(groupName) + "_"; + + if (const char* option = GetOption(prefix + "DISPLAY_NAME")) { + group.DisplayName = option; + } else { + group.DisplayName = group.Name; + } + + if (const char* option = GetOption(prefix + "DESCRIPTION")) { + group.Description = option; + } + group.IsBold = IsOn(prefix + "BOLD_TITLE"); + group.IsExpandedByDefault = IsOn(prefix + "EXPANDED"); + + // Package configuration + + group.Name = groupName; + + if (Generator) { + Name = Generator->GetGroupPackageName(&group); + } else { + Name = group.Name; + } + + return ConfigureFromGroup(&group); +} + +// Common options for components and groups +int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) +{ + // Temporary variable for full option name + std::string option; + + // Display name + option = prefix + "DISPLAY_NAME"; + if (IsSetToEmpty(option)) { + DisplayName.clear(); + } else if (const char* value = GetOption(option)) { + DisplayName = value; + } + + // Description + option = prefix + "DESCRIPTION"; + if (IsSetToEmpty(option)) { + Description.clear(); + } else if (const char* value = GetOption(option)) { + Description = value; + } + + // Release date + option = prefix + "RELEASE_DATE"; + if (IsSetToEmpty(option)) { + ReleaseDate.clear(); + } else if (const char* value = GetOption(option)) { + ReleaseDate = value; + } + + // Sorting priority + option = prefix + "SORTING_PRIORITY"; + if (IsSetToEmpty(option)) { + SortingPriority.clear(); + } else if (const char* value = GetOption(option)) { + SortingPriority = value; + } + + // Update text + option = prefix + "UPDATE_TEXT"; + if (IsSetToEmpty(option)) { + UpdateText.clear(); + } else if (const char* value = GetOption(option)) { + UpdateText = value; + } + + // Translations + option = prefix + "TRANSLATIONS"; + if (IsSetToEmpty(option)) { + Translations.clear(); + } else if (const char* value = this->GetOption(option)) { + Translations.clear(); + cmSystemTools::ExpandListArgument(value, Translations); + } + + // QtIFW dependencies + std::vector<std::string> deps; + option = prefix + "DEPENDS"; + if (const char* value = this->GetOption(option)) { + cmSystemTools::ExpandListArgument(value, deps); + } + option = prefix + "DEPENDENCIES"; + if (const char* value = this->GetOption(option)) { + cmSystemTools::ExpandListArgument(value, deps); + } + for (std::vector<std::string>::iterator dit = deps.begin(); + dit != deps.end(); ++dit) { + DependenceStruct dep(*dit); + if (Generator->Packages.count(dep.Name)) { + cmCPackIFWPackage& depPkg = Generator->Packages[dep.Name]; + dep.Name = depPkg.Name; + } + bool hasDep = Generator->DependentPackages.count(dep.Name) > 0; + DependenceStruct& depRef = Generator->DependentPackages[dep.Name]; + if (!hasDep) { + depRef = dep; + } + AlienDependencies.insert(&depRef); + } + + // Automatic dependency on + option = prefix + "AUTO_DEPEND_ON"; + if (IsSetToEmpty(option)) { + AlienAutoDependOn.clear(); + } else if (const char* value = this->GetOption(option)) { + std::vector<std::string> depsOn; + cmSystemTools::ExpandListArgument(value, depsOn); + for (std::vector<std::string>::iterator dit = depsOn.begin(); + dit != depsOn.end(); ++dit) { + DependenceStruct dep(*dit); + if (Generator->Packages.count(dep.Name)) { + cmCPackIFWPackage& depPkg = Generator->Packages[dep.Name]; + dep.Name = depPkg.Name; + } + bool hasDep = Generator->DependentPackages.count(dep.Name) > 0; + DependenceStruct& depRef = Generator->DependentPackages[dep.Name]; + if (!hasDep) { + depRef = dep; + } + AlienAutoDependOn.insert(&depRef); + } + } + + // Visibility + option = prefix + "VIRTUAL"; + if (IsSetToEmpty(option)) { + Virtual.clear(); + } else if (IsOn(option)) { + Virtual = "true"; + } + + // Default selection + option = prefix + "DEFAULT"; + if (IsSetToEmpty(option)) { + Default.clear(); + } else if (const char* value = GetOption(option)) { + std::string lowerValue = cmsys::SystemTools::LowerCase(value); + if (lowerValue.compare("true") == 0) { + Default = "true"; + } else if (lowerValue.compare("false") == 0) { + Default = "false"; + } else if (lowerValue.compare("script") == 0) { + Default = "script"; + } else { + Default = value; + } + } + + // Forsed installation + option = prefix + "FORCED_INSTALLATION"; + if (IsSetToEmpty(option)) { + ForcedInstallation.clear(); + } else if (IsOn(option)) { + ForcedInstallation = "true"; + } else if (IsSetToOff(option)) { + ForcedInstallation = "false"; + } + + // Requires admin rights + option = prefix + "REQUIRES_ADMIN_RIGHTS"; + if (IsSetToEmpty(option)) { + RequiresAdminRights.clear(); + } else if (IsOn(option)) { + RequiresAdminRights = "true"; + } else if (IsSetToOff(option)) { + RequiresAdminRights = "false"; + } + + return 1; +} + +void cmCPackIFWPackage::GeneratePackageFile() +{ + // Lazy directory initialization + if (Directory.empty()) { + if (Installer) { + Directory = Installer->Directory + "/packages/" + Name; + } else if (Generator) { + Directory = Generator->toplevel + "/packages/" + Name; + } + } + + // Output stream + cmGeneratedFileStream fout((Directory + "/meta/package.xml").data()); + cmXMLWriter xout(fout); + + xout.StartDocument(); + + WriteGeneratedByToStrim(xout); + + xout.StartElement("Package"); + + xout.Element("DisplayName", DisplayName); + xout.Element("Description", Description); + + // Update text + if (!UpdateText.empty()) { + xout.Element("UpdateText", UpdateText); + } + + xout.Element("Name", Name); + xout.Element("Version", Version); + + if (!ReleaseDate.empty()) { + xout.Element("ReleaseDate", ReleaseDate); + } else { + xout.Element("ReleaseDate", cmTimestamp().CurrentTime("%Y-%m-%d", true)); + } + + // Script (copy to meta dir) + if (!Script.empty()) { + std::string name = cmSystemTools::GetFilenameName(Script); + std::string path = Directory + "/meta/" + name; + cmsys::SystemTools::CopyFileIfDifferent(Script.data(), path.data()); + xout.Element("Script", name); + } + + // User Interfaces (copy to meta dir) + std::vector<std::string> userInterfaces = UserInterfaces; + for (size_t i = 0; i < userInterfaces.size(); i++) { + std::string name = cmSystemTools::GetFilenameName(userInterfaces[i]); + std::string path = Directory + "/meta/" + name; + cmsys::SystemTools::CopyFileIfDifferent(userInterfaces[i].data(), + path.data()); + userInterfaces[i] = name; + } + if (!userInterfaces.empty()) { + xout.StartElement("UserInterfaces"); + for (size_t i = 0; i < userInterfaces.size(); i++) { + xout.Element("UserInterface", userInterfaces[i]); + } + xout.EndElement(); + } + + // Translations (copy to meta dir) + std::vector<std::string> translations = Translations; + for (size_t i = 0; i < translations.size(); i++) { + std::string name = cmSystemTools::GetFilenameName(translations[i]); + std::string path = Directory + "/meta/" + name; + cmsys::SystemTools::CopyFileIfDifferent(translations[i].data(), + path.data()); + translations[i] = name; + } + if (!translations.empty()) { + xout.StartElement("Translations"); + for (size_t i = 0; i < translations.size(); i++) { + xout.Element("Translation", translations[i]); + } + xout.EndElement(); + } + + // Dependencies + std::set<DependenceStruct> compDepSet; + for (std::set<DependenceStruct*>::iterator ait = AlienDependencies.begin(); + ait != AlienDependencies.end(); ++ait) { + compDepSet.insert(*(*ait)); + } + for (std::set<cmCPackIFWPackage*>::iterator it = Dependencies.begin(); + it != Dependencies.end(); ++it) { + compDepSet.insert(DependenceStruct((*it)->Name)); + } + // Write dependencies + if (!compDepSet.empty()) { + std::ostringstream dependencies; + std::set<DependenceStruct>::iterator it = compDepSet.begin(); + dependencies << it->NameWithCompare(); + ++it; + while (it != compDepSet.end()) { + dependencies << "," << it->NameWithCompare(); + ++it; + } + xout.Element("Dependencies", dependencies.str()); + } + + // Automatic dependency on + std::set<DependenceStruct> compAutoDepSet; + for (std::set<DependenceStruct*>::iterator ait = AlienAutoDependOn.begin(); + ait != AlienAutoDependOn.end(); ++ait) { + compAutoDepSet.insert(*(*ait)); + } + // Write automatic dependency on + if (!compAutoDepSet.empty()) { + std::ostringstream dependencies; + std::set<DependenceStruct>::iterator it = compAutoDepSet.begin(); + dependencies << it->NameWithCompare(); + ++it; + while (it != compAutoDepSet.end()) { + dependencies << "," << it->NameWithCompare(); + ++it; + } + xout.Element("AutoDependOn", dependencies.str()); + } + + // Licenses (copy to meta dir) + std::vector<std::string> licenses = Licenses; + for (size_t i = 1; i < licenses.size(); i += 2) { + std::string name = cmSystemTools::GetFilenameName(licenses[i]); + std::string path = Directory + "/meta/" + name; + cmsys::SystemTools::CopyFileIfDifferent(licenses[i].data(), path.data()); + licenses[i] = name; + } + if (!licenses.empty()) { + xout.StartElement("Licenses"); + for (size_t i = 0; i < licenses.size(); i += 2) { + xout.StartElement("License"); + xout.Attribute("name", licenses[i]); + xout.Attribute("file", licenses[i + 1]); + xout.EndElement(); + } + xout.EndElement(); + } + + if (!ForcedInstallation.empty()) { + xout.Element("ForcedInstallation", ForcedInstallation); + } + + if (!RequiresAdminRights.empty()) { + xout.Element("RequiresAdminRights", RequiresAdminRights); + } + + if (!Virtual.empty()) { + xout.Element("Virtual", Virtual); + } else if (!Default.empty()) { + xout.Element("Default", Default); + } + + // Essential + if (!Essential.empty()) { + xout.Element("Essential", Essential); + } + + // Priority + if (!SortingPriority.empty()) { + xout.Element("SortingPriority", SortingPriority); + } + + xout.EndElement(); + xout.EndDocument(); +} + +void cmCPackIFWPackage::WriteGeneratedByToStrim(cmXMLWriter& xout) +{ + if (Generator) { + Generator->WriteGeneratedByToStrim(xout); + } +} diff --git a/Source/CPack/IFW/cmCPackIFWPackage.h b/Source/CPack/IFW/cmCPackIFWPackage.h new file mode 100644 index 0000000..bd1d6c5 --- /dev/null +++ b/Source/CPack/IFW/cmCPackIFWPackage.h @@ -0,0 +1,160 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmCPackIFWPackage_h +#define cmCPackIFWPackage_h + +#include <cmConfigure.h> // IWYU pragma: keep + +#include <set> +#include <string> +#include <vector> + +class cmCPackComponent; +class cmCPackComponentGroup; +class cmCPackIFWGenerator; +class cmCPackIFWInstaller; +class cmXMLWriter; + +/** \class cmCPackIFWPackage + * \brief A single component to be installed by CPack IFW generator + */ +class cmCPackIFWPackage +{ +public: + // Types + + enum CompareTypes + { + CompareNone = 0x0, + CompareEqual = 0x1, + CompareLess = 0x2, + CompareLessOrEqual = 0x3, + CompareGreater = 0x4, + CompareGreaterOrEqual = 0x5 + }; + + struct CompareStruct + { + CompareStruct(); + + unsigned int Type; + std::string Value; + }; + + struct DependenceStruct + { + DependenceStruct(); + DependenceStruct(const std::string& dependence); + + std::string Name; + CompareStruct Compare; + + std::string NameWithCompare() const; + + bool operator<(const DependenceStruct& other) const + { + return Name < other.Name; + } + }; + +public: + // [Con|De]structor + + /** + * Construct package + */ + cmCPackIFWPackage(); + +public: + // Configuration + + /// Human-readable name of the component + std::string DisplayName; + + /// Human-readable description of the component + std::string Description; + + /// Version number of the component + std::string Version; + + /// Date when this component version was released + std::string ReleaseDate; + + /// Domain-like identification for this component + std::string Name; + + /// File name of a script being loaded + std::string Script; + + /// List of license agreements to be accepted by the installing user + std::vector<std::string> Licenses; + + /// List of pages to load + std::vector<std::string> UserInterfaces; + + /// List of translation files to load + std::vector<std::string> Translations; + + /// Priority of the component in the tree + std::string SortingPriority; + + /// Description added to the component description + std::string UpdateText; + + /// Set to true to preselect the component in the installer + std::string Default; + + /// Marks the package as essential to force a restart of the MaintenanceTool + std::string Essential; + + /// Set to true to hide the component from the installer + std::string Virtual; + + /// Determines that the package must always be installed + std::string ForcedInstallation; + + /// Package needs to be installed with elevated permissions + std::string RequiresAdminRights; + +public: + // Internal implementation + + const char* GetOption(const std::string& op) const; + bool IsOn(const std::string& op) const; + bool IsSetToOff(const std::string& op) const; + bool IsSetToEmpty(const std::string& op) const; + + bool IsVersionLess(const char* version); + bool IsVersionGreater(const char* version); + bool IsVersionEqual(const char* version); + + std::string GetComponentName(cmCPackComponent* component); + + void DefaultConfiguration(); + + int ConfigureFromOptions(); + int ConfigureFromComponent(cmCPackComponent* component); + int ConfigureFromGroup(cmCPackComponentGroup* group); + int ConfigureFromGroup(const std::string& groupName); + int ConfigureFromPrefix(const std::string& prefix); + + void GeneratePackageFile(); + + // Pointer to generator + cmCPackIFWGenerator* Generator; + // Pointer to installer + cmCPackIFWInstaller* Installer; + // Collection of dependencies + std::set<cmCPackIFWPackage*> Dependencies; + // Collection of unresolved dependencies + std::set<DependenceStruct*> AlienDependencies; + // Collection of unresolved automatic dependency on + std::set<DependenceStruct*> AlienAutoDependOn; + // Patch to package directory + std::string Directory; + +protected: + void WriteGeneratedByToStrim(cmXMLWriter& xout); +}; + +#endif // cmCPackIFWPackage_h diff --git a/Source/CPack/IFW/cmCPackIFWRepository.cxx b/Source/CPack/IFW/cmCPackIFWRepository.cxx new file mode 100644 index 0000000..cc204e8 --- /dev/null +++ b/Source/CPack/IFW/cmCPackIFWRepository.cxx @@ -0,0 +1,334 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmCPackIFWRepository.h" + +#include "CPack/cmCPackGenerator.h" +#include "cmCPackIFWGenerator.h" +#include "cmGeneratedFileStream.h" +#include "cmSystemTools.h" +#include "cmXMLParser.h" +#include "cmXMLWriter.h" + +#include <cmConfigure.h> +#include <stddef.h> + +#ifdef cmCPackLogger +#undef cmCPackLogger +#endif +#define cmCPackLogger(logType, msg) \ + do { \ + std::ostringstream cmCPackLog_msg; \ + cmCPackLog_msg << msg; \ + if (Generator) { \ + Generator->Logger->Log(logType, __FILE__, __LINE__, \ + cmCPackLog_msg.str().c_str()); \ + } \ + } while (false) + +cmCPackIFWRepository::cmCPackIFWRepository() + : Update(None) + , Generator(CM_NULLPTR) +{ +} + +bool cmCPackIFWRepository::IsValid() const +{ + bool valid = true; + + switch (Update) { + case None: + valid = !Url.empty(); + break; + case Add: + valid = !Url.empty(); + break; + case Remove: + valid = !Url.empty(); + break; + case Replace: + valid = !OldUrl.empty() && !NewUrl.empty(); + break; + } + + return valid; +} + +const char* cmCPackIFWRepository::GetOption(const std::string& op) const +{ + return Generator ? Generator->GetOption(op) : CM_NULLPTR; +} + +bool cmCPackIFWRepository::IsOn(const std::string& op) const +{ + return Generator ? Generator->IsOn(op) : false; +} + +bool cmCPackIFWRepository::IsVersionLess(const char* version) +{ + return Generator ? Generator->IsVersionLess(version) : false; +} + +bool cmCPackIFWRepository::IsVersionGreater(const char* version) +{ + return Generator ? Generator->IsVersionGreater(version) : false; +} + +bool cmCPackIFWRepository::IsVersionEqual(const char* version) +{ + return Generator ? Generator->IsVersionEqual(version) : false; +} + +bool cmCPackIFWRepository::ConfigureFromOptions() +{ + // Name; + if (Name.empty()) { + return false; + } + + std::string prefix = + "CPACK_IFW_REPOSITORY_" + cmsys::SystemTools::UpperCase(Name) + "_"; + + // Update + if (IsOn(prefix + "ADD")) { + Update = Add; + } else if (IsOn(prefix + "REMOVE")) { + Update = Remove; + } else if (IsOn(prefix + "REPLACE")) { + Update = Replace; + } else { + Update = None; + } + + // Url + if (const char* url = GetOption(prefix + "URL")) { + Url = url; + } else { + Url = ""; + } + + // Old url + if (const char* oldUrl = GetOption(prefix + "OLD_URL")) { + OldUrl = oldUrl; + } else { + OldUrl = ""; + } + + // New url + if (const char* newUrl = GetOption(prefix + "NEW_URL")) { + NewUrl = newUrl; + } else { + NewUrl = ""; + } + + // Enabled + if (IsOn(prefix + "DISABLED")) { + Enabled = "0"; + } else { + Enabled = ""; + } + + // Username + if (const char* username = GetOption(prefix + "USERNAME")) { + Username = username; + } else { + Username = ""; + } + + // Password + if (const char* password = GetOption(prefix + "PASSWORD")) { + Password = password; + } else { + Password = ""; + } + + // DisplayName + if (const char* displayName = GetOption(prefix + "DISPLAY_NAME")) { + DisplayName = displayName; + } else { + DisplayName = ""; + } + + return IsValid(); +} + +/** \class cmCPackeIFWUpdatesPatcher + * \brief Helper class that parses and patch Updates.xml file (QtIFW) + */ +class cmCPackeIFWUpdatesPatcher : public cmXMLParser +{ +public: + cmCPackeIFWUpdatesPatcher(cmCPackIFWRepository* r, cmXMLWriter& x) + : repository(r) + , xout(x) + , patched(false) + { + } + + cmCPackIFWRepository* repository; + cmXMLWriter& xout; + bool patched; + +protected: + void StartElement(const std::string& name, const char** atts) CM_OVERRIDE + { + xout.StartElement(name); + StartFragment(atts); + } + + void StartFragment(const char** atts) + { + for (size_t i = 0; atts[i]; i += 2) { + const char* key = atts[i]; + const char* value = atts[i + 1]; + xout.Attribute(key, value); + } + } + + void EndElement(const std::string& name) CM_OVERRIDE + { + if (name == "Updates" && !patched) { + repository->WriteRepositoryUpdates(xout); + patched = true; + } + xout.EndElement(); + if (patched) { + return; + } + if (name == "Checksum") { + repository->WriteRepositoryUpdates(xout); + patched = true; + } + } + + void CharacterDataHandler(const char* data, int length) CM_OVERRIDE + { + std::string content(data, data + length); + if (content == "" || content == " " || content == " " || + content == "\n") { + return; + } + xout.Content(content); + } +}; + +bool cmCPackIFWRepository::PatchUpdatesXml() +{ + // Lazy directory initialization + if (Directory.empty() && Generator) { + Directory = Generator->toplevel; + } + + // Filenames + std::string updatesXml = Directory + "/repository/Updates.xml"; + std::string updatesPatchXml = Directory + "/repository/UpdatesPatch.xml"; + + // Output stream + cmGeneratedFileStream fout(updatesPatchXml.data()); + cmXMLWriter xout(fout); + + xout.StartDocument(); + + WriteGeneratedByToStrim(xout); + + // Patch + { + cmCPackeIFWUpdatesPatcher patcher(this, xout); + patcher.ParseFile(updatesXml.data()); + } + + xout.EndDocument(); + + fout.Close(); + + return cmSystemTools::RenameFile(updatesPatchXml.data(), updatesXml.data()); +} + +void cmCPackIFWRepository::WriteRepositoryConfig(cmXMLWriter& xout) +{ + xout.StartElement("Repository"); + + // Url + xout.Element("Url", Url); + // Enabled + if (!Enabled.empty()) { + xout.Element("Enabled", Enabled); + } + // Username + if (!Username.empty()) { + xout.Element("Username", Username); + } + // Password + if (!Password.empty()) { + xout.Element("Password", Password); + } + // DisplayName + if (!DisplayName.empty()) { + xout.Element("DisplayName", DisplayName); + } + + xout.EndElement(); +} + +void cmCPackIFWRepository::WriteRepositoryUpdate(cmXMLWriter& xout) +{ + xout.StartElement("Repository"); + + switch (Update) { + case None: + break; + case Add: + xout.Attribute("action", "add"); + break; + case Remove: + xout.Attribute("action", "remove"); + break; + case Replace: + xout.Attribute("action", "replace"); + break; + } + + // Url + if (Update == Add || Update == Remove) { + xout.Attribute("url", Url); + } else if (Update == Replace) { + xout.Attribute("oldUrl", OldUrl); + xout.Attribute("newUrl", NewUrl); + } + // Enabled + if (!Enabled.empty()) { + xout.Attribute("enabled", Enabled); + } + // Username + if (!Username.empty()) { + xout.Attribute("username", Username); + } + // Password + if (!Password.empty()) { + xout.Attribute("password", Password); + } + // DisplayName + if (!DisplayName.empty()) { + xout.Attribute("displayname", DisplayName); + } + + xout.EndElement(); +} + +void cmCPackIFWRepository::WriteRepositoryUpdates(cmXMLWriter& xout) +{ + if (!RepositoryUpdate.empty()) { + xout.StartElement("RepositoryUpdate"); + for (RepositoriesVector::iterator rit = RepositoryUpdate.begin(); + rit != RepositoryUpdate.end(); ++rit) { + (*rit)->WriteRepositoryUpdate(xout); + } + xout.EndElement(); + } +} + +void cmCPackIFWRepository::WriteGeneratedByToStrim(cmXMLWriter& xout) +{ + if (Generator) { + Generator->WriteGeneratedByToStrim(xout); + } +} diff --git a/Source/CPack/IFW/cmCPackIFWRepository.h b/Source/CPack/IFW/cmCPackIFWRepository.h new file mode 100644 index 0000000..36f46da --- /dev/null +++ b/Source/CPack/IFW/cmCPackIFWRepository.h @@ -0,0 +1,98 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmCPackIFWRepository_h +#define cmCPackIFWRepository_h + +#include <cmConfigure.h> // IWYU pragma: keep + +#include <string> +#include <vector> + +class cmCPackIFWGenerator; +class cmXMLWriter; + +/** \class cmCPackIFWRepository + * \brief A remote repository to be created CPack IFW generator + */ +class cmCPackIFWRepository +{ +public: + // Types + + enum Action + { + None, + Add, + Remove, + Replace + }; + + typedef std::vector<cmCPackIFWRepository*> RepositoriesVector; + +public: + // Constructor + + /** + * Construct repository + */ + cmCPackIFWRepository(); + +public: + // Configuration + + /// Internal repository name + std::string Name; + + /// Optional update action + Action Update; + + /// Is points to a list of available components + std::string Url; + + /// Is points to a list that will replaced + std::string OldUrl; + + /// Is points to a list that will replace to + std::string NewUrl; + + /// With "0" disabling this repository + std::string Enabled; + + /// Is used as user on a protected repository + std::string Username; + + /// Is password to use on a protected repository + std::string Password; + + /// Is optional string to display instead of the URL + std::string DisplayName; + +public: + // Internal implementation + + bool IsValid() const; + + const char* GetOption(const std::string& op) const; + bool IsOn(const std::string& op) const; + + bool IsVersionLess(const char* version); + bool IsVersionGreater(const char* version); + bool IsVersionEqual(const char* version); + + bool ConfigureFromOptions(); + + bool PatchUpdatesXml(); + + void WriteRepositoryConfig(cmXMLWriter& xout); + void WriteRepositoryUpdate(cmXMLWriter& xout); + void WriteRepositoryUpdates(cmXMLWriter& xout); + + cmCPackIFWGenerator* Generator; + RepositoriesVector RepositoryUpdate; + std::string Directory; + +protected: + void WriteGeneratedByToStrim(cmXMLWriter& xout); +}; + +#endif // cmCPackIFWRepository_h |