forked from qt-creator/qt-creator
VcsCommand: Reuse ProcessProgress
Change-Id: I02116d1c7ff05471f7be61ecc33a7b54c57a78cf Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
@@ -13,12 +13,9 @@
|
|||||||
#include <utils/globalfilechangeblocker.h>
|
#include <utils/globalfilechangeblocker.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <utils/qtcprocess.h>
|
#include <utils/qtcprocess.h>
|
||||||
|
#include <utils/threadutils.h>
|
||||||
|
|
||||||
#include <QCoreApplication>
|
|
||||||
#include <QFuture>
|
|
||||||
#include <QFutureWatcher>
|
|
||||||
#include <QTextCodec>
|
#include <QTextCodec>
|
||||||
#include <QThread>
|
|
||||||
|
|
||||||
using namespace Core;
|
using namespace Core;
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
@@ -43,7 +40,6 @@ public:
|
|||||||
, m_environment(environment)
|
, m_environment(environment)
|
||||||
{
|
{
|
||||||
VcsBase::setProcessEnvironment(&m_environment);
|
VcsBase::setProcessEnvironment(&m_environment);
|
||||||
m_futureInterface.setProgressRange(0, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Environment environment()
|
Environment environment()
|
||||||
@@ -56,7 +52,6 @@ public:
|
|||||||
return m_environment;
|
return m_environment;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString displayName() const;
|
|
||||||
int timeoutS() const;
|
int timeoutS() const;
|
||||||
|
|
||||||
void setup();
|
void setup();
|
||||||
@@ -76,7 +71,6 @@ public:
|
|||||||
Environment m_environment;
|
Environment m_environment;
|
||||||
QTextCodec *m_codec = nullptr;
|
QTextCodec *m_codec = nullptr;
|
||||||
ProgressParser m_progressParser = {};
|
ProgressParser m_progressParser = {};
|
||||||
QFutureWatcher<void> m_watcher;
|
|
||||||
QList<Job> m_jobs;
|
QList<Job> m_jobs;
|
||||||
|
|
||||||
int m_currentJob = 0;
|
int m_currentJob = 0;
|
||||||
@@ -84,28 +78,10 @@ public:
|
|||||||
QString m_stdOut;
|
QString m_stdOut;
|
||||||
QString m_stdErr;
|
QString m_stdErr;
|
||||||
ProcessResult m_result = ProcessResult::StartFailed;
|
ProcessResult m_result = ProcessResult::StartFailed;
|
||||||
QFutureInterface<void> m_futureInterface;
|
|
||||||
|
|
||||||
RunFlags m_flags = RunFlags::None;
|
RunFlags m_flags = RunFlags::None;
|
||||||
};
|
};
|
||||||
|
|
||||||
QString VcsCommandPrivate::displayName() const
|
|
||||||
{
|
|
||||||
if (!m_displayName.isEmpty())
|
|
||||||
return m_displayName;
|
|
||||||
if (m_jobs.isEmpty())
|
|
||||||
return tr("Unknown");
|
|
||||||
const Job &job = m_jobs.at(0);
|
|
||||||
QString result = job.command.executable().baseName();
|
|
||||||
if (!result.isEmpty())
|
|
||||||
result[0] = result.at(0).toTitleCase();
|
|
||||||
else
|
|
||||||
result = tr("UNKNOWN");
|
|
||||||
if (!job.command.arguments().isEmpty())
|
|
||||||
result += ' ' + job.command.splitArguments().at(0);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int VcsCommandPrivate::timeoutS() const
|
int VcsCommandPrivate::timeoutS() const
|
||||||
{
|
{
|
||||||
return std::accumulate(m_jobs.cbegin(), m_jobs.cend(), 0,
|
return std::accumulate(m_jobs.cbegin(), m_jobs.cend(), 0,
|
||||||
@@ -114,15 +90,12 @@ int VcsCommandPrivate::timeoutS() const
|
|||||||
|
|
||||||
void VcsCommandPrivate::setup()
|
void VcsCommandPrivate::setup()
|
||||||
{
|
{
|
||||||
m_futureInterface.reportStarted();
|
|
||||||
if (m_flags & RunFlags::ExpectRepoChanges)
|
if (m_flags & RunFlags::ExpectRepoChanges)
|
||||||
GlobalFileChangeBlocker::instance()->forceBlocked(true);
|
GlobalFileChangeBlocker::instance()->forceBlocked(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VcsCommandPrivate::cleanup()
|
void VcsCommandPrivate::cleanup()
|
||||||
{
|
{
|
||||||
QTC_ASSERT(m_futureInterface.isRunning(), return);
|
|
||||||
m_futureInterface.reportFinished();
|
|
||||||
if (m_flags & RunFlags::ExpectRepoChanges)
|
if (m_flags & RunFlags::ExpectRepoChanges)
|
||||||
GlobalFileChangeBlocker::instance()->forceBlocked(false);
|
GlobalFileChangeBlocker::instance()->forceBlocked(false);
|
||||||
}
|
}
|
||||||
@@ -145,15 +118,22 @@ void VcsCommandPrivate::setupProcess(QtcProcess *process, const Job &job)
|
|||||||
process->setCodec(m_codec);
|
process->setCodec(m_codec);
|
||||||
|
|
||||||
installStdCallbacks(process);
|
installStdCallbacks(process);
|
||||||
|
|
||||||
|
if (m_flags & RunFlags::SuppressCommandLogging)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ProcessProgress *progress = new ProcessProgress(process);
|
||||||
|
progress->setDisplayName(m_displayName);
|
||||||
|
if (m_progressParser)
|
||||||
|
progress->setProgressParser(m_progressParser);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VcsCommandPrivate::installStdCallbacks(QtcProcess *process)
|
void VcsCommandPrivate::installStdCallbacks(QtcProcess *process)
|
||||||
{
|
{
|
||||||
if (!(m_flags & RunFlags::MergeOutputChannels) && (m_flags & RunFlags::ProgressiveOutput
|
if (!(m_flags & RunFlags::MergeOutputChannels) && (m_flags & RunFlags::ProgressiveOutput
|
||||||
|| !(m_flags & RunFlags::SuppressStdErr))) {
|
|| m_progressParser || !(m_flags & RunFlags::SuppressStdErr))) {
|
||||||
process->setStdErrCallback([this](const QString &text) {
|
process->setTextChannelMode(Channel::Error, TextChannelMode::MultiLine);
|
||||||
if (m_progressParser)
|
connect(process, &QtcProcess::textOnStandardError, [this](const QString &text) {
|
||||||
m_progressParser(m_futureInterface, text);
|
|
||||||
if (!(m_flags & RunFlags::SuppressStdErr))
|
if (!(m_flags & RunFlags::SuppressStdErr))
|
||||||
emit q->appendError(text);
|
emit q->appendError(text);
|
||||||
if (m_flags & RunFlags::ProgressiveOutput)
|
if (m_flags & RunFlags::ProgressiveOutput)
|
||||||
@@ -163,9 +143,8 @@ void VcsCommandPrivate::installStdCallbacks(QtcProcess *process)
|
|||||||
// connect stdout to the output window if desired
|
// connect stdout to the output window if desired
|
||||||
if (m_progressParser || m_flags & RunFlags::ProgressiveOutput
|
if (m_progressParser || m_flags & RunFlags::ProgressiveOutput
|
||||||
|| m_flags & RunFlags::ShowStdOut) {
|
|| m_flags & RunFlags::ShowStdOut) {
|
||||||
process->setStdOutCallback([this](const QString &text) {
|
process->setTextChannelMode(Channel::Output, TextChannelMode::MultiLine);
|
||||||
if (m_progressParser)
|
connect(process, &QtcProcess::textOnStandardOutput, [this](const QString &text) {
|
||||||
m_progressParser(m_futureInterface, text);
|
|
||||||
if (m_flags & RunFlags::ShowStdOut) {
|
if (m_flags & RunFlags::ShowStdOut) {
|
||||||
if (m_flags & RunFlags::SilentOutput)
|
if (m_flags & RunFlags::SilentOutput)
|
||||||
emit q->appendSilently(text);
|
emit q->appendSilently(text);
|
||||||
@@ -182,7 +161,7 @@ void VcsCommandPrivate::installStdCallbacks(QtcProcess *process)
|
|||||||
|
|
||||||
EventLoopMode VcsCommandPrivate::eventLoopMode() const
|
EventLoopMode VcsCommandPrivate::eventLoopMode() const
|
||||||
{
|
{
|
||||||
if ((m_flags & RunFlags::UseEventLoop) && QThread::currentThread() == qApp->thread())
|
if ((m_flags & RunFlags::UseEventLoop) && isMainThread())
|
||||||
return EventLoopMode::On;
|
return EventLoopMode::On;
|
||||||
return EventLoopMode::Off;
|
return EventLoopMode::Off;
|
||||||
}
|
}
|
||||||
@@ -232,8 +211,6 @@ void VcsCommandPrivate::processDone()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
emit q->done();
|
emit q->done();
|
||||||
if (!success)
|
|
||||||
m_futureInterface.reportCanceled();
|
|
||||||
cleanup();
|
cleanup();
|
||||||
// As it is used asynchronously, we need to delete ourselves
|
// As it is used asynchronously, we need to delete ourselves
|
||||||
q->deleteLater();
|
q->deleteLater();
|
||||||
@@ -244,8 +221,6 @@ void VcsCommandPrivate::processDone()
|
|||||||
VcsCommand::VcsCommand(const FilePath &workingDirectory, const Environment &environment) :
|
VcsCommand::VcsCommand(const FilePath &workingDirectory, const Environment &environment) :
|
||||||
d(new Internal::VcsCommandPrivate(this, workingDirectory, environment))
|
d(new Internal::VcsCommandPrivate(this, workingDirectory, environment))
|
||||||
{
|
{
|
||||||
connect(&d->m_watcher, &QFutureWatcher<void>::canceled, this, &VcsCommand::cancel);
|
|
||||||
|
|
||||||
VcsOutputWindow::setRepository(d->m_defaultWorkingDirectory);
|
VcsOutputWindow::setRepository(d->m_defaultWorkingDirectory);
|
||||||
VcsOutputWindow *outputWindow = VcsOutputWindow::instance(); // Keep me here, just to be sure it's not instantiated in other thread
|
VcsOutputWindow *outputWindow = VcsOutputWindow::instance(); // Keep me here, just to be sure it's not instantiated in other thread
|
||||||
connect(this, &VcsCommand::append, outputWindow, [outputWindow](const QString &t) {
|
connect(this, &VcsCommand::append, outputWindow, [outputWindow](const QString &t) {
|
||||||
@@ -259,11 +234,9 @@ VcsCommand::VcsCommand(const FilePath &workingDirectory, const Environment &envi
|
|||||||
this, &VcsCommand::postRunCommand);
|
this, &VcsCommand::postRunCommand);
|
||||||
connect(ICore::instance(), &ICore::coreAboutToClose, this, [this, connection] {
|
connect(ICore::instance(), &ICore::coreAboutToClose, this, [this, connection] {
|
||||||
disconnect(connection);
|
disconnect(connection);
|
||||||
d->m_process.reset();
|
if (d->m_process && d->m_process->isRunning())
|
||||||
if (d->m_futureInterface.isRunning()) {
|
|
||||||
d->m_futureInterface.reportCanceled();
|
|
||||||
d->cleanup();
|
d->cleanup();
|
||||||
}
|
d->m_process.reset();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,10 +251,8 @@ void VcsCommand::postRunCommand(const FilePath &workingDirectory)
|
|||||||
|
|
||||||
VcsCommand::~VcsCommand()
|
VcsCommand::~VcsCommand()
|
||||||
{
|
{
|
||||||
if (d->m_futureInterface.isRunning()) {
|
if (d->m_process && d->m_process->isRunning())
|
||||||
d->m_futureInterface.reportCanceled();
|
|
||||||
d->cleanup();
|
d->cleanup();
|
||||||
}
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,21 +281,10 @@ void VcsCommand::start()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
d->startAll();
|
d->startAll();
|
||||||
d->m_watcher.setFuture(d->m_futureInterface.future());
|
|
||||||
if ((d->m_flags & RunFlags::SuppressCommandLogging))
|
|
||||||
return;
|
|
||||||
|
|
||||||
const QString name = d->displayName();
|
|
||||||
const auto id = Id::fromString(name + QLatin1String(".action"));
|
|
||||||
if (d->m_progressParser)
|
|
||||||
ProgressManager::addTask(d->m_futureInterface.future(), name, id);
|
|
||||||
else
|
|
||||||
ProgressManager::addTimedTask(d->m_futureInterface, name, id, qMax(2, d->timeoutS() / 5));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VcsCommand::cancel()
|
void VcsCommand::cancel()
|
||||||
{
|
{
|
||||||
d->m_futureInterface.reportCanceled();
|
|
||||||
if (d->m_process) {
|
if (d->m_process) {
|
||||||
// TODO: we may want to call cancel here...
|
// TODO: we may want to call cancel here...
|
||||||
d->m_process->stop();
|
d->m_process->stop();
|
||||||
|
@@ -6,17 +6,14 @@
|
|||||||
#include "vcsbase_global.h"
|
#include "vcsbase_global.h"
|
||||||
#include "vcsenums.h"
|
#include "vcsenums.h"
|
||||||
|
|
||||||
|
#include <coreplugin/progressmanager/processprogress.h>
|
||||||
|
|
||||||
#include <utils/filepath.h>
|
#include <utils/filepath.h>
|
||||||
#include <utils/processenums.h>
|
#include <utils/processenums.h>
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QVariant;
|
|
||||||
template <typename T>
|
|
||||||
class QFuture;
|
|
||||||
template <typename T>
|
|
||||||
class QFutureInterface;
|
|
||||||
class QTextCodec;
|
class QTextCodec;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
@@ -30,8 +27,6 @@ namespace VcsBase {
|
|||||||
|
|
||||||
namespace Internal { class VcsCommandPrivate; }
|
namespace Internal { class VcsCommandPrivate; }
|
||||||
|
|
||||||
using ProgressParser = std::function<void(QFutureInterface<void> &, const QString &)>;
|
|
||||||
|
|
||||||
class VCSBASE_EXPORT CommandResult
|
class VCSBASE_EXPORT CommandResult
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -79,7 +74,7 @@ public:
|
|||||||
|
|
||||||
void setCodec(QTextCodec *codec);
|
void setCodec(QTextCodec *codec);
|
||||||
|
|
||||||
void setProgressParser(const ProgressParser &parser);
|
void setProgressParser(const Core::ProgressParser &parser);
|
||||||
|
|
||||||
static CommandResult runBlocking(const Utils::FilePath &workingDirectory,
|
static CommandResult runBlocking(const Utils::FilePath &workingDirectory,
|
||||||
const Utils::Environment &environmentconst,
|
const Utils::Environment &environmentconst,
|
||||||
|
Reference in New Issue
Block a user