aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs
diff options
context:
space:
mode:
authorEike Ziller <eike.ziller@qt.io>2019-07-17 14:55:39 +0200
committerEike Ziller <eike.ziller@qt.io>2019-07-18 08:55:26 +0000
commit32ac159ce663bf978216e661881690e9041f8556 (patch)
treee9729579ca72868ce50d3cd908d8119f4a50f8b7 /src/libs
parent3fbb5ddba873e65855e8cf4d9b404170746fc511 (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.cpp44
-rw-r--r--src/libs/utils/filesearch.h1
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;