Advanced search: Add exclusion patterns

All files with full file path matching one of the exclusion patterns are
ignored in the search.
Searching with "git grep" now requires git >= 1.9

Change-Id: Ied5d11499bc1ff21247e50f8e146e8e5011dd2c1
Reviewed-by: David Schulz <david.schulz@qt.io>
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
Eike Ziller
2016-12-09 13:33:12 +01:00
parent 99a6d78bba
commit 1f8b2dc361
18 changed files with 244 additions and 104 deletions

View File

@@ -23,11 +23,14 @@
**
****************************************************************************/
#include "algorithm.h"
#include "filesearch.h"
#include "fileutils.h"
#include "mapreduce.h"
#include <QCoreApplication>
#include <QMutex>
#include <QRegExp>
#include <QRegularExpression>
#include <QTextCodec>
@@ -457,6 +460,50 @@ QString matchCaseReplacement(const QString &originalText, const QString &replace
return replaceText; // mixed
}
} // namespace
static QList<QRegExp> filtersToRegExps(const QStringList &filters)
{
return Utils::transform(filters, [](const QString &filter) {
return QRegExp(filter, Qt::CaseInsensitive, QRegExp::Wildcard);
});
}
static bool matches(const QList<QRegExp> &exprList, const QString &filePath)
{
return Utils::anyOf(exprList, [&filePath](QRegExp reg) {
return (reg.exactMatch(filePath)
|| reg.exactMatch(Utils::FileName::fromString(filePath).fileName()));
});
}
static bool isFileIncluded(const QList<QRegExp> &filterRegs, const QList<QRegExp> &exclusionRegs,
const QString &filePath)
{
const bool isIncluded = filterRegs.isEmpty() || matches(filterRegs, filePath);
return isIncluded && (exclusionRegs.isEmpty() || !matches(exclusionRegs, filePath));
}
std::function<bool(const QString &)>
filterFileFunction(const QStringList &filters, const QStringList &exclusionFilters)
{
const QList<QRegExp> filterRegs = filtersToRegExps(filters);
const QList<QRegExp> exclusionRegs = filtersToRegExps(exclusionFilters);
return [filterRegs, exclusionRegs](const QString &filePath) {
return isFileIncluded(filterRegs, exclusionRegs, filePath);
};
}
std::function<QStringList(const QStringList &)>
filterFilesFunction(const QStringList &filters, const QStringList &exclusionFilters)
{
const QList<QRegExp> filterRegs = filtersToRegExps(filters);
const QList<QRegExp> exclusionRegs = filtersToRegExps(exclusionFilters);
return [filterRegs, exclusionRegs](const QStringList &filePaths) {
return Utils::filtered(filePaths, [&filterRegs, &exclusionRegs](const QString &filePath) {
return isFileIncluded(filterRegs, exclusionRegs, filePath);
});
};
}
QString matchCaseReplacement(const QString &originalText, const QString &replaceText)
@@ -562,8 +609,9 @@ namespace {
}
SubDirFileIterator::SubDirFileIterator(const QStringList &directories, const QStringList &filters,
QTextCodec *encoding)
: m_filters(filters), m_progress(0)
const QStringList &exclusionFilters, QTextCodec *encoding)
: m_filterFiles(filterFilesFunction(filters, exclusionFilters)),
m_progress(0)
{
m_encoding = (encoding == 0 ? QTextCodec::codecForLocale() : encoding);
qreal maxPer = qreal(MAX_PROGRESS) / directories.count();
@@ -591,19 +639,21 @@ void SubDirFileIterator::update(int index)
const qreal dirProgressMax = m_progressValues.pop();
const bool processed = m_processedValues.pop();
if (dir.exists()) {
const QString dirPath = dir.path();
QStringList subDirs;
if (!processed)
subDirs = dir.entryList(QDir::Dirs|QDir::Hidden|QDir::NoDotAndDotDot);
if (subDirs.isEmpty()) {
QStringList fileEntries = dir.entryList(m_filters,
QDir::Files|QDir::Hidden);
QStringListIterator it(fileEntries);
it.toBack();
m_items.reserve(m_items.size() + fileEntries.size());
while (it.hasPrevious()) {
const QString &file = it.previous();
m_items.append(new Item(dir.path()+ QLatin1Char('/') + file, m_encoding));
}
const QStringList allFileEntries = dir.entryList(QDir::Files|QDir::Hidden);
const QStringList allFilePaths = Utils::transform(allFileEntries,
[&dirPath](const QString &entry) {
return QString(dirPath + '/' + entry);
});
const QStringList filePaths = m_filterFiles(allFilePaths);
m_items.reserve(m_items.size() + filePaths.size());
Utils::reverseForeach(filePaths, [this](const QString &file) {
m_items.append(new Item(file, m_encoding));
});
m_progress += dirProgressMax;
} else {
qreal subProgress = dirProgressMax/(subDirs.size()+1);
@@ -614,7 +664,7 @@ void SubDirFileIterator::update(int index)
it.toBack();
while (it.hasPrevious()) {
const QString &directory = it.previous();
m_dirs.push(QDir(dir.path()+ QLatin1Char('/') + directory));
m_dirs.push(QDir(dirPath + QLatin1Char('/') + directory));
m_progressValues.push(subProgress);
m_processedValues.push(false);
}