summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Hunger <tobias.hunger@qt.io>2017-06-19 16:07:25 +0200
committerTobias Hunger <tobias.hunger@qt.io>2017-06-20 14:24:02 +0000
commitbc22de5f0ae7795561673bf91e9bd5f532e7f4b0 (patch)
tree65bff7bc0fcad47ccb1bec91b832e4163a8735de
parente42f3db9f0ab1ec28bf9ba414add84d3b552118f (diff)
downloadqt-creator-bc22de5f0ae7795561673bf91e9bd5f532e7f4b0.tar.gz
ProjectExplorer: Do not use version manager cache in threads
Do not use VcsManager's cache of version control systems from different threads. Iterate over all IVersionControls instead of getting the specific version control for a directory. This is less exact, but will probably not hurt users. Task-number: QTCREATORBUG-18258 Change-Id: Iae2be5735a0d7ecc8d774904f6681963fca1d114 Reviewed-by: Eike Ziller <eike.ziller@qt.io>
-rw-r--r--src/plugins/cmakeprojectmanager/treescanner.cpp20
-rw-r--r--src/plugins/cmakeprojectmanager/treescanner.h6
-rw-r--r--src/plugins/coreplugin/iversioncontrol.h2
-rw-r--r--src/plugins/nim/project/nimproject.cpp9
-rw-r--r--src/plugins/projectexplorer/projectnodes.cpp27
-rw-r--r--src/plugins/projectexplorer/projectnodes.h8
6 files changed, 55 insertions, 17 deletions
diff --git a/src/plugins/cmakeprojectmanager/treescanner.cpp b/src/plugins/cmakeprojectmanager/treescanner.cpp
index 6951221dd8..83fae4070e 100644
--- a/src/plugins/cmakeprojectmanager/treescanner.cpp
+++ b/src/plugins/cmakeprojectmanager/treescanner.cpp
@@ -25,6 +25,8 @@
#include "treescanner.h"
+#include <coreplugin/iversioncontrol.h>
+#include <coreplugin/vcsmanager.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <cpptools/cpptoolsconstants.h>
@@ -67,7 +69,10 @@ bool TreeScanner::asyncScanForFiles(const Utils::FileName &directory)
m_scanFuture = fi->future();
m_futureWatcher.setFuture(m_scanFuture);
- Utils::runAsync([this, fi, directory]() { TreeScanner::scanForFiles(fi, directory, m_filter, m_factory); });
+ if (m_versionControls.isEmpty())
+ m_versionControls = Core::VcsManager::versionControls();
+
+ Utils::runAsync([this, fi, directory]() { TreeScanner::scanForFiles(fi, directory, m_filter, m_factory, m_versionControls); });
return true;
}
@@ -144,13 +149,17 @@ FileType TreeScanner::genericFileType(const Utils::MimeType &mimeType, const Uti
return Node::fileTypeForMimeType(mimeType);
}
-void TreeScanner::scanForFiles(FutureInterface *fi, const Utils::FileName& directory, const FileFilter &filter, const FileTypeFactory &factory)
+void TreeScanner::scanForFiles(FutureInterface *fi, const Utils::FileName& directory,
+ const FileFilter &filter, const FileTypeFactory &factory,
+ QList<Core::IVersionControl *> &versionControls)
{
std::unique_ptr<FutureInterface> fip(fi);
fip->reportStarted();
- Result nodes = FileNode::scanForFiles(directory,
- [&filter, &factory](const Utils::FileName &fn) -> FileNode * {
+ Result nodes
+ = FileNode::scanForFilesWithVersionControls(
+ directory,
+ [&filter, &factory](const Utils::FileName &fn) -> FileNode * {
QTC_ASSERT(!fn.isEmpty(), return nullptr);
const Utils::MimeType mimeType = Utils::mimeTypeForFile(fn.toString());
@@ -166,8 +175,7 @@ void TreeScanner::scanForFiles(FutureInterface *fi, const Utils::FileName& direc
type = factory(mimeType, fn);
return new FileNode(fn, type, false);
- },
- fip.get());
+ }, versionControls, fip.get());
// Clean up nodes and keep it sorted
Result tmp = Utils::filtered(nodes, [](const FileNode *fn) -> bool {
diff --git a/src/plugins/cmakeprojectmanager/treescanner.h b/src/plugins/cmakeprojectmanager/treescanner.h
index 33b4522a20..146076f1f2 100644
--- a/src/plugins/cmakeprojectmanager/treescanner.h
+++ b/src/plugins/cmakeprojectmanager/treescanner.h
@@ -36,6 +36,8 @@
#include <functional>
+namespace Core { class IVersionControl; }
+
namespace CMakeProjectManager {
namespace Internal {
@@ -86,7 +88,8 @@ signals:
private:
static void scanForFiles(FutureInterface *fi, const Utils::FileName &directory,
- const FileFilter &filter, const FileTypeFactory &factory);
+ const FileFilter &filter, const FileTypeFactory &factory,
+ QList<Core::IVersionControl *> &versionControls);
private:
FileFilter m_filter;
@@ -94,6 +97,7 @@ private:
FutureWatcher m_futureWatcher;
Future m_scanFuture;
+ QList<Core::IVersionControl *> m_versionControls;
};
} // namespace Internal
diff --git a/src/plugins/coreplugin/iversioncontrol.h b/src/plugins/coreplugin/iversioncontrol.h
index eb880e7c70..eddcee4ff3 100644
--- a/src/plugins/coreplugin/iversioncontrol.h
+++ b/src/plugins/coreplugin/iversioncontrol.h
@@ -100,6 +100,8 @@ public:
*
* It will return true only for exact matches of the name, not for e.g. files in a
* directory owned by the version control system (e.g. .git/control).
+ *
+ * This method needs to be thread safe!
*/
virtual bool isVcsFileOrDirectory(const Utils::FileName &fileName) const = 0;
diff --git a/src/plugins/nim/project/nimproject.cpp b/src/plugins/nim/project/nimproject.cpp
index 5db9fd554a..8910bd42af 100644
--- a/src/plugins/nim/project/nimproject.cpp
+++ b/src/plugins/nim/project/nimproject.cpp
@@ -31,6 +31,8 @@
#include "../nimconstants.h"
#include <coreplugin/progressmanager/progressmanager.h>
+#include <coreplugin/iversioncontrol.h>
+#include <coreplugin/vcsmanager.h>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/kit.h>
#include <projectexplorer/projectexplorerconstants.h>
@@ -113,8 +115,11 @@ void NimProject::collectProjectFiles()
m_lastProjectScan.start();
QTC_ASSERT(!m_futureWatcher.future().isRunning(), return);
FileName prjDir = projectDirectory();
- QFuture<QList<ProjectExplorer::FileNode *>> future = Utils::runAsync([prjDir] {
- return FileNode::scanForFiles(prjDir, [](const FileName &fn) { return new FileNode(fn, FileType::Source, false); });
+ const QList<Core::IVersionControl *> versionControls = Core::VcsManager::versionControls();
+ QFuture<QList<ProjectExplorer::FileNode *>> future = Utils::runAsync([prjDir, versionControls] {
+ return FileNode::scanForFilesWithVersionControls(
+ prjDir, [](const FileName &fn) { return new FileNode(fn, FileType::Source, false); },
+ versionControls);
});
m_futureWatcher.setFuture(future);
Core::ProgressManager::addTask(future, tr("Scanning for Nim files"), "Nim.Project.Scan");
diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp
index aa619aa426..741dc394e7 100644
--- a/src/plugins/projectexplorer/projectnodes.cpp
+++ b/src/plugins/projectexplorer/projectnodes.cpp
@@ -339,7 +339,8 @@ FileType FileNode::fileType() const
static QList<FileNode *> scanForFilesRecursively(const Utils::FileName &directory,
const std::function<FileNode *(const Utils::FileName &)> factory,
QSet<QString> &visited, QFutureInterface<QList<FileNode*>> *future,
- double progressStart, double progressRange)
+ double progressStart, double progressRange,
+ const QList<Core::IVersionControl*> &versionControls)
{
QList<FileNode *> result;
@@ -351,8 +352,6 @@ static QList<FileNode *> scanForFilesRecursively(const Utils::FileName &director
if (visitedCount == visited.count())
return result;
- const Core::IVersionControl *vcsControl
- = Core::VcsManager::findVersionControlForDirectory(baseDir.absolutePath(), nullptr);
const QList<QFileInfo> entries = baseDir.entryInfoList(QStringList(), QDir::AllEntries|QDir::NoDotAndDotDot);
double progress = 0;
const double progressIncrement = progressRange / static_cast<double>(entries.count());
@@ -362,9 +361,11 @@ static QList<FileNode *> scanForFilesRecursively(const Utils::FileName &director
return result;
const Utils::FileName entryName = Utils::FileName::fromString(entry.absoluteFilePath());
- if (!vcsControl || !vcsControl->isVcsFileOrDirectory(entryName)) {
+ if (!Utils::contains(versionControls, [&entryName](const Core::IVersionControl *vc) {
+ return vc->isVcsFileOrDirectory(entryName);
+ })) {
if (entry.isDir())
- result.append(scanForFilesRecursively(entryName, factory, visited, future, progress, progressIncrement));
+ result.append(scanForFilesRecursively(entryName, factory, visited, future, progress, progressIncrement, versionControls));
else if (FileNode *node = factory(entryName))
result.append(node);
}
@@ -382,14 +383,24 @@ static QList<FileNode *> scanForFilesRecursively(const Utils::FileName &director
return result;
}
+
QList<FileNode *> FileNode::scanForFiles(const Utils::FileName &directory,
- const std::function<FileNode *(const Utils::FileName &)> factory,
- QFutureInterface<QList<FileNode *>> *future)
+ const std::function<FileNode *(const Utils::FileName &)> factory,
+ QFutureInterface<QList<FileNode *> > *future)
+{
+ return FileNode::scanForFilesWithVersionControls(directory, factory, QList<Core::IVersionControl *>(), future);
+}
+
+QList<FileNode *>
+FileNode::scanForFilesWithVersionControls(const Utils::FileName &directory,
+ const std::function<FileNode *(const Utils::FileName &)> factory,
+ const QList<Core::IVersionControl *> &versionControls,
+ QFutureInterface<QList<FileNode *>> *future)
{
QSet<QString> visited;
if (future)
future->setProgressRange(0, 1000000);
- return scanForFilesRecursively(directory, factory, visited, future, 0.0, 1000000.0);
+ return scanForFilesRecursively(directory, factory, visited, future, 0.0, 1000000.0, versionControls);
}
bool FileNode::supportsAction(ProjectAction action, Node *node) const
diff --git a/src/plugins/projectexplorer/projectnodes.h b/src/plugins/projectexplorer/projectnodes.h
index 7c440b7355..746f7437b4 100644
--- a/src/plugins/projectexplorer/projectnodes.h
+++ b/src/plugins/projectexplorer/projectnodes.h
@@ -37,6 +37,7 @@
#include <functional>
namespace Utils { class MimeType; }
+namespace Core { class IVersionControl; }
namespace ProjectExplorer {
@@ -188,9 +189,16 @@ public:
FileNode *asFileNode() final { return this; }
const FileNode *asFileNode() const final { return this; }
+ // For ABI compatibility, remove in QtC 4.4:
static QList<FileNode *> scanForFiles(const Utils::FileName &directory,
const std::function<FileNode *(const Utils::FileName &fileName)> factory,
QFutureInterface<QList<FileNode *>> *future = nullptr);
+
+ static QList<FileNode *>
+ scanForFilesWithVersionControls(const Utils::FileName &directory,
+ const std::function<FileNode *(const Utils::FileName &fileName)> factory,
+ const QList<Core::IVersionControl *> &versionControls,
+ QFutureInterface<QList<FileNode *>> *future = nullptr);
bool supportsAction(ProjectAction action, Node *node) const override;
private: