[PATCH] Added possibility to force inclusion of directory entries =

Jakub Zakrzewski jzakrzewski at e2e.ch
Thu Jan 19 11:21:18 EST 2012


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 apropriat=
e 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/cmCPac=
kArchiveGenerator.cxx
index 0ce5b01..803ff64 100644
--- a/Source/CPack/cmCPackArchiveGenerator.cxx
+++ b/Source/CPack/cmCPackArchiveGenerator.cxx
@@ -57,6 +57,21 @@ int cmCPackArchiveGenerator::addOneComponentToArchive(cm=
ArchiveWrite& archive,
   std::string dir =3D cmSystemTools::GetCurrentWorkingDirectory();
   // Change to local toplevel
   cmSystemTools::ChangeDirectory(localToplevel.c_str());
+  std::set<std::string>::const_iterator dirIt;
+  for (dirIt =3D component->DirectoryEntries.begin(); dirIt !=3D 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 director=
y entries: "
+            << archive.GetError()
+            << std::endl);
+      return 0;
+      }
+    }
   std::vector<std::string>::const_iterator fileIt;
   for (fileIt =3D component->Files.begin(); fileIt !=3D component->Files.e=
nd();
        ++fileIt )
@@ -264,6 +279,49 @@ int cmCPackArchiveGenerator::PackageFiles()
   std::vector<std::string>::const_iterator fileIt;
   std::string dir =3D cmSystemTools::GetCurrentWorkingDirectory();
   cmSystemTools::ChangeDirectory(toplevel.c_str());
+  bool packageDirEntries =3D this->IsOn("CPACK_ARCHIVE_INCLUDE_DIRECTORY_E=
NTRIES");
+  if(packageDirEntries)
+    {
+
+    std::set<std::string> directoryEntries;
+    for ( fileIt =3D files.begin(); fileIt !=3D files.end(); ++ fileIt )
+      {
+      // Get the relative path to the file
+      std::string localDirName =3D cmSystemTools::RelativePath(toplevel.c_=
str(),
+                                                   fileIt->c_str());
+      bool stop =3D true;
+      do
+        {
+        size_t lastSeparatorPosition =3D localDirName.find_last_of('/');
+        if(lastSeparatorPosition < localDirName.size())
+          {
+          localDirName.resize(lastSeparatorPosition);
+          stop =3D !directoryEntries.insert(localDirName).second;
+          }
+        else
+          {
+          stop =3D true;
+          }
+        }
+      while (!stop);
+      }
+
+    std::set<std::string>::const_iterator dirIt;
+    for (dirIt =3D directoryEntries.begin(); dirIt !=3D directoryEntries.e=
nd(); ++dirIt )
+      {
+      cmCPackLogger(cmCPackLog::LOG_DEBUG,"Adding directory entry: "
+                    << (*dirIt) << std::endl);
+      archive.AddDirEntry(*dirIt);
+      if (!archive)
+        {
+        cmCPackLogger(cmCPackLog::LOG_ERROR, "ERROR while packaging direct=
ory entries: "
+              << archive.GetError()
+              << std::endl);
+        return 0;
+        }
+      }
+    }
+
   for ( fileIt =3D files.begin(); fileIt !=3D files.end(); ++ fileIt )
     {
     // Get the relative path to the file
diff --git a/Source/CPack/cmCPackComponentGroup.h b/Source/CPack/cmCPackCom=
ponentGroup.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;
=20
+  /// 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=20
   /// component was installed.
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenera=
tor.cxx
index 083279f..24925c1 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -842,7 +842,10 @@ int cmCPackGenerator::InstallProjectViaInstallCMakePro=
jects(
                   result.begin());
=20
           std::vector<std::string>::iterator fit;
+
           std::string localFileName;
+          std::string localDirName;
+          bool packageDirEntries =3D this->IsOn("CPACK_ARCHIVE_INCLUDE_DIR=
ECTORY_ENTRIES");
           // Populate the File field of each component
           for (fit=3Dresult.begin();fit!=3Ddiff;++fit)
             {
@@ -851,6 +854,25 @@ int cmCPackGenerator::InstallProjectViaInstallCMakePro=
jects(
             localFileName =3D
                 localFileName.substr(localFileName.find('/')+1,
                                      std::string::npos);
+            if(packageDirEntries)
+              {
+              localDirName =3D localFileName;
+              bool stop =3D true;
+              do
+                {
+                size_t lastSeparatorPosition =3D localDirName.find_last_of=
('/');
+                if(lastSeparatorPosition < localDirName.size())
+                  {
+                  localDirName.resize(lastSeparatorPosition);
+                  stop =3D !Components[installComponent].DirectoryEntries.=
insert(localDirName).second;
+                  }
+                else
+                  {
+                  stop =3D 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)
 }
=20
 //------------------------------------------------------------------------=
----
+bool cmArchiveWrite::AddDirEntry(std::string path, size_t skip, const char=
* prefix)
+{
+  if(this->Okay())
+    {
+    if(!path.empty() && path[path.size()-1] =3D=3D '/')
+      {
+      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 =3D 0, const char* prefix =3D 0);
=20
+  /**
+   * 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 =3D 0, const char* prefix=
 =3D 0);
+
   /** Returns true if there has been no error.  */
   operator safe_bool() const
     { return this->Okay()? &cmArchiveWrite::safe_bool_true : 0; }
--=20
1.7.7




More information about the CMake mailing list