From 6ce54b7de5a734824441be469993fa17f1f2fc55 Mon Sep 17 00:00:00 2001
From: Eric NOULARD <eric.noulard@gmail.com>
Date: Tue, 3 Aug 2010 22:54:58 +0200
Subject: [PATCH 3/3] CPack   enable generators to produce more than one package (part2)

Add component support for ArchiveGenerators. In this patch
Only the 1 component == 1 package is supported.
The 1 component group == 1 package will come in another patch.
(there is already some code for that but it is unfinished)
---
 Source/CPack/cmCPackArchiveGenerator.cxx |  116 +++++++++++++++++++++++++++---
 Source/CPack/cmCPackArchiveGenerator.h   |    3 +
 Source/CPack/cmCPackGenerator.cxx        |    6 +-
 Source/CPack/cmCPackSTGZGenerator.cxx    |   40 ++++++++--
 4 files changed, 143 insertions(+), 22 deletions(-)

diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx
index 42a7552..7452044 100644
--- a/Source/CPack/cmCPackArchiveGenerator.cxx
+++ b/Source/CPack/cmCPackArchiveGenerator.cxx
@@ -22,6 +22,7 @@
 #include <errno.h>
 
 #include <cmsys/SystemTools.hxx>
+#include <cmsys/Directory.hxx>
 #include <cmlibarchive/libarchive/archive.h>
 #include <cmlibarchive/libarchive/archive_entry.h>
 
@@ -166,10 +167,6 @@ int cmCPackArchiveGenerator::InitializeInternal()
   return this->Superclass::InitializeInternal();
 }
 
-int cmCPackArchiveGenerator::CompressFiles(const char* outFileName,
-  const char* toplevel, const std::vector<std::string>& files, std::list<std::string>& packageFileNames)
-{
-  int res = ARCHIVE_OK;
 #define CHECK_ARCHIVE_ERROR(res, msg)           \
   if(res != ARCHIVE_OK)                         \
     {\
@@ -179,8 +176,15 @@ int cmCPackArchiveGenerator::CompressFiles(const char* outFileName,
                   << " " << res                   \
                   << "\n");                       \
     }
-  cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel: "
-                << (toplevel ? toplevel : "(NULL)") << std::endl);
+
+int cmCPackArchiveGenerator::CompressOneSetOfFiles(const char* outFileName,
+  const char* toplevel, const std::vector<std::string>& files)
+{
+  cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel (C1): "
+                << (toplevel ? toplevel : "(NULL)")
+                << ", outFileName = " << outFileName
+                << std::endl);
+  int res = ARCHIVE_OK;
   // create a new archive
   struct archive* a = archive_write_new();
   // Set the compress and archive types for the archive
@@ -193,7 +197,7 @@ int cmCPackArchiveGenerator::CompressFiles(const char* outFileName,
   res = archive_write_open(a,
                            &data,
                            OpenArchive,
-                           WriteArchive, 
+                           WriteArchive,
                            CloseArchive);
   CHECK_ARCHIVE_ERROR(res, "archive_write_open:");
   // create a new disk struct
@@ -210,9 +214,17 @@ int cmCPackArchiveGenerator::CompressFiles(const char* outFileName,
     // create a new entry for each file
     struct archive_entry *entry = archive_entry_new();
     // Get the relative path to the file
-    std::string rp = cmSystemTools::RelativePath(toplevel, fileIt->c_str());
+    std::string rp;
+    if (cmSystemTools::FileIsFullPath(fileIt->c_str()))
+      {
+      rp = cmSystemTools::RelativePath(toplevel, fileIt->c_str());
+      }
+    else
+      {
+      rp = (*fileIt);
+      }
     // Set the name of the entry to the file name
-    archive_entry_set_pathname(entry, rp.c_str());  
+    archive_entry_set_pathname(entry, rp.c_str());
     res = archive_read_disk_entry_from_file(disk, entry, -1, 0);
     CHECK_ARCHIVE_ERROR(res, "archive_read_disk_entry_from_file:");
     // write  entry header
@@ -225,7 +237,7 @@ int cmCPackArchiveGenerator::CompressFiles(const char* outFileName,
       FILE* file = fopen(fileIt->c_str(), "rb");
       if(!file)
         {
-        cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem with fopen(): " 
+        cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem with fopen(): "
                       << fileIt->c_str()
                       << strerror(errno)
                       << std::endl);
@@ -238,7 +250,7 @@ int cmCPackArchiveGenerator::CompressFiles(const char* outFileName,
         size_t wlen = archive_write_data(a, buff, len);
         if(wlen != len)
           {
-          cmCPackLogger(cmCPackLog::LOG_ERROR, "archive_write_data(): " 
+          cmCPackLogger(cmCPackLog::LOG_ERROR, "archive_write_data(): "
                         << "tried to write " << len  << "\n"
                         << "write " << wlen << "\n");
           return 0;
@@ -258,8 +270,90 @@ int cmCPackArchiveGenerator::CompressFiles(const char* outFileName,
   return 1;
 }
 
+int cmCPackArchiveGenerator::CompressFiles(const char* outFileName,
+  const char* toplevel, const std::vector<std::string>& files,
+  std::list<std::string>& packageFileNames)
+{
+  int res = 0;
+  cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel: "
+                << (toplevel ? toplevel : "(NULL)") << std::endl);
+  packageFileNames.clear();
+  // FIXME this is temporary because the idea of
+  // 1 component == 1 package file is not "that" easy to do
+  this->SetOption("CPACK_COMPONENT_IGNORE_COMPONENT_GROUP","1");
+  // The default behavior is to have one package by component group
+  // unless CPACK_COMPONENT_IGNORE_COMPONENT_GROUP is specified.
+  if ((!this->ComponentGroups.empty()) &&
+      (!this->GetOption("CPACK_COMPONENT_IGNORE_COMPONENT_GROUP")))
+    {
+    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);
+      std::vector<std::string> filesInPackage;
+      // 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)
+        {
+        cmCPackLogger(cmCPackLog::LOG_VERBOSE, "   - packaging component: "
+                                       << (*compIt)->Name
+                                       << std::endl);
+        // Add the file
+        filesInPackage.insert(filesInPackage.begin(),
+                              (*compIt)->Files.begin(),
+                              (*compIt)->Files.end());
+        }
+      // now create the package file for this component group
+      std::string localToplevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
+      std::string packageFileName(toplevel);
+
+      }
+    }
+  else if (!this->Components.empty())
+    {
+    std::map<std::string, cmCPackComponent>::iterator compIt;
+    for (compIt=this->Components.begin();compIt!=this->Components.end(); ++compIt )
+      {
+      cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging component: "
+                                     << compIt->first
+                                     << std::endl);
+      std::string localToplevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
+      std::string packageFileName(toplevel);
+
+      localToplevel += "/"+ compIt->first;
+      packageFileName += "/"+std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME"))+"-"+compIt->first + this->GetOutputExtension();
+      res = CompressOneSetOfFiles(packageFileName.c_str(),localToplevel.c_str(),(compIt->second).Files);
+      if (0==res)
+        {
+        cmCPackLogger(cmCPackLog::LOG_ERROR, "Failed to package component: "
+                              << compIt->first
+                              << std::endl);
+        break;
+        }
+      else
+        {
+        packageFileNames.push_back(packageFileName);
+        }
+      }
+    }
+  else
+    {
+    res = CompressOneSetOfFiles(outFileName,toplevel,files);
+    }
+  return res;
+}
+
 //----------------------------------------------------------------------
 int cmCPackArchiveGenerator::GenerateHeader(std::ostream*)
 {
   return 1;
 }
+
+bool cmCPackArchiveGenerator::SupportsComponentInstallation() const {
+  return true;
+}
diff --git a/Source/CPack/cmCPackArchiveGenerator.h b/Source/CPack/cmCPackArchiveGenerator.h
index 19b939e..20ea4b4 100644
--- a/Source/CPack/cmCPackArchiveGenerator.h
+++ b/Source/CPack/cmCPackArchiveGenerator.h
@@ -39,7 +39,10 @@ protected:
   virtual int InitializeInternal();
   int CompressFiles(const char* outFileName, const char* toplevel,
     const std::vector<std::string>& files, std::list<std::string>& packageFileNames);
+  int CompressOneSetOfFiles(const char* outFileName,
+    const char* toplevel, const std::vector<std::string>& files);
   virtual const char* GetOutputExtension() = 0;
+  virtual bool SupportsComponentInstallation() const;
   CompressType Compress;
   ArchiveType Archive;
 };
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
index d90a375..5d5ada5 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -912,9 +912,6 @@ int cmCPackGenerator::DoPackage()
                       << " to "
                       << (packageFileName ? packageFileName : "(NULL)")
                       << std::endl);
