VcsBase: Use QtConcurrent invocation for async run

Change-Id: Ia4e461c1a2e71d4c959f582e9ed464d4713b672a
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Jarek Kobus
2023-03-04 00:39:50 +01:00
parent cae18f8872
commit ce037d09a2
6 changed files with 54 additions and 50 deletions

View File

@@ -30,13 +30,13 @@
#include <projectexplorer/projectmanager.h> #include <projectexplorer/projectmanager.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/asynctask.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <utils/infobar.h> #include <utils/infobar.h>
#include <utils/layoutbuilder.h> #include <utils/layoutbuilder.h>
#include <utils/parameteraction.h> #include <utils/parameteraction.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/qtcprocess.h> #include <utils/qtcprocess.h>
#include <utils/runextensions.h>
#include <utils/temporarydirectory.h> #include <utils/temporarydirectory.h>
#include <vcsbase/basevcseditorfactory.h> #include <vcsbase/basevcseditorfactory.h>
@@ -259,7 +259,7 @@ private:
CommandResult runCleartool(const FilePath &workingDir, const QStringList &arguments, CommandResult runCleartool(const FilePath &workingDir, const QStringList &arguments,
VcsBase::RunFlags flags = VcsBase::RunFlags::None, VcsBase::RunFlags flags = VcsBase::RunFlags::None,
QTextCodec *codec = nullptr, int timeoutMultiplier = 1) const; QTextCodec *codec = nullptr, int timeoutMultiplier = 1) const;
static void sync(QFutureInterface<void> &future, QStringList files); static void sync(QPromise<void> &promise, QStringList files);
void history(const FilePath &workingDir, void history(const FilePath &workingDir,
const QStringList &file = {}, const QStringList &file = {},
@@ -1657,7 +1657,7 @@ bool ClearCasePluginPrivate::vcsOpen(const FilePath &workingDir, const QString &
if (!m_settings.disableIndexer && if (!m_settings.disableIndexer &&
(fi.isWritable() || vcsStatus(absPath).status == FileStatus::Unknown)) (fi.isWritable() || vcsStatus(absPath).status == FileStatus::Unknown))
runAsync(sync, QStringList(absPath)).waitForFinished(); Utils::asyncRun(sync, QStringList(absPath)).waitForFinished();
if (vcsStatus(absPath).status == FileStatus::CheckedOut) { if (vcsStatus(absPath).status == FileStatus::CheckedOut) {
QMessageBox::information(ICore::dialogParent(), Tr::tr("ClearCase Checkout"), QMessageBox::information(ICore::dialogParent(), Tr::tr("ClearCase Checkout"),
Tr::tr("File is already checked out.")); Tr::tr("File is already checked out."));
@@ -2129,7 +2129,8 @@ void ClearCasePluginPrivate::updateIndex()
return; return;
m_checkInAllAction->setEnabled(false); m_checkInAllAction->setEnabled(false);
m_statusMap->clear(); m_statusMap->clear();
QFuture<void> result = runAsync(sync, transform(project->files(Project::SourceFiles), &FilePath::toString)); QFuture<void> result = Utils::asyncRun(sync, transform(project->files(Project::SourceFiles),
&FilePath::toString));
if (!m_settings.disableIndexer) if (!m_settings.disableIndexer)
ProgressManager::addTask(result, Tr::tr("Updating ClearCase Index"), ClearCase::Constants::TASK_INDEX); ProgressManager::addTask(result, Tr::tr("Updating ClearCase Index"), ClearCase::Constants::TASK_INDEX);
} }
@@ -2261,7 +2262,7 @@ void ClearCasePluginPrivate::syncSlot()
FilePath topLevel = state.topLevel(); FilePath topLevel = state.topLevel();
if (topLevel != state.currentProjectTopLevel()) if (topLevel != state.currentProjectTopLevel())
return; return;
runAsync(sync, QStringList()); Utils::asyncRun(sync, QStringList()); // TODO: make use of returned QFuture
} }
void ClearCasePluginPrivate::closing() void ClearCasePluginPrivate::closing()
@@ -2271,12 +2272,12 @@ void ClearCasePluginPrivate::closing()
disconnect(qApp, &QApplication::applicationStateChanged, nullptr, nullptr); disconnect(qApp, &QApplication::applicationStateChanged, nullptr, nullptr);
} }
void ClearCasePluginPrivate::sync(QFutureInterface<void> &future, QStringList files) void ClearCasePluginPrivate::sync(QPromise<void> &promise, QStringList files)
{ {
ClearCasePluginPrivate *plugin = ClearCasePluginPrivate::instance(); ClearCasePluginPrivate *plugin = ClearCasePluginPrivate::instance();
ClearCaseSync ccSync(plugin->m_statusMap); ClearCaseSync ccSync(plugin->m_statusMap);
connect(&ccSync, &ClearCaseSync::updateStreamAndView, plugin, &ClearCasePluginPrivate::updateStreamAndView); connect(&ccSync, &ClearCaseSync::updateStreamAndView, plugin, &ClearCasePluginPrivate::updateStreamAndView);
ccSync.run(future, files); ccSync.run(promise, files);
} }
QString ClearCasePluginPrivate::displayName() const QString ClearCasePluginPrivate::displayName() const

