From 4890f30cd9e2008d3e6cc62c93fbfa062f237267 Mon Sep 17 00:00:00 2001
From: Domen Vrankar <domen.vrankar@gmail.com>
Date: Sun, 1 Mar 2015 22:35:37 +0100
Subject: [PATCH] Glob: Add support for directory listing

Glob now supports listing of directories in recursive mode and disabling
listing of directories in non recursive mode.  In recursive mode when
directory listing is enabled directory symlinks are also listed.  For
backward compatibility there is a separate flag for recursive and
non-recursive globbing mode as this functionality was previously
inconsistent.

Change-Id: I6099c0c568a04caf7c9a36a5d476390371115790
---
 Glob.cxx    | 18 +++++++++++++++++-
 Glob.hxx.in | 11 +++++++++++
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/Glob.cxx b/Glob.cxx
index 17d551b..11bfd16 100644
--- a/Glob.cxx
+++ b/Glob.cxx
@@ -69,6 +69,10 @@ Glob::Glob()
     // RecurseThroughSymlinks is true by default for backwards compatibility,
     // not because it's a good idea...
   this->FollowedSymlinkCount = 0;
+
+  // Keep separate variables for directory listing for back compatibility
+  this->ListDirs = true;
+  this->RecurseListDirs = false;
 }
 
 //----------------------------------------------------------------------------
@@ -277,6 +281,12 @@ bool Glob::RecurseDirectory(kwsys_stl::string::size_type start,
             this->VisitedSymlinks.end(),
             canonicalPath) == this->VisitedSymlinks.end())
           {
+          if(this->RecurseListDirs)
+            {
+            // symlinks are treated as directories
+            this->AddFile(this->Internals->Files, realname);
+            }
+
           this->VisitedSymlinks.push_back(canonicalPath);
           if(!this->RecurseDirectory(start+1, realname, messages))
             {
@@ -304,6 +314,10 @@ bool Glob::RecurseDirectory(kwsys_stl::string::size_type start,
         }
       else
         {
+        if(this->RecurseListDirs)
+          {
+          this->AddFile(this->Internals->Files, realname);
+          }
         if(!this->RecurseDirectory(start+1, realname, messages))
           {
           return false;
@@ -375,7 +389,9 @@ void Glob::ProcessDirectory(kwsys_stl::string::size_type start,
     // << this->Internals->TextExpressions[start].c_str() << kwsys_ios::endl;
     //kwsys_ios::cout << "Real name: " << realname << kwsys_ios::endl;
 
-    if( !last && !kwsys::SystemTools::FileIsDirectory(realname) )
+    if( (!last && !kwsys::SystemTools::FileIsDirectory(realname))
+      || (!this->ListDirs && last &&
+          kwsys::SystemTools::FileIsDirectory(realname)) )
       {
       continue;
       }
diff --git a/Glob.hxx.in b/Glob.hxx.in
index 0d40d02..39b7ce7 100644
--- a/Glob.hxx.in
+++ b/Glob.hxx.in
@@ -105,6 +105,15 @@ public:
                                           bool require_whole_string = true,
                                           bool preserve_case = false);
 
+  /** Getters and setters for enabling and disabling directory
+      listing in recursive and non recursive globbing mode.
+      If listing is enabled in recursive mode it also lists
+      directory symbolic links even if follow symlinks is enabled. */
+  void SetListDirs(bool list) { this->ListDirs=list; }
+  bool GetListDirs() const { return this->ListDirs; }
+  void SetRecurseListDirs(bool list) { this->RecurseListDirs=list; }
+  bool GetRecurseListDirs() const { return this->RecurseListDirs; }
+
 protected:
   //! Process directory
   void ProcessDirectory(kwsys_stl::string::size_type start,
@@ -129,6 +138,8 @@ protected:
   bool RecurseThroughSymlinks;
   unsigned int FollowedSymlinkCount;
   kwsys_stl::vector<kwsys_stl::string> VisitedSymlinks;
+  bool ListDirs;
+  bool RecurseListDirs;
 
 private:
   Glob(const Glob&);  // Not implemented.
-- 
GitLab