mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-06-01 02:56:28 +03:00
199 lines
5.6 KiB
C++
199 lines
5.6 KiB
C++
#include "ignorematcher.hpp"
|
|
#include <algorithm>
|
|
#include <eepp/core/string.hpp>
|
|
#include <eepp/system/filesystem.hpp>
|
|
|
|
namespace ecode {
|
|
|
|
IgnoreMatcher::IgnoreMatcher( const std::string& rootPath ) : mPath( rootPath ) {
|
|
FileSystem::dirAddSlashAtEnd( mPath );
|
|
}
|
|
|
|
IgnoreMatcher::~IgnoreMatcher() {}
|
|
|
|
GitIgnoreMatcher::GitIgnoreMatcher( const std::string& rootPath, const std::string& ignoreFileName,
|
|
bool addGitFolderFilter ) :
|
|
IgnoreMatcher( rootPath ),
|
|
mIgnoreFileName( ignoreFileName ),
|
|
mIgnoreFilePath( mPath + mIgnoreFileName ) {
|
|
if ( canMatch() ) {
|
|
if ( addGitFolderFilter ) {
|
|
if ( FileSystem::fileExists( mPath + ".git" ) ) // Also ignore the .git folder
|
|
mPatterns.emplace_back( std::make_pair( ".git/**", false ) );
|
|
}
|
|
if ( parse() ) {
|
|
mMatcherReady = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool GitIgnoreMatcher::canMatch() {
|
|
return FileSystem::fileExists( mIgnoreFilePath );
|
|
}
|
|
|
|
const std::string& GitIgnoreMatcher::getIgnoreFilePath() const {
|
|
return mIgnoreFilePath;
|
|
}
|
|
|
|
bool GitIgnoreMatcher::parse() {
|
|
std::string patternFile;
|
|
FileSystem::fileGet( mPath + mIgnoreFileName, patternFile );
|
|
std::vector<std::string> patterns = String::split( patternFile );
|
|
for ( auto& pattern : patterns ) {
|
|
bool negates = false;
|
|
if ( pattern.empty() )
|
|
continue;
|
|
if ( pattern[0] == '#' )
|
|
continue;
|
|
pattern = String::rTrim( pattern, ' ' );
|
|
pattern = String::rTrim( pattern, '\r' );
|
|
if ( pattern[0] == '!' ) {
|
|
negates = true;
|
|
pattern = String::lTrim( pattern, '!' );
|
|
}
|
|
pattern = String::rTrim( pattern, '/' );
|
|
mPatterns.emplace_back( std::make_pair( pattern, negates ) );
|
|
}
|
|
return !mPatterns.empty();
|
|
}
|
|
|
|
bool GitIgnoreMatcher::match( const std::string& value ) const {
|
|
if ( mPatterns.empty() )
|
|
return false;
|
|
bool match = false;
|
|
for ( size_t i = 0; i < mPatterns.size(); i++ ) {
|
|
auto& pattern = mPatterns[i];
|
|
match = String::globMatch( value, pattern.first );
|
|
if ( pattern.second )
|
|
match = !match;
|
|
if ( match && !pattern.second ) {
|
|
if ( 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 ) {
|
|
if ( String::globMatch( value, mPatterns[n].first ) )
|
|
return false;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
std::string GitIgnoreMatcher::findRepositoryRootPath() const {
|
|
std::string rootPath( mPath );
|
|
std::string lRootPath;
|
|
FileSystem::dirAddSlashAtEnd( rootPath );
|
|
while ( rootPath != lRootPath && !FileSystem::fileExists( rootPath + ".git" ) ) {
|
|
lRootPath = rootPath;
|
|
rootPath = FileSystem::removeLastFolderFromPath( rootPath );
|
|
}
|
|
return FileSystem::fileExists( rootPath + ".git" ) ? rootPath : "";
|
|
}
|
|
|
|
IgnoreMatcherManager::IgnoreMatcherManager( IgnoreMatcherManager&& ignoreMatcher ) :
|
|
mMatchers( ignoreMatcher.mMatchers ) {
|
|
ignoreMatcher.mMatchers.clear();
|
|
}
|
|
|
|
IgnoreMatcherManager::IgnoreMatcherManager( std::string rootPath ) {
|
|
FileSystem::dirAddSlashAtEnd( rootPath );
|
|
mRootPath = rootPath;
|
|
GitIgnoreMatcher git( rootPath );
|
|
if ( git.canMatch() )
|
|
mMatchers.emplace_back( eeNew( GitIgnoreMatcher, ( rootPath ) ) );
|
|
}
|
|
|
|
IgnoreMatcherManager& IgnoreMatcherManager::operator=( IgnoreMatcherManager&& other ) {
|
|
mMatchers = other.mMatchers;
|
|
other.mMatchers.clear();
|
|
return *this;
|
|
}
|
|
|
|
IgnoreMatcherManager::~IgnoreMatcherManager() {
|
|
for ( size_t i = 0; i < mMatchers.size(); ++i )
|
|
eeDelete( mMatchers[i] );
|
|
}
|
|
|
|
bool IgnoreMatcherManager::foundMatch() const {
|
|
return !mMatchers.empty();
|
|
}
|
|
|
|
bool IgnoreMatcherManager::match( const FileInfo& file ) const {
|
|
eeASSERT( foundMatch() );
|
|
auto dirPath( file.getDirectoryPath() );
|
|
std::string localPath;
|
|
for ( const auto& matcher : mMatchers ) {
|
|
localPath.clear();
|
|
if ( String::startsWith( dirPath, matcher->getPath() ) )
|
|
localPath = dirPath.substr( matcher->getPath().size() );
|
|
if ( matcher->match( localPath + file.getFileName() ) )
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool IgnoreMatcherManager::match( const std::string& dir, const std::string& value ) const {
|
|
eeASSERT( foundMatch() );
|
|
std::string localPath;
|
|
for ( const auto& matcher : mMatchers ) {
|
|
localPath.clear();
|
|
if ( String::startsWith( dir, matcher->getPath() ) )
|
|
localPath = dir.substr( matcher->getPath().size() );
|
|
if ( matcher->match( localPath + value ) )
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
std::string IgnoreMatcherManager::findRepositoryRootPath() const {
|
|
if ( mMatchers.empty() ) {
|
|
std::string rootPath( mRootPath );
|
|
std::string lRootpath;
|
|
while ( rootPath != lRootpath && !rootPath.empty() ) {
|
|
GitIgnoreMatcher git( rootPath );
|
|
if ( git.canMatch() )
|
|
return git.findRepositoryRootPath();
|
|
lRootpath = rootPath;
|
|
rootPath = FileSystem::removeLastFolderFromPath( rootPath );
|
|
}
|
|
return "";
|
|
}
|
|
return mMatchers.front()->findRepositoryRootPath();
|
|
}
|
|
|
|
const std::string& IgnoreMatcherManager::getPath() const {
|
|
eeASSERT( foundMatch() );
|
|
return mMatchers[mMatchers.size() - 1]->getPath();
|
|
}
|
|
|
|
const std::string& IgnoreMatcherManager::getRootPath() const {
|
|
return mRootPath;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
const std::vector<IgnoreMatcher*>& IgnoreMatcherManager::getMatchers() const {
|
|
return mMatchers;
|
|
}
|
|
|
|
} // namespace ecode
|