File search: Avoid symlink loops and duplicate directories

Looks like this was always broken, but got more prominent by the
introduction of automatic directory locator filters for all open
projects.

Task-number: QTCREATORBUG-22662
Change-Id: I248fb611bb1a6226b27901ea6ab310fc640def7a
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Eike Ziller
2019-07-17 14:55:39 +02:00
parent 3fbb5ddba8
commit 32ac159ce6
2 changed files with 29 additions and 16 deletions

View File

@@ -651,13 +651,18 @@ SubDirFileIterator::SubDirFileIterator(const QStringList &directories, const QSt
{ {
m_encoding = (encoding == nullptr ? QTextCodec::codecForLocale() : encoding); m_encoding = (encoding == nullptr ? QTextCodec::codecForLocale() : encoding);
qreal maxPer = qreal(MAX_PROGRESS) / directories.count(); qreal maxPer = qreal(MAX_PROGRESS) / directories.count();
foreach (const QString &directoryEntry, directories) { for (const QString &directoryEntry : directories) {
if (!directoryEntry.isEmpty()) { if (!directoryEntry.isEmpty()) {
m_dirs.push(QDir(directoryEntry)); const QDir dir(directoryEntry);
const QString canonicalPath = dir.canonicalPath();
if (!canonicalPath.isEmpty() && dir.exists()) {
m_dirs.push(dir);
m_knownDirs.insert(canonicalPath);
m_progressValues.push(maxPer); m_progressValues.push(maxPer);
m_processedValues.push(false); m_processedValues.push(false);
} }
} }
}
} }
SubDirFileIterator::~SubDirFileIterator() SubDirFileIterator::~SubDirFileIterator()
@@ -676,10 +681,18 @@ void SubDirFileIterator::update(int index)
const bool processed = m_processedValues.pop(); const bool processed = m_processedValues.pop();
if (dir.exists()) { if (dir.exists()) {
const QString dirPath = dir.path(); const QString dirPath = dir.path();
QStringList subDirs; using Dir = QString;
if (!processed) using CanonicalDir = QString;
subDirs = dir.entryList(QDir::Dirs|QDir::Hidden|QDir::NoDotAndDotDot); std::vector<std::pair<Dir, CanonicalDir>> subDirs;
if (subDirs.isEmpty()) { if (!processed) {
for (const QFileInfo &info :
dir.entryInfoList(QDir::Dirs | QDir::Hidden | QDir::NoDotAndDotDot)) {
const QString canonicalDir = info.canonicalFilePath();
if (!m_knownDirs.contains(canonicalDir))
subDirs.emplace_back(info.filePath(), canonicalDir);
}
}
if (subDirs.empty()) {
const QStringList allFileEntries = dir.entryList(QDir::Files|QDir::Hidden); const QStringList allFileEntries = dir.entryList(QDir::Files|QDir::Hidden);
const QStringList allFilePaths = Utils::transform(allFileEntries, const QStringList allFilePaths = Utils::transform(allFileEntries,
[&dirPath](const QString &entry) { [&dirPath](const QString &entry) {
@@ -696,14 +709,13 @@ void SubDirFileIterator::update(int index)
m_dirs.push(dir); m_dirs.push(dir);
m_progressValues.push(subProgress); m_progressValues.push(subProgress);
m_processedValues.push(true); m_processedValues.push(true);
QStringListIterator it(subDirs); Utils::reverseForeach(subDirs,
it.toBack(); [this, subProgress](const std::pair<Dir, CanonicalDir> &dir) {
while (it.hasPrevious()) { m_dirs.push(QDir(dir.first));
const QString &directory = it.previous(); m_knownDirs.insert(dir.second);
m_dirs.push(QDir(dirPath + QLatin1Char('/') + directory));
m_progressValues.push(subProgress); m_progressValues.push(subProgress);
m_processedValues.push(false); m_processedValues.push(false);
} });
} }
} else { } else {
m_progress += dirProgressMax; m_progress += dirProgressMax;

View File

@@ -159,6 +159,7 @@ private:
std::function<QStringList(const QStringList &)> m_filterFiles; std::function<QStringList(const QStringList &)> m_filterFiles;
QTextCodec *m_encoding; QTextCodec *m_encoding;
QStack<QDir> m_dirs; QStack<QDir> m_dirs;
QSet<QString> m_knownDirs;
QStack<qreal> m_progressValues; QStack<qreal> m_progressValues;
QStack<bool> m_processedValues; QStack<bool> m_processedValues;
qreal m_progress; qreal m_progress;