KWSys 2015-03-03 (4890f30c)

Extract upstream KWSys using the following shell commands.

$ git archive --prefix=upstream-kwsys/ 4890f30c | tar x
$ git shortlog --no-merges --abbrev=8 --format='%h %s' d2aa1afd..4890f30c
Domen Vrankar (2):
      5d6204e9 Glob: Handle symlink cycles in directory paths
      4890f30c Glob: Add support for directory listing

Change-Id: Id8b77dabf8f50efeffdeaf1c826154fd2a25e17b
This commit is contained in:
KWSys Robot 2015-03-03 08:50:09 -05:00 committed by Brad King
parent 7c9afb5738
commit aa84d26e63
2 changed files with 124 additions and 16 deletions

View File

@ -19,6 +19,7 @@
#include KWSYS_HEADER(Directory.hxx) #include KWSYS_HEADER(Directory.hxx)
#include KWSYS_HEADER(stl/string) #include KWSYS_HEADER(stl/string)
#include KWSYS_HEADER(stl/vector) #include KWSYS_HEADER(stl/vector)
#include KWSYS_HEADER(stl/algorithm)
// Work-around CMake dependency scanning limitation. This must // Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers. // duplicate the above list of headers.
@ -30,6 +31,8 @@
# include "SystemTools.hxx.in" # include "SystemTools.hxx.in"
# include "kwsys_stl.hxx.in" # include "kwsys_stl.hxx.in"
# include "kwsys_stl_string.hxx.in" # include "kwsys_stl_string.hxx.in"
# include "kwsys_stl_vector.hxx.in"
# include "kwsys_stl_algorithm.hxx.in"
#endif #endif
#include <ctype.h> #include <ctype.h>
@ -66,6 +69,10 @@ Glob::Glob()
// RecurseThroughSymlinks is true by default for backwards compatibility, // RecurseThroughSymlinks is true by default for backwards compatibility,
// not because it's a good idea... // not because it's a good idea...
this->FollowedSymlinkCount = 0; this->FollowedSymlinkCount = 0;
// Keep separate variables for directory listing for back compatibility
this->ListDirs = true;
this->RecurseListDirs = false;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -214,13 +221,13 @@ kwsys_stl::string Glob::PatternToRegex(const kwsys_stl::string& pattern,
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void Glob::RecurseDirectory(kwsys_stl::string::size_type start, bool Glob::RecurseDirectory(kwsys_stl::string::size_type start,
const kwsys_stl::string& dir) const kwsys_stl::string& dir, GlobMessages* messages)
{ {
kwsys::Directory d; kwsys::Directory d;
if ( !d.Load(dir) ) if ( !d.Load(dir) )
{ {
return; return true;
} }
unsigned long cc; unsigned long cc;
kwsys_stl::string realname; kwsys_stl::string realname;
@ -255,8 +262,67 @@ void Glob::RecurseDirectory(kwsys_stl::string::size_type start,
if (isSymLink) if (isSymLink)
{ {
++this->FollowedSymlinkCount; ++this->FollowedSymlinkCount;
kwsys_stl::string realPathErrorMessage;
kwsys_stl::string canonicalPath(SystemTools::GetRealPath(dir,
&realPathErrorMessage));
if(!realPathErrorMessage.empty())
{
if(messages)
{
messages->push_back(Message(
Glob::error, "Canonical path generation from path '"
+ dir + "' failed! Reason: '" + realPathErrorMessage + "'"));
}
return false;
}
if(kwsys_stl::find(this->VisitedSymlinks.begin(),
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))
{
this->VisitedSymlinks.pop_back();
return false;
}
this->VisitedSymlinks.pop_back();
}
// else we have already visited this symlink - prevent cyclic recursion
else if(messages)
{
kwsys_stl::string message;
for(kwsys_stl::vector<kwsys_stl::string>::const_iterator
pathIt = kwsys_stl::find(this->VisitedSymlinks.begin(),
this->VisitedSymlinks.end(),
canonicalPath);
pathIt != this->VisitedSymlinks.end(); ++pathIt)
{
message += *pathIt + "\n";
}
message += canonicalPath + "/" + fname;
messages->push_back(Message(Glob::cyclicRecursion, message));
}
}
else
{
if(this->RecurseListDirs)
{
this->AddFile(this->Internals->Files, realname);
}
if(!this->RecurseDirectory(start+1, realname, messages))
{
return false;
}
} }
this->RecurseDirectory(start+1, realname);
} }
else else
{ {
@ -267,17 +333,19 @@ void Glob::RecurseDirectory(kwsys_stl::string::size_type start,
} }
} }
} }
return true;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void Glob::ProcessDirectory(kwsys_stl::string::size_type start, void Glob::ProcessDirectory(kwsys_stl::string::size_type start,
const kwsys_stl::string& dir) const kwsys_stl::string& dir, GlobMessages* messages)
{ {
//kwsys_ios::cout << "ProcessDirectory: " << dir << kwsys_ios::endl; //kwsys_ios::cout << "ProcessDirectory: " << dir << kwsys_ios::endl;
bool last = ( start == this->Internals->Expressions.size()-1 ); bool last = ( start == this->Internals->Expressions.size()-1 );
if ( last && this->Recurse ) if ( last && this->Recurse )
{ {
this->RecurseDirectory(start, dir); this->RecurseDirectory(start, dir, messages);
return; return;
} }
@ -321,8 +389,9 @@ void Glob::ProcessDirectory(kwsys_stl::string::size_type start,
// << this->Internals->TextExpressions[start].c_str() << kwsys_ios::endl; // << this->Internals->TextExpressions[start].c_str() << kwsys_ios::endl;
//kwsys_ios::cout << "Real name: " << realname << kwsys_ios::endl; //kwsys_ios::cout << "Real name: " << realname << kwsys_ios::endl;
if ( !last && if( (!last && !kwsys::SystemTools::FileIsDirectory(realname))
!kwsys::SystemTools::FileIsDirectory(realname) ) || (!this->ListDirs && last &&
kwsys::SystemTools::FileIsDirectory(realname)) )
{ {
continue; continue;
} }
@ -335,14 +404,14 @@ void Glob::ProcessDirectory(kwsys_stl::string::size_type start,
} }
else else
{ {
this->ProcessDirectory(start+1, realname); this->ProcessDirectory(start+1, realname, messages);
} }
} }
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool Glob::FindFiles(const kwsys_stl::string& inexpr) bool Glob::FindFiles(const kwsys_stl::string& inexpr, GlobMessages* messages)
{ {
kwsys_stl::string cexpr; kwsys_stl::string cexpr;
kwsys_stl::string::size_type cc; kwsys_stl::string::size_type cc;
@ -438,11 +507,11 @@ bool Glob::FindFiles(const kwsys_stl::string& inexpr)
// Handle network paths // Handle network paths
if ( skip > 0 ) if ( skip > 0 )
{ {
this->ProcessDirectory(0, fexpr.substr(0, skip) + "/"); this->ProcessDirectory(0, fexpr.substr(0, skip) + "/", messages);
} }
else else
{ {
this->ProcessDirectory(0, "/"); this->ProcessDirectory(0, "/", messages);
} }
return true; return true;
} }

