diff options
author | Eike Ziller <eike.ziller@qt.io> | 2019-07-17 14:55:39 +0200 |
---|---|---|
committer | Eike Ziller <eike.ziller@qt.io> | 2019-07-18 08:55:26 +0000 |
commit | 32ac159ce663bf978216e661881690e9041f8556 (patch) | |
tree | e9729579ca72868ce50d3cd908d8119f4a50f8b7 /src/libs | |
parent | 3fbb5ddba873e65855e8cf4d9b404170746fc511 (diff) |
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>
Diffstat (limited to 'src/libs')
-rw-r--r-- | src/libs/utils/filesearch.cpp | 44 | ||||
-rw-r--r-- | src/libs/utils/filesearch.h | 1 |
2 files changed, 29 insertions, 16 deletions
diff --git a/src/libs/utils/filesearch.cpp b/src/libs/utils/filesearch.cpp index 0bdf3991c5..03aa1cf9b2 100644 --- a/src/libs/utils/filesearch.cpp +++ b/src/libs/utils/filesearch.cpp @@ -651,11 +651,16 @@ SubDirFileIterator::SubDirFileIterator(const QStringList &directories, const QSt { m_encoding = (encoding == nullptr ? QTextCodec::codecForLocale() : encoding); qreal maxPer = qreal(MAX_PROGRESS) / directories.count(); - foreach (const QString &directoryEntry, directories) { + for (const QString &directoryEntry : directories) { if (!directoryEntry.isEmpty()) { - m_dirs.push(QDir(directoryEntry)); - m_progressValues.push(maxPer); - m_processedValues.push(false); + 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_processedValues.push(false); + } } } } @@ -676,10 +681,18 @@ void SubDirFileIterator::update(int index) 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()) { + using Dir = QString; + using CanonicalDir = QString; + std::vector<std::pair<Dir, CanonicalDir>> subDirs; + 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 allFilePaths = Utils::transform(allFileEntries, [&dirPath](const QString &entry) { @@ -696,14 +709,13 @@ void SubDirFileIterator::update(int index) m_dirs.push(dir); m_progressValues.push(subProgress); m_processedValues.push(true); - QStringListIterator it(subDirs); - it.toBack(); - while (it.hasPrevious()) { - const QString &directory = it.previous(); - m_dirs.push(QDir(dirPath + QLatin1Char('/') + directory)); - m_progressValues.push(subProgress); - m_processedValues.push(false); - } + Utils::reverseForeach(subDirs, + [this, subProgress](const std::pair<Dir, CanonicalDir> &dir) { + m_dirs.push(QDir(dir.first)); + m_knownDirs.insert(dir.second); + m_progressValues.push(subProgress); + m_processedValues.push(false); + }); } } else { m_progress += dirProgressMax; diff --git a/src/libs/utils/filesearch.h b/src/libs/utils/filesearch.h index cddb637184..546a7334cc 100644 --- a/src/libs/utils/filesearch.h +++ b/src/libs/utils/filesearch.h @@ -159,6 +159,7 @@ private: std::function<QStringList(const QStringList &)> m_filterFiles; QTextCodec *m_encoding; QStack<QDir> m_dirs; + QSet<QString> m_knownDirs; QStack<qreal> m_progressValues; QStack<bool> m_processedValues; qreal m_progress; |