-      cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Created package: "
-                            << cmSystemTools::GetFilenameName(*it)
-                            << std::endl);
       if ( !cmSystemTools::CopyFileIfDifferent(tempPackageFileName,
               packageFileName) )
             {
@@ -925,6 +922,9 @@ int cmCPackGenerator::DoPackage()
                           << std::endl);
             return 0;
             }
+      cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Component package: "
+                            << packageFileName
+                            << " generated." << std::endl);
       }
     }
   else
diff --git a/Source/CPack/cmCPackSTGZGenerator.cxx b/Source/CPack/cmCPackSTGZGenerator.cxx
index 1ca063d..04c179f 100644
--- a/Source/CPack/cmCPackSTGZGenerator.cxx
+++ b/Source/CPack/cmCPackSTGZGenerator.cxx
@@ -53,23 +53,47 @@ int cmCPackSTGZGenerator::InitializeInternal()
 
 //----------------------------------------------------------------------
 int cmCPackSTGZGenerator::CompressFiles(const char* outFileName,
-  const char* toplevel, const std::vector<std::string>& files, std::list<std::string>& packageFileNames)
+  const char* toplevel, const std::vector<std::string>& files,
+  std::list<std::string>& packageFileNames)
 {
+  bool res=true;
   if ( !this->Superclass::CompressFiles(outFileName, toplevel, files, packageFileNames) )
     {
     return 0;
     }
-  return cmSystemTools::SetPermissions(outFileName,
+  if (packageFileNames.size()>0)
+    {std::list<std::string>::iterator it;
+     for (it=packageFileNames.begin(); it!=packageFileNames.end();++it)
+       {
+       res = res &
+           cmSystemTools::SetPermissions((*it).c_str(),
+           #if defined( _MSC_VER ) || defined( __MINGW32__ )
+                 S_IREAD | S_IWRITE | S_IEXEC
+           #elif defined( __BORLANDC__ )
+                 S_IRUSR | S_IWUSR | S_IXUSR
+           #else
+                 S_IRUSR | S_IWUSR | S_IXUSR |
+                 S_IRGRP | S_IWGRP | S_IXGRP |
+                 S_IROTH | S_IWOTH | S_IXOTH
+           #endif
+           );
+       }
+    }
+  else
+    {
+    res = cmSystemTools::SetPermissions(outFileName,
 #if defined( _MSC_VER ) || defined( __MINGW32__ )
-    S_IREAD | S_IWRITE | S_IEXEC
+      S_IREAD | S_IWRITE | S_IEXEC
 #elif defined( __BORLANDC__ )
-    S_IRUSR | S_IWUSR | S_IXUSR
+      S_IRUSR | S_IWUSR | S_IXUSR
 #else
-    S_IRUSR | S_IWUSR | S_IXUSR |
-    S_IRGRP | S_IWGRP | S_IXGRP |
-    S_IROTH | S_IWOTH | S_IXOTH
+      S_IRUSR | S_IWUSR | S_IXUSR |
+      S_IRGRP | S_IWGRP | S_IXGRP |
+      S_IROTH | S_IWOTH | S_IXOTH
 #endif
-  );
+    );
+    }
+  return res;
 }
 
 //----------------------------------------------------------------------
-- 
1.7.1