View File

@@ -13,6 +13,8 @@
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/qtcprocess.h> #include <utils/qtcprocess.h>
#include <QPromise>
#ifdef WITH_TESTS #ifdef WITH_TESTS
#include <QTest> #include <QTest>
#include <utils/fileutils.h> #include <utils/fileutils.h>
@@ -22,8 +24,7 @@ using namespace Utils;
namespace ClearCase::Internal { namespace ClearCase::Internal {
static void runProcess(QFutureInterface<void> &future, static void runProcess(QPromise<void> &promise, const ClearCaseSettings &settings,
const ClearCaseSettings &settings,
const QStringList &args, const QStringList &args,
std::function<void(const QString &buffer, int processed)> processLine) std::function<void(const QString &buffer, int processed)> processLine)
{ {
@@ -37,7 +38,7 @@ static void runProcess(QFutureInterface<void> &future,
int processed = 0; int processed = 0;
QString buffer; QString buffer;
while (process.waitForReadyRead() && !future.isCanceled()) { while (process.waitForReadyRead() && !promise.isCanceled()) {
buffer += QString::fromLocal8Bit(process.readAllRawStandardOutput()); buffer += QString::fromLocal8Bit(process.readAllRawStandardOutput());
int index = buffer.indexOf('\n'); int index = buffer.indexOf('\n');
while (index != -1) { while (index != -1) {
@@ -135,7 +136,7 @@ void ClearCaseSync::updateStatusForNotManagedFiles(const QStringList &files)
} }
} }
void ClearCaseSync::syncSnapshotView(QFutureInterface<void> &future, QStringList &files, void ClearCaseSync::syncSnapshotView(QPromise<void> &promise, QStringList &files,
const ClearCaseSettings &settings) const ClearCaseSettings &settings)
{ {
const QString view = ClearCasePlugin::viewData().name; const QString view = ClearCasePlugin::viewData().name;
@@ -167,18 +168,18 @@ void ClearCaseSync::syncSnapshotView(QFutureInterface<void> &future, QStringList
// adding 1 for initial sync in which total is not accurate, to prevent finishing // adding 1 for initial sync in which total is not accurate, to prevent finishing
// (we don't want it to become green) // (we don't want it to become green)
future.setProgressRange(0, totalFileCount + 1); promise.setProgressRange(0, totalFileCount + 1);
int totalProcessed = 0; int totalProcessed = 0;
runProcess(future, settings, args, [&](const QString &buffer, int processed) { runProcess(promise, settings, args, [&](const QString &buffer, int processed) {
processCleartoolLsLine(viewRootDir, buffer); processCleartoolLsLine(viewRootDir, buffer);
future.setProgressValue(qMin(totalFileCount, processed)); promise.setProgressValue(qMin(totalFileCount, processed));
totalProcessed = processed; totalProcessed = processed;
}); });
if (!future.isCanceled()) { if (!promise.isCanceled()) {
updateStatusForNotManagedFiles(files); updateStatusForNotManagedFiles(files);
future.setProgressValue(totalFileCount + 1); promise.setProgressValue(totalFileCount + 1);
if (!hot) if (!hot)
updateTotalFilesCount(view, settings, totalProcessed); updateTotalFilesCount(view, settings, totalProcessed);
} }
@@ -193,21 +194,20 @@ void ClearCaseSync::processCleartoolLscheckoutLine(const QString &buffer)
/// ///
/// Update the file status for dynamic views. /// Update the file status for dynamic views.
/// ///
void ClearCaseSync::syncDynamicView(QFutureInterface<void> &future, void ClearCaseSync::syncDynamicView(QPromise<void> &promise, const ClearCaseSettings& settings)
const ClearCaseSettings& settings)
{ {
// Always invalidate status for all files // Always invalidate status for all files
invalidateStatusAllFiles(); invalidateStatusAllFiles();
const QStringList args({"lscheckout", "-avobs", "-me", "-cview", "-s"}); const QStringList args({"lscheckout", "-avobs", "-me", "-cview", "-s"});
runProcess(future, settings, args, [&](const QString &buffer, int processed) { runProcess(promise, settings, args, [&](const QString &buffer, int processed) {
processCleartoolLscheckoutLine(buffer); processCleartoolLscheckoutLine(buffer);
future.setProgressValue(processed); promise.setProgressValue(processed);
}); });
} }
void ClearCaseSync::run(QFutureInterface<void> &future, QStringList &files) void ClearCaseSync::run(QPromise<void> &promise, QStringList &files)
{ {
ClearCaseSettings settings = ClearCasePlugin::settings(); ClearCaseSettings settings = ClearCasePlugin::settings();
if (settings.disableIndexer) if (settings.disableIndexer)
@@ -225,9 +225,9 @@ void ClearCaseSync::run(QFutureInterface<void> &future, QStringList &files)
emit updateStreamAndView(); emit updateStreamAndView();
if (ClearCasePlugin::viewData().isDynamic) if (ClearCasePlugin::viewData().isDynamic)
syncDynamicView(future, settings); syncDynamicView(promise, settings);
else else
syncSnapshotView(future, files, settings); syncSnapshotView(promise, files, settings);
} }
#ifdef WITH_TESTS #ifdef WITH_TESTS

View File

@@ -9,6 +9,8 @@ QT_BEGIN_NAMESPACE
class QDir; class QDir;
template <typename T> template <typename T>
class QFutureInterface; class QFutureInterface;
template <typename T>
class QPromise;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace ClearCase::Internal { namespace ClearCase::Internal {
@@ -18,7 +20,7 @@ class ClearCaseSync : public QObject
Q_OBJECT Q_OBJECT
public: public:
explicit ClearCaseSync(QSharedPointer<StatusMap> statusMap); explicit ClearCaseSync(QSharedPointer<StatusMap> statusMap);
void run(QFutureInterface<void> &future, QStringList &files); void run(QPromise<void> &promise, QStringList &files);
QStringList updateStatusHotFiles(const QString &viewRoot, int &total); QStringList updateStatusHotFiles(const QString &viewRoot, int &total);
void invalidateStatus(const QDir &viewRootDir, const QStringList &files); void invalidateStatus(const QDir &viewRootDir, const QStringList &files);
@@ -28,9 +30,8 @@ public:
const int processed); const int processed);
void updateStatusForNotManagedFiles(const QStringList &files); void updateStatusForNotManagedFiles(const QStringList &files);
void syncDynamicView(QFutureInterface<void> &future, void syncDynamicView(QPromise<void> &promise, const ClearCaseSettings &settings);
const ClearCaseSettings &settings); void syncSnapshotView(QPromise<void> &promise, QStringList &files,
void syncSnapshotView(QFutureInterface<void> &future, QStringList &files,
const ClearCaseSettings &settings); const ClearCaseSettings &settings);
void processCleartoolLscheckoutLine(const QString &buffer); void processCleartoolLscheckoutLine(const QString &buffer);

View File

@@ -13,6 +13,7 @@
#include <vcsbase/vcsbaseconstants.h> #include <vcsbase/vcsbaseconstants.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/asynctask.h>
#include <utils/environment.h> #include <utils/environment.h>
#include <utils/fancylineedit.h> #include <utils/fancylineedit.h>
#include <utils/filesearch.h> #include <utils/filesearch.h>
@@ -45,7 +46,7 @@ public:
class GitGrepRunner class GitGrepRunner
{ {
using FutureInterfaceType = QFutureInterface<FileSearchResultList>; using PromiseType = QPromise<FileSearchResultList>;
public: public:
GitGrepRunner(const TextEditor::FileFindParameters &parameters) GitGrepRunner(const TextEditor::FileFindParameters &parameters)
@@ -116,7 +117,7 @@ public:
} }
} }
void read(FutureInterfaceType &fi, const QString &text) void read(PromiseType &fi, const QString &text)
{ {
FileSearchResultList resultList; FileSearchResultList resultList;
QString t = text; QString t = text;
@@ -124,10 +125,10 @@ public:
while (!stream.atEnd() && !fi.isCanceled()) while (!stream.atEnd() && !fi.isCanceled())
processLine(stream.readLine(), &resultList); processLine(stream.readLine(), &resultList);
if (!resultList.isEmpty() && !fi.isCanceled()) if (!resultList.isEmpty() && !fi.isCanceled())
fi.reportResult(resultList); fi.addResult(resultList);
} }
void operator()(FutureInterfaceType &fi) void operator()(PromiseType &promise)
{ {
QStringList arguments = { QStringList arguments = {
"-c", "color.grep.match=bold red", "-c", "color.grep.match=bold red",
@@ -165,7 +166,7 @@ public:
process.setEnvironment(m_environment); process.setEnvironment(m_environment);
process.setCommand({m_vcsBinary, arguments}); process.setCommand({m_vcsBinary, arguments});
process.setWorkingDirectory(m_directory); process.setWorkingDirectory(m_directory);
process.setStdOutCallback([this, &fi](const QString &text) { read(fi, text); }); process.setStdOutCallback([this, &promise](const QString &text) { read(promise, text); });
process.start(); process.start();
process.waitForFinished(); process.waitForFinished();
@@ -173,7 +174,7 @@ public:
case ProcessResult::TerminatedAbnormally: case ProcessResult::TerminatedAbnormally:
case ProcessResult::StartFailed: case ProcessResult::StartFailed:
case ProcessResult::Hang: case ProcessResult::Hang:
fi.reportCanceled(); promise.future().cancel();
break; break;
case ProcessResult::FinishedWithSuccess: case ProcessResult::FinishedWithSuccess:
case ProcessResult::FinishedWithError: case ProcessResult::FinishedWithError:
@@ -275,7 +276,7 @@ void GitGrep::writeSettings(QSettings *settings) const
QFuture<FileSearchResultList> GitGrep::executeSearch(const TextEditor::FileFindParameters &parameters, QFuture<FileSearchResultList> GitGrep::executeSearch(const TextEditor::FileFindParameters &parameters,
TextEditor::BaseFileFind * /*baseFileFind*/) TextEditor::BaseFileFind * /*baseFileFind*/)
{ {
return Utils::runAsync(GitGrepRunner(parameters)); return Utils::asyncRun(GitGrepRunner(parameters));
} }
IEditor *GitGrep::openEditor(const SearchResultItem &item, IEditor *GitGrep::openEditor(const SearchResultItem &item,

View File

@@ -11,8 +11,8 @@
#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/iversioncontrol.h> #include <coreplugin/iversioncontrol.h>
#include <coreplugin/progressmanager/progressmanager.h> #include <coreplugin/progressmanager/progressmanager.h>
#include <utils/asynctask.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/runextensions.h>
#include <vcsbase/submitfilemodel.h> #include <vcsbase/submitfilemodel.h>
#include <vcsbase/vcsoutputwindow.h> #include <vcsbase/vcsoutputwindow.h>
@@ -204,7 +204,7 @@ void GitSubmitEditor::updateFileModel()
return; return;
w->setUpdateInProgress(true); w->setUpdateInProgress(true);
// TODO: Check if fetch works OK from separate thread, refactor otherwise // TODO: Check if fetch works OK from separate thread, refactor otherwise
m_fetchWatcher.setFuture(Utils::runAsync(&CommitDataFetchResult::fetch, m_fetchWatcher.setFuture(Utils::asyncRun(&CommitDataFetchResult::fetch,
m_commitType, m_workingDirectory)); m_commitType, m_workingDirectory));
Core::ProgressManager::addTask(m_fetchWatcher.future(), Tr::tr("Refreshing Commit Data"), Core::ProgressManager::addTask(m_fetchWatcher.future(), Tr::tr("Refreshing Commit Data"),
TASK_UPDATE_COMMIT); TASK_UPDATE_COMMIT);

View File

@@ -9,8 +9,8 @@
#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/progressmanager/progressmanager.h> #include <coreplugin/progressmanager/progressmanager.h>
#include <utils/asynctask.h>
#include <utils/layoutbuilder.h> #include <utils/layoutbuilder.h>
#include <utils/runextensions.h>
#include <QApplication> #include <QApplication>
#include <QCheckBox> #include <QCheckBox>
@@ -38,10 +38,10 @@ enum { nameColumn, columnCount };
enum { fileNameRole = Qt::UserRole, isDirectoryRole = Qt::UserRole + 1 }; enum { fileNameRole = Qt::UserRole, isDirectoryRole = Qt::UserRole + 1 };
// Helper for recursively removing files. // Helper for recursively removing files.
static void removeFileRecursion(QFutureInterface<void> &futureInterface, static void removeFileRecursion(QPromise<void> &promise, const QFileInfo &f,
const QFileInfo &f, QString *errorMessage) QString *errorMessage)
{ {
if (futureInterface.isCanceled()) if (promise.isCanceled())
return; return;
// The version control system might list files/directory in arbitrary // The version control system might list files/directory in arbitrary
// order, causing files to be removed from parent directories. // order, causing files to be removed from parent directories.
@@ -51,7 +51,7 @@ static void removeFileRecursion(QFutureInterface<void> &futureInterface,
const QDir dir(f.absoluteFilePath()); const QDir dir(f.absoluteFilePath());
const QList<QFileInfo> infos = dir.entryInfoList(QDir::AllEntries|QDir::NoDotAndDotDot|QDir::Hidden); const QList<QFileInfo> infos = dir.entryInfoList(QDir::AllEntries|QDir::NoDotAndDotDot|QDir::Hidden);
for (const QFileInfo &fi : infos) for (const QFileInfo &fi : infos)
removeFileRecursion(futureInterface, fi, errorMessage); removeFileRecursion(promise, fi, errorMessage);
QDir parent = f.absoluteDir(); QDir parent = f.absoluteDir();
if (!parent.rmdir(f.fileName())) if (!parent.rmdir(f.fileName()))
errorMessage->append(Tr::tr("The directory %1 could not be deleted.") errorMessage->append(Tr::tr("The directory %1 could not be deleted.")
@@ -67,18 +67,19 @@ static void removeFileRecursion(QFutureInterface<void> &futureInterface,
} }
// Cleaning files in the background // Cleaning files in the background
static void runCleanFiles(QFutureInterface<void> &futureInterface, static void runCleanFiles(QPromise<void> &promise, const FilePath &repository,
const FilePath &repository, const QStringList &files, const QStringList &files,
const std::function<void(const QString&)> &errorHandler) const std::function<void(const QString&)> &errorHandler)
{ {
QString errorMessage; QString errorMessage;
futureInterface.setProgressRange(0, files.size()); promise.setProgressRange(0, files.size());
futureInterface.setProgressValue(0); promise.setProgressValue(0);
int fileIndex = 0;
for (const QString &name : files) { for (const QString &name : files) {
removeFileRecursion(futureInterface, QFileInfo(name), &errorMessage); removeFileRecursion(promise, QFileInfo(name), &errorMessage);
if (futureInterface.isCanceled()) if (promise.isCanceled())
break; break;
futureInterface.setProgressValue(futureInterface.progressValue() + 1); promise.setProgressValue(++fileIndex);
} }
if (!errorMessage.isEmpty()) { if (!errorMessage.isEmpty()) {
// Format and emit error. // Format and emit error.
@@ -258,7 +259,7 @@ bool CleanDialog::promptToDelete()
return false; return false;
// Remove in background // Remove in background
QFuture<void> task = runAsync(Internal::runCleanFiles, d->m_workingDirectory, QFuture<void> task = Utils::asyncRun(Internal::runCleanFiles, d->m_workingDirectory,
selectedFiles, Internal::handleError); selectedFiles, Internal::handleError);
const QString taskName = Tr::tr("Cleaning \"%1\"").arg(d->m_workingDirectory.toUserOutput()); const QString taskName = Tr::tr("Cleaning \"%1\"").arg(d->m_workingDirectory.toUserOutput());