View File

@ -39,12 +39,37 @@ class GlobInternals;
*/ */
class @KWSYS_NAMESPACE@_EXPORT Glob class @KWSYS_NAMESPACE@_EXPORT Glob
{ {
public:
enum MessageType
{
error,
cyclicRecursion
};
struct Message
{
MessageType type;
kwsys_stl::string content;
Message(MessageType t, const kwsys_stl::string& c) :
type(t),
content(c)
{}
Message(const Message& msg) :
type(msg.type),
content(msg.content)
{}
};
typedef kwsys_stl::vector<Message> GlobMessages;
typedef kwsys_stl::vector<Message>::iterator GlobMessagesIterator;
public: public:
Glob(); Glob();
~Glob(); ~Glob();
//! Find all files that match the pattern. //! Find all files that match the pattern.
bool FindFiles(const kwsys_stl::string& inexpr); bool FindFiles(const kwsys_stl::string& inexpr,
GlobMessages* messages = 0);
//! Return the list of files that matched. //! Return the list of files that matched.
kwsys_stl::vector<kwsys_stl::string>& GetFiles(); kwsys_stl::vector<kwsys_stl::string>& GetFiles();
@ -80,15 +105,26 @@ public:
bool require_whole_string = true, bool require_whole_string = true,
bool preserve_case = false); 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: protected:
//! Process directory //! Process directory
void ProcessDirectory(kwsys_stl::string::size_type start, void ProcessDirectory(kwsys_stl::string::size_type start,
const kwsys_stl::string& dir); const kwsys_stl::string& dir,
GlobMessages* messages);
//! Process last directory, but only when recurse flags is on. That is //! Process last directory, but only when recurse flags is on. That is
// effectively like saying: /path/to/file/**/file // effectively like saying: /path/to/file/**/file
void RecurseDirectory(kwsys_stl::string::size_type start, bool RecurseDirectory(kwsys_stl::string::size_type start,
const kwsys_stl::string& dir); const kwsys_stl::string& dir,
GlobMessages* messages);
//! Add regular expression //! Add regular expression
void AddExpression(const kwsys_stl::string& expr); void AddExpression(const kwsys_stl::string& expr);
@ -101,6 +137,9 @@ protected:
kwsys_stl::string Relative; kwsys_stl::string Relative;
bool RecurseThroughSymlinks; bool RecurseThroughSymlinks;
unsigned int FollowedSymlinkCount; unsigned int FollowedSymlinkCount;
kwsys_stl::vector<kwsys_stl::string> VisitedSymlinks;
bool ListDirs;
bool RecurseListDirs;
private: private:
Glob(const Glob&); // Not implemented. Glob(const Glob&); // Not implemented.