diff options
Diffstat (limited to 'Source/CPack/cmCPackArchiveGenerator.cxx')
-rw-r--r-- | Source/CPack/cmCPackArchiveGenerator.cxx | 314 |
1 files changed, 314 insertions, 0 deletions
diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx new file mode 100644 index 000000000..6e7b8d7c8 --- /dev/null +++ b/Source/CPack/cmCPackArchiveGenerator.cxx @@ -0,0 +1,314 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#include "cmCPackArchiveGenerator.h" + +#include "cmake.h" +#include "cmGlobalGenerator.h" +#include "cmLocalGenerator.h" +#include "cmSystemTools.h" +#include "cmMakefile.h" +#include "cmGeneratedFileStream.h" +#include "cmCPackLog.h" +#include <errno.h> + +#include <cmsys/SystemTools.hxx> +#include <cmsys/Directory.hxx> +#include <cm_libarchive.h> + +//---------------------------------------------------------------------- +cmCPackArchiveGenerator::cmCPackArchiveGenerator(cmArchiveWrite::Compress t, + cmArchiveWrite::Type at) +{ + this->Compress = t; + this->Archive = at; +} + +//---------------------------------------------------------------------- +cmCPackArchiveGenerator::~cmCPackArchiveGenerator() +{ +} + +//---------------------------------------------------------------------- +int cmCPackArchiveGenerator::InitializeInternal() +{ + this->SetOptionIfNotSet("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", "1"); + return this->Superclass::InitializeInternal(); +} +//---------------------------------------------------------------------- +int cmCPackArchiveGenerator::addOneComponentToArchive(cmArchiveWrite& archive, + cmCPackComponent* component) +{ + cmCPackLogger(cmCPackLog::LOG_VERBOSE, " - packaging component: " + << component->Name + << std::endl); + // Add the files of this component to the archive + std::string localToplevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY")); + localToplevel += "/"+ component->Name; + std::string dir = cmSystemTools::GetCurrentWorkingDirectory(); + // Change to local toplevel + cmSystemTools::ChangeDirectory(localToplevel.c_str()); + std::string filePrefix; + if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) + { + filePrefix = this->GetOption("CPACK_PACKAGE_FILE_NAME"); + filePrefix += "/"; + } + std::vector<std::string>::const_iterator fileIt; + for (fileIt = component->Files.begin(); fileIt != component->Files.end(); + ++fileIt ) + { + std::string rp = filePrefix + *fileIt; + cmCPackLogger(cmCPackLog::LOG_DEBUG,"Adding file: " + << rp << std::endl); + archive.Add(rp); + if (!archive) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, "ERROR while packaging files: " + << archive.GetError() + << std::endl); + return 0; + } + } + // Go back to previous dir + cmSystemTools::ChangeDirectory(dir.c_str()); + return 1; +} + +/* + * The macro will open/create a file 'filename' + * an declare and open the associated + * cmArchiveWrite 'archive' object. + */ +#define DECLARE_AND_OPEN_ARCHIVE(filename,archive) \ +cmGeneratedFileStream gf; \ +gf.Open(filename.c_str(), false, true); \ +if (!GenerateHeader(&gf)) \ + { \ + cmCPackLogger(cmCPackLog::LOG_ERROR, \ + "Problem to generate Header for archive < " \ + << filename \ + << ">." << std::endl); \ + return 0; \ + } \ +cmArchiveWrite archive(gf,this->Compress, this->Archive); \ +if (!archive) \ + { \ + cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem to create archive < " \ + << filename \ + << ">. ERROR =" \ + << archive.GetError() \ + << std::endl); \ + return 0; \ + } + +//---------------------------------------------------------------------- +int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup) +{ + packageFileNames.clear(); + // The default behavior is to have one package by component group + // unless CPACK_COMPONENTS_IGNORE_GROUP is specified. + if (!ignoreGroup) + { + std::map<std::string, cmCPackComponentGroup>::iterator compGIt; + for (compGIt=this->ComponentGroups.begin(); + compGIt!=this->ComponentGroups.end(); ++compGIt) + { + cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging component group: " + << compGIt->first + << std::endl); + // Begin the archive for this group + std::string packageFileName= std::string(toplevel); + packageFileName += "/"+ + GetComponentPackageFileName(this->GetOption("CPACK_PACKAGE_FILE_NAME"), + compGIt->first, + true) + + this->GetOutputExtension(); + // open a block in order to automatically close archive + // at the end of the block + { + DECLARE_AND_OPEN_ARCHIVE(packageFileName,archive); + // now iterate over the component of this group + std::vector<cmCPackComponent*>::iterator compIt; + for (compIt=(compGIt->second).Components.begin(); + compIt!=(compGIt->second).Components.end(); + ++compIt) + { + // Add the files of this component to the archive + addOneComponentToArchive(archive,*compIt); + } + } + // add the generated package to package file names list + packageFileNames.push_back(packageFileName); + } + // Handle Orphan components (components not belonging to any groups) + std::map<std::string, cmCPackComponent>::iterator compIt; + for (compIt=this->Components.begin(); + compIt!=this->Components.end(); ++compIt ) + { + // Does the component belong to a group? + if (compIt->second.Group==NULL) + { + cmCPackLogger(cmCPackLog::LOG_VERBOSE, + "Component <" + << compIt->second.Name + << "> does not belong to any group, package it separately." + << std::endl); + std::string localToplevel( + this->GetOption("CPACK_TEMPORARY_DIRECTORY") + ); + std::string packageFileName = std::string(toplevel); + + localToplevel += "/"+ compIt->first; + packageFileName += "/"+ + GetComponentPackageFileName(this->GetOption("CPACK_PACKAGE_FILE_NAME"), + compIt->first, + false) + + this->GetOutputExtension(); + { + DECLARE_AND_OPEN_ARCHIVE(packageFileName,archive); + // Add the files of this component to the archive + addOneComponentToArchive(archive,&(compIt->second)); + } + // add the generated package to package file names list + packageFileNames.push_back(packageFileName); + } + } + } + // CPACK_COMPONENTS_IGNORE_GROUPS is set + // We build 1 package per component + else + { + std::map<std::string, cmCPackComponent>::iterator compIt; + for (compIt=this->Components.begin(); + compIt!=this->Components.end(); ++compIt ) + { + std::string localToplevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY")); + std::string packageFileName = std::string(toplevel); + + localToplevel += "/"+ compIt->first; + packageFileName += "/"+ + GetComponentPackageFileName(this->GetOption("CPACK_PACKAGE_FILE_NAME"), + compIt->first, + false) + + this->GetOutputExtension(); + { + DECLARE_AND_OPEN_ARCHIVE(packageFileName,archive); + // Add the files of this component to the archive + addOneComponentToArchive(archive,&(compIt->second)); + } + // add the generated package to package file names list + packageFileNames.push_back(packageFileName); + } + } + return 1; +} + +//---------------------------------------------------------------------- +int cmCPackArchiveGenerator::PackageComponentsAllInOne() +{ + // reset the package file names + packageFileNames.clear(); + packageFileNames.push_back(std::string(toplevel)); + packageFileNames[0] += "/" + +std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME")) + + this->GetOutputExtension(); + cmCPackLogger(cmCPackLog::LOG_VERBOSE, + "Packaging all groups in one package..." + "(CPACK_COMPONENTS_ALL_GROUPS_IN_ONE_PACKAGE is set)" + << std::endl); + DECLARE_AND_OPEN_ARCHIVE(packageFileNames[0],archive); + + // The ALL COMPONENTS in ONE package case + std::map<std::string, cmCPackComponent>::iterator compIt; + for (compIt=this->Components.begin();compIt!=this->Components.end(); + ++compIt ) + { + // Add the files of this component to the archive + addOneComponentToArchive(archive,&(compIt->second)); + } + + // archive goes out of scope so it will finalized and closed. + return 1; +} + +//---------------------------------------------------------------------- +int cmCPackArchiveGenerator::PackageFiles() +{ + cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel: " + << toplevel << std::endl); + + if (WantsComponentInstallation()) { + // CASE 1 : COMPONENT ALL-IN-ONE package + // If ALL COMPONENTS in ONE package has been requested + // then the package file is unique and should be open here. + if (componentPackageMethod == ONE_PACKAGE) + { + return PackageComponentsAllInOne(); + } + // CASE 2 : COMPONENT CLASSICAL package(s) (i.e. not all-in-one) + // There will be 1 package for each component group + // however one may require to ignore component group and + // in this case you'll get 1 package for each component. + else + { + return PackageComponents(componentPackageMethod == + ONE_PACKAGE_PER_COMPONENT); + } + } + + // CASE 3 : NON COMPONENT package. + DECLARE_AND_OPEN_ARCHIVE(packageFileNames[0],archive); + std::vector<std::string>::const_iterator fileIt; + std::string dir = cmSystemTools::GetCurrentWorkingDirectory(); + cmSystemTools::ChangeDirectory(toplevel.c_str()); + for ( fileIt = files.begin(); fileIt != files.end(); ++ fileIt ) + { + // Get the relative path to the file + std::string rp = cmSystemTools::RelativePath(toplevel.c_str(), + fileIt->c_str()); + archive.Add(rp); + if(!archive) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem while adding file< " + << *fileIt + << "> to archive <" + << packageFileNames[0] << "> .ERROR =" + << archive.GetError() + << std::endl); + return 0; + } + } + cmSystemTools::ChangeDirectory(dir.c_str()); + // The destructor of cmArchiveWrite will close and finish the write + return 1; +} + +//---------------------------------------------------------------------- +int cmCPackArchiveGenerator::GenerateHeader(std::ostream*) +{ + return 1; +} + +bool cmCPackArchiveGenerator::SupportsComponentInstallation() const { + // The Component installation support should only + // be activated if explicitly requested by the user + // (for backward compatibility reason) + if (IsOn("CPACK_ARCHIVE_COMPONENT_INSTALL")) + { + return true; + } + else + { + return false; + } +} |