Browse Source

ENH: Recurse subdirectories

Andy Cedilnik 22 years ago
parent
commit
274535d366
4 changed files with 64 additions and 4 deletions
  1. 8 2
      Source/cmFileCommand.cxx
  2. 7 1
      Source/cmFileCommand.h
  3. 38 1
      Source/cmGlob.cxx
  4. 11 0
      Source/cmGlob.h

+ 8 - 2
Source/cmFileCommand.cxx

@@ -41,7 +41,11 @@ bool cmFileCommand::InitialPass(std::vector<std::string> const& args)
     }
   else if ( subCommand == "GLOB" )
     {
-    return this->HandleGlobCommand(args);
+    return this->HandleGlobCommand(args, false);
+    }
+  else if ( subCommand == "GLOB_RECURSE" )
+    {
+    return this->HandleGlobCommand(args, true);
     }
   else if ( subCommand == "MAKE_DIRECTORY" )
     {
@@ -135,7 +139,8 @@ bool cmFileCommand::HandleReadCommand(std::vector<std::string> const& args)
 }
 
 //----------------------------------------------------------------------------
-bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args)
+bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args,
+  bool recurse)
 {
   if ( args.size() < 2 )
     {
@@ -150,6 +155,7 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args)
   std::string variable = *i;
   i++;
   cmGlob g;
+  g.SetRecurse(recurse);
   std::string output = "";
   bool first = true;
   for ( ; i != args.end(); ++i )

+ 7 - 1
Source/cmFileCommand.h

@@ -70,6 +70,7 @@ public:
       "  FILE(APPEND filename \"message to write\"... )\n"
       "  FILE(READ filename variable)\n"
       "  FILE(GLOB variable [globbing expressions]...)\n"
+      "  FILE(GLOB_RECURSE variable [globbing expressions]...)\n"
       "WRITE will write a message into a file called 'filename'. It "
       "overwrites the file if it already exists, and creates the file "
       "if it does not exists.\n"
@@ -84,6 +85,11 @@ public:
       "   *.cxx      - match all files with extension cxx\n"
       "   *.vt?      - match all files with extension vta, vtb, ... vtz\n"
       "   f[3-5].txt - match files f3.txt, f4.txt, f5.txt\n"
+      "GLOB_RECURSE will generate similar list as the regular GLOB, except "
+      "it will traverse all the subdirectories of the matched directory and "
+      "match the files.\n"
+      "Example of recursive globbing:\n"
+      "   /dir/*.py  - match all python files /dir and subdirectories\n"
       "MAKE_DIRECTORY will create a directory at the specified location"; 
     }
   
@@ -92,7 +98,7 @@ public:
 protected:
   bool HandleWriteCommand(std::vector<std::string> const& args, bool append);
   bool HandleReadCommand(std::vector<std::string> const& args);
-  bool HandleGlobCommand(std::vector<std::string> const& args);
+  bool HandleGlobCommand(std::vector<std::string> const& args, bool recurse);
   bool HandleMakeDirectoryCommand(std::vector<std::string> const& args);
 };
 

+ 38 - 1
Source/cmGlob.cxx

@@ -32,6 +32,7 @@ public:
 cmGlob::cmGlob()
 {
   m_Internals = new cmGlobInternal;
+  m_Recurse = false;
 }
 
 cmGlob::~cmGlob()
@@ -137,9 +138,46 @@ std::string cmGlob::ConvertExpression(const std::string& expr)
   return res + "$";
 }
 
+void cmGlob::RecurseDirectory(const std::string& dir, bool dir_only)
+{
+  cmsys::Directory d;
+  if ( !d.Load(dir.c_str()) )
+    {
+    return;
+    }
+  unsigned long cc;
+  std::string fullname;
+  for ( cc = 0; cc < d.GetNumberOfFiles(); cc ++ )
+    {
+    if ( strcmp(d.GetFile(cc), ".") == 0 ||
+      strcmp(d.GetFile(cc), "..") == 0  )
+      {
+      continue;
+      }
+    fullname = dir + "/" + d.GetFile(cc);
+    if ( !dir_only || !cmsys::SystemTools::FileIsDirectory(fullname.c_str()) )
+      {
+      if ( m_Internals->Expressions[m_Internals->Expressions.size()-1].find(d.GetFile(cc)) )
+        {
+        m_Internals->Files.push_back(fullname);
+        }
+      }
+    if ( cmsys::SystemTools::FileIsDirectory(fullname.c_str()) )
+      {
+      this->RecurseDirectory(fullname, dir_only);
+      }
+    }
+}
+
 void cmGlob::ProcessDirectory(std::string::size_type start, 
   const std::string& dir, bool dir_only)
 {
+  bool last = ( start == m_Internals->Expressions.size()-1 );
+  if ( last && m_Recurse )
+    {
+    this->RecurseDirectory(dir, dir_only);
+    return;
+    }
   cmsys::Directory d;
   if ( !d.Load(dir.c_str()) )
     {
@@ -147,7 +185,6 @@ void cmGlob::ProcessDirectory(std::string::size_type start,
     }
   unsigned long cc;
   std::string fullname;
-  bool last = ( start == m_Internals->Expressions.size()-1 );
   for ( cc = 0; cc < d.GetNumberOfFiles(); cc ++ )
     {
     if ( strcmp(d.GetFile(cc), ".") == 0 ||

+ 11 - 0
Source/cmGlob.h

@@ -38,11 +38,21 @@ public:
   //! Return the list of files that matched.
   std::vector<std::string>& GetFiles();
 
+  //! Set recurse to true to match subdirectories.
+  void RecurseOn() { this->SetRecurse(true); }
+  void RecurseOff() { this->SetRecurse(false); }
+  void SetRecurse(bool i) { m_Recurse = i; }
+  bool GetRecurse() { return m_Recurse; }
+
 protected:
   //! Process directory
   void ProcessDirectory(std::string::size_type start, 
     const std::string& dir, bool dir_only);
 
+  //! Process last directory, but only when recurse flags is on. That is
+  // effectively like saying: /path/to/file/**/file
+  void RecurseDirectory(const std::string& dir, bool dir_only);
+
   //! Escape all non-alphanumeric characters in pattern.
   void Escape(int ch, char* buffer);
 
@@ -55,6 +65,7 @@ protected:
   void AddExpression(const char* expr);
 
   cmGlobInternal* m_Internals;
+  bool m_Recurse;
 };