We needed directory entries explicitly listed in zip file headers, so I created 
this patch.
It DOES NOT solve the issue with empty directories. It knows what directories 
to include by analyzing file paths during addition to archive.
===========================================================================================


>From 700075de0d05042a10074ad9e24995c6a9087e1e Mon Sep 17 00:00:00 2001
From: Jakub Zakrzewski <[email protected]>
Date: Thu, 19 Jan 2012 17:21:18 +0100
Subject: [PATCH] Added possibility to force inclusion of directory entries in
 achive files (zip, tgz...)

In normal case only files were added to archive file filelist.
Due to some legancy requirements it may be necessary to have also apropriate 
entries
for directories theirselves, so instead of having only entry for 
'dir/dir2/file.txt'
one may want to have three entries:
* 'dir/'
* 'dir/dir2/'
* 'dir/dir2/file.txt'

To achieve this simply set variable CPACK_ARCHIVE_INCLUDE_DIRECTORY_ENTRIES to 
ON.
---
 Source/CPack/cmCPackArchiveGenerator.cxx |   58 ++++++++++++++++++++++++++++++
 Source/CPack/cmCPackComponentGroup.h     |    3 ++
 Source/CPack/cmCPackGenerator.cxx        |   22 +++++++++++
 Source/cmArchiveWrite.cxx                |   14 +++++++
 Source/cmArchiveWrite.h                  |   11 ++++++
 5 files changed, 108 insertions(+), 0 deletions(-)

diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx 
b/Source/CPack/cmCPackArchiveGenerator.cxx
index 0ce5b01..803ff64 100644
--- a/Source/CPack/cmCPackArchiveGenerator.cxx
+++ b/Source/CPack/cmCPackArchiveGenerator.cxx
@@ -57,6 +57,21 @@ int 
cmCPackArchiveGenerator::addOneComponentToArchive(cmArchiveWrite& archive,
   std::string dir = cmSystemTools::GetCurrentWorkingDirectory();
   // Change to local toplevel
   cmSystemTools::ChangeDirectory(localToplevel.c_str());
+  std::set<std::string>::const_iterator dirIt;
+  for (dirIt = component->DirectoryEntries.begin(); dirIt != 
component->DirectoryEntries.end();
+       ++dirIt )
+    {
+    cmCPackLogger(cmCPackLog::LOG_DEBUG,"Adding directory entry: "
+                  << (*dirIt) << std::endl);
+    archive.AddDirEntry(*dirIt);
+    if (!archive)
+      {
+      cmCPackLogger(cmCPackLog::LOG_ERROR, "ERROR while packaging directory 
entries: "
+            << archive.GetError()
+            << std::endl);
+      return 0;
+      }
+    }
   std::vector<std::string>::const_iterator fileIt;
   for (fileIt = component->Files.begin(); fileIt != component->Files.end();
        ++fileIt )
@@ -264,6 +279,49 @@ int cmCPackArchiveGenerator::PackageFiles()
   std::vector<std::string>::const_iterator fileIt;
   std::string dir = cmSystemTools::GetCurrentWorkingDirectory();
   cmSystemTools::ChangeDirectory(toplevel.c_str());
+  bool packageDirEntries = 
this->IsOn("CPACK_ARCHIVE_INCLUDE_DIRECTORY_ENTRIES");
+  if(packageDirEntries)
+    {
+
+    std::set<std::string> directoryEntries;
+    for ( fileIt = files.begin(); fileIt != files.end(); ++ fileIt )
+      {
+      // Get the relative path to the file
+      std::string localDirName = cmSystemTools::RelativePath(toplevel.c_str(),
+                                                   fileIt->c_str());
+      bool stop = true;
+      do
+        {
+        size_t lastSeparatorPosition = localDirName.find_last_of('/');
+        if(lastSeparatorPosition < localDirName.size())
+          {
+          localDirName.resize(lastSeparatorPosition);
+          stop = !directoryEntries.insert(localDirName).second;
+          }
+        else
+          {
+          stop = true;
+          }
+        }
+      while (!stop);
+      }
+
+    std::set<std::string>::const_iterator dirIt;
+    for (dirIt = directoryEntries.begin(); dirIt != directoryEntries.end(); 
++dirIt )
+      {
+      cmCPackLogger(cmCPackLog::LOG_DEBUG,"Adding directory entry: "
+                    << (*dirIt) << std::endl);
+      archive.AddDirEntry(*dirIt);
+      if (!archive)
+        {
+        cmCPackLogger(cmCPackLog::LOG_ERROR, "ERROR while packaging directory 
entries: "
+              << archive.GetError()
+              << std::endl);
+        return 0;
+        }
+      }
+    }
+
   for ( fileIt = files.begin(); fileIt != files.end(); ++ fileIt )
     {
     // Get the relative path to the file
diff --git a/Source/CPack/cmCPackComponentGroup.h 
b/Source/CPack/cmCPackComponentGroup.h
index cebdd6d..c0b71e2 100644
--- a/Source/CPack/cmCPackComponentGroup.h
+++ b/Source/CPack/cmCPackComponentGroup.h
@@ -89,6 +89,9 @@ public:
   /// The list of installed directories that are part of this component.
   std::vector<std::string> Directories;
 
+  /// The list of directory entries that are to be put into archive.
+  std::set<std::string> DirectoryEntries;
+
   /// Get the total installed size of all of the files in this
   /// component, in bytes. installDir is the directory into which the 
   /// component was installed.
diff --git a/Source/CPack/cmCPackGenerator.cxx 
b/Source/CPack/cmCPackGenerator.cxx
index 083279f..24925c1 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -842,7 +842,10 @@ int 
cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
                   result.begin());
 
           std::vector<std::string>::iterator fit;
+
           std::string localFileName;
+          std::string localDirName;
+          bool packageDirEntries = 
this->IsOn("CPACK_ARCHIVE_INCLUDE_DIRECTORY_ENTRIES");
           // Populate the File field of each component
           for (fit=result.begin();fit!=diff;++fit)
             {
@@ -851,6 +854,25 @@ int 
cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
             localFileName =
                 localFileName.substr(localFileName.find('/')+1,
                                      std::string::npos);
+            if(packageDirEntries)
+              {
+              localDirName = localFileName;
+              bool stop = true;
+              do
+                {
+                size_t lastSeparatorPosition = localDirName.find_last_of('/');
+                if(lastSeparatorPosition < localDirName.size())
+                  {
+                  localDirName.resize(lastSeparatorPosition);
+                  stop = 
!Components[installComponent].DirectoryEntries.insert(localDirName).second;
+                  }
+                else
+                  {
+                  stop = true;
+                  }
+                }
+              while (!stop && !localDirName.empty());
+              }
             Components[installComponent].Files.push_back(localFileName);
             cmCPackLogger(cmCPackLog::LOG_DEBUG, "Adding file <"
                                 <<localFileName<<"> to component <"
diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx
index dc6b749..c79f9d5 100644
--- a/Source/cmArchiveWrite.cxx
+++ b/Source/cmArchiveWrite.cxx
@@ -173,6 +173,20 @@ bool cmArchiveWrite::Add(std::string path, size_t skip, 
const char* prefix)
 }
 
 //----------------------------------------------------------------------------
+bool cmArchiveWrite::AddDirEntry(std::string path, size_t skip, const char* 
prefix)
+{
+  if(this->Okay())
+    {
+    if(!path.empty() && path[path.size()-1] == '/')
+      {
+      path.erase(path.size()-1);
+      }
+    this->AddFile(path.c_str(), skip, prefix);
+    }
+  return this->Okay();
+}
+
+//----------------------------------------------------------------------------
 bool cmArchiveWrite::AddPath(const char* path,
                              size_t skip, const char* prefix)
 {
diff --git a/Source/cmArchiveWrite.h b/Source/cmArchiveWrite.h
index 3e3b2f0..4b2e81c 100644
--- a/Source/cmArchiveWrite.h
+++ b/Source/cmArchiveWrite.h
@@ -59,6 +59,17 @@ public:
    */
   bool Add(std::string path, size_t skip = 0, const char* prefix = 0);
 
+  /**
+   * Add a directory entry to the archive.  This causes the archive to
+   * store additional information about directories and not only
+   * abot their content.  The "path" must be readable on disk, either
+   * full path or relative to current working directory.  The "skip"
+   * value indicates how many leading bytes from the input path to
+   * skip.  The remaining part of the input path is appended to the
+   * "prefix" value to construct the final name in the archive.
+   */
+  bool AddDirEntry(std::string path, size_t skip = 0, const char* prefix = 0);
+
   /** Returns true if there has been no error.  */
   operator safe_bool() const
     { return this->Okay()? &cmArchiveWrite::safe_bool_true : 0; }
-- 
1.7.7


--

Powered by www.kitware.com

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Please keep messages on-topic and check the CMake FAQ at: 
http://www.cmake.org/Wiki/CMake_FAQ

Follow this link to subscribe/unsubscribe:
http://www.cmake.org/mailman/listinfo/cmake

Reply via email to