diff --git a/src/tools/ecode/ignorematcher.cpp b/src/tools/ecode/ignorematcher.cpp index 2dcf860c6..81bbd338a 100644 --- a/src/tools/ecode/ignorematcher.cpp +++ b/src/tools/ecode/ignorematcher.cpp @@ -1,4 +1,5 @@ #include "ignorematcher.hpp" +#include #include #include @@ -171,7 +172,6 @@ bool GitIgnoreMatcher::parse() { if ( pattern[0] == '!' ) { negates = true; pattern = String::lTrim( pattern, '!' ); - mHasNegates = true; } pattern = String::rTrim( pattern, '/' ); mPatterns.emplace_back( std::make_pair( pattern, negates ) ); @@ -181,13 +181,20 @@ bool GitIgnoreMatcher::parse() { } bool GitIgnoreMatcher::match( const std::string& value ) const { + bool match = false; for ( size_t i = 0; i < mPatterns.size(); i++ ) { - if ( gitignore_glob_match( value, mPatterns[i].first ) ) { - if ( mHasNegates ) { + auto& pattern = mPatterns[i]; + match = gitignore_glob_match( value, pattern.first ); + if ( ( match && !pattern.second ) || ( !match && pattern.second ) ) { + if ( !pattern.second && i + 1 < mPatterns.size() && mPatterns[i + 1].second ) { for ( size_t n = i + 1; n < mPatterns.size(); n++ ) { // Check if there's a positive negate after the match - if ( mPatterns[n].second && gitignore_glob_match( value, mPatterns[n].first ) ) - return false; + if ( mPatterns[n].second ) { + if ( gitignore_glob_match( value, mPatterns[n].first ) ) + return false; + } else { + break; + } } } return true; @@ -200,21 +207,45 @@ IgnoreMatcherManager::IgnoreMatcherManager( std::string rootPath ) { FileSystem::dirAddSlashAtEnd( rootPath ); GitIgnoreMatcher git( rootPath ); if ( git.canMatch() ) - mMatcher = std::make_unique( rootPath ); + mMatchers.emplace_back( eeNew( GitIgnoreMatcher, ( rootPath ) ) ); +} + +IgnoreMatcherManager::~IgnoreMatcherManager() { + for ( size_t i = 0; i < mMatchers.size(); ++i ) + eeDelete( mMatchers[i] ); } bool IgnoreMatcherManager::foundMatch() const { - return mMatcher != nullptr; + return !mMatchers.empty(); } bool IgnoreMatcherManager::match( const std::string& value ) const { eeASSERT( foundMatch() ); - return mMatcher->match( value ); + for ( const auto& matcher : mMatchers ) + if ( matcher->match( value ) ) + return true; + return false; } const std::string& IgnoreMatcherManager::getPath() const { eeASSERT( foundMatch() ); - return mMatcher->getPath(); + return mMatchers[mMatchers.size() - 1]->getPath(); } +void IgnoreMatcherManager::addChild( IgnoreMatcher* child ) { + mMatchers.emplace_back( child ); } + +void IgnoreMatcherManager::removeChild( IgnoreMatcher* child ) { + auto it = std::find( mMatchers.begin(), mMatchers.end(), child ); + if ( it != mMatchers.end() ) + mMatchers.erase( it ); +} + +IgnoreMatcher* IgnoreMatcherManager::popMatcher( size_t index ) { + IgnoreMatcher* matcher = mMatchers[index]; + mMatchers.erase( mMatchers.begin() + index ); + return matcher; +} + +} // namespace ecode diff --git a/src/tools/ecode/ignorematcher.hpp b/src/tools/ecode/ignorematcher.hpp index 345f35e20..b9322223f 100644 --- a/src/tools/ecode/ignorematcher.hpp +++ b/src/tools/ecode/ignorematcher.hpp @@ -41,21 +41,30 @@ class GitIgnoreMatcher : public IgnoreMatcher { bool parse() override; std::vector> mPatterns; - bool mHasNegates{ false }; }; class IgnoreMatcherManager { public: IgnoreMatcherManager( std::string rootPath ); + virtual ~IgnoreMatcherManager(); + bool foundMatch() const; bool match( const std::string& value ) const; const std::string& getPath() const; + void addChild( IgnoreMatcher* child ); + + void removeChild( IgnoreMatcher* child ); + + size_t matchersCount() { return mMatchers.size(); } + + IgnoreMatcher* popMatcher( size_t index ); + protected: - std::unique_ptr mMatcher; + std::vector mMatchers; }; } // namespace ecode diff --git a/src/tools/ecode/projectdirectorytree.cpp b/src/tools/ecode/projectdirectorytree.cpp index 2063b26ff..4ba06104c 100644 --- a/src/tools/ecode/projectdirectorytree.cpp +++ b/src/tools/ecode/projectdirectorytree.cpp @@ -161,7 +161,7 @@ void ProjectDirectoryTree::getDirectoryFiles( std::vector& files, std::string directory, std::set currentDirs, const bool& ignoreHidden, - const IgnoreMatcherManager& ignoreMatcher ) { + IgnoreMatcherManager& ignoreMatcher ) { if ( !mRunning ) return; currentDirs.insert( directory ); @@ -190,8 +190,16 @@ void ProjectDirectoryTree::getDirectoryFiles( std::vector& files, mDirectories.push_back( fullpath ); } IgnoreMatcherManager dirMatcher( fullpath ); - getDirectoryFiles( files, names, fullpath, currentDirs, ignoreHidden, - dirMatcher.foundMatch() ? dirMatcher : ignoreMatcher ); + IgnoreMatcher* childMatch = nullptr; + if ( dirMatcher.foundMatch() ) { + childMatch = dirMatcher.popMatcher( 0 ); + ignoreMatcher.addChild( childMatch ); + } + getDirectoryFiles( files, names, fullpath, currentDirs, ignoreHidden, ignoreMatcher ); + if ( childMatch ) { + ignoreMatcher.removeChild( childMatch ); + eeSAFE_DELETE( childMatch ); + } } else { files.emplace_back( fullpath ); names.emplace_back( file ); diff --git a/src/tools/ecode/projectdirectorytree.hpp b/src/tools/ecode/projectdirectorytree.hpp index 656f82ded..5b13a75e9 100644 --- a/src/tools/ecode/projectdirectorytree.hpp +++ b/src/tools/ecode/projectdirectorytree.hpp @@ -111,7 +111,7 @@ class ProjectDirectoryTree { void getDirectoryFiles( std::vector& files, std::vector& names, std::string directory, std::set currentDirs, - const bool& ignoreHidden, const IgnoreMatcherManager& ignoreMatcher ); + const bool& ignoreHidden, IgnoreMatcherManager& ignoreMatcher ); void addFile( const FileInfo& file ); @@ -126,6 +126,6 @@ class ProjectDirectoryTree { size_t findFileIndex( const std::string& path ); }; -} +} // namespace ecode #endif // ECODE_PROJECTDIRECTORYTREE_HPP