diff --git a/src/plugins/vcsbase/vcsbaseclient.cpp b/src/plugins/vcsbase/vcsbaseclient.cpp index 4779a01220d..cf38ee7921c 100644 --- a/src/plugins/vcsbase/vcsbaseclient.cpp +++ b/src/plugins/vcsbase/vcsbaseclient.cpp @@ -25,26 +25,22 @@ #include "vcsbaseclient.h" #include "vcsbaseclientsettings.h" +#include "vcsbaseeditor.h" #include "vcsbaseeditorconfig.h" +#include "vcsbaseplugin.h" #include "vcscommand.h" -#include "vcsplugin.h" +#include "vcsoutputwindow.h" #include #include #include #include #include -#include #include #include -#include #include -#include -#include -#include - #include #include #include @@ -77,85 +73,6 @@ static IEditor *locateEditor(const char *property, const QString &entry) namespace VcsBase { -class VcsCommandDecorator : public QObject -{ -public: - VcsCommandDecorator(VcsCommand *command); - ~VcsCommandDecorator(); - -private: - void addTask(const QFuture &future); - void postRunCommand(const FilePath &workingDirectory); - - VcsCommand *m_command; - QFutureInterface m_futureInterface; -}; - -VcsCommandDecorator::VcsCommandDecorator(VcsCommand *command) - : QObject(command) - , m_command(command) -{ - Environment env = m_command->environment(); - VcsBase::setProcessEnvironment(&env); - m_command->setEnvironment(env); - - VcsOutputWindow::setRepository(m_command->defaultWorkingDirectory().toString()); - m_command->setDisableUnixTerminal(); - connect(m_command, &VcsCommand::started, this, [this] { - if (m_command->flags() & VcsCommand::ExpectRepoChanges) - GlobalFileChangeBlocker::instance()->forceBlocked(true); - }); - connect(m_command, &VcsCommand::finished, this, [this] { - if (m_command->flags() & VcsCommand::ExpectRepoChanges) - GlobalFileChangeBlocker::instance()->forceBlocked(false); - }); - VcsOutputWindow *outputWindow = VcsOutputWindow::instance(); - connect(m_command, &VcsCommand::append, outputWindow, [outputWindow](const QString &t) { - outputWindow->append(t); - }); - connect(m_command, &VcsCommand::appendSilently, outputWindow, &VcsOutputWindow::appendSilently); - connect(m_command, &VcsCommand::appendError, outputWindow, &VcsOutputWindow::appendError); - connect(m_command, &VcsCommand::appendCommand, outputWindow, &VcsOutputWindow::appendCommand); - connect(m_command, &VcsCommand::appendMessage, outputWindow, &VcsOutputWindow::appendMessage); - connect(m_command, &VcsCommand::executedAsync, this, &VcsCommandDecorator::addTask); - const auto connection = connect(m_command, &VcsCommand::runCommandFinished, - this, &VcsCommandDecorator::postRunCommand); - connect(ICore::instance(), &ICore::coreAboutToClose, this, [this, connection] { - disconnect(connection); - m_command->abort(); - }); -} - -VcsCommandDecorator::~VcsCommandDecorator() -{ - m_futureInterface.reportFinished(); -} - -void VcsCommandDecorator::addTask(const QFuture &future) -{ - if ((m_command->flags() & VcsCommand::SuppressCommandLogging)) - return; - - const QString name = m_command->displayName(); - const auto id = Id::fromString(name + QLatin1String(".action")); - if (m_command->hasProgressParser()) { - ProgressManager::addTask(future, name, id); - } else { - ProgressManager::addTimedTask(m_futureInterface, name, id, qMax(2, m_command->timeoutS() / 5)); - } - - Internal::VcsPlugin::addFuture(future); -} - -void VcsCommandDecorator::postRunCommand(const FilePath &workingDirectory) -{ - if (!(m_command->flags() & VcsCommand::ExpectRepoChanges)) - return; - // TODO tell the document manager that the directory now received all expected changes - // Core::DocumentManager::unexpectDirectoryChange(d->m_workingDirectory); - VcsManager::emitRepositoryChanged(workingDirectory); -} - VcsBaseClientImpl::VcsBaseClientImpl(VcsBaseSettings *baseSettings) : m_baseSettings(baseSettings) { @@ -250,7 +167,6 @@ CommandResult VcsBaseClientImpl::vcsFullySynchronousExec(const FilePath &working const CommandLine &cmdLine, unsigned flags, int timeoutS, QTextCodec *codec) const { VcsCommand command(workingDir, processEnvironment()); - new VcsCommandDecorator(&command); command.addFlags(flags); if (codec) command.setCodec(codec); @@ -297,7 +213,6 @@ CommandResult VcsBaseClientImpl::vcsSynchronousExec(const FilePath &workingDir, { Environment env = processEnvironment(); VcsCommand command(workingDir, env.isValid() ? env : Environment::systemEnvironment()); - new VcsCommandDecorator(&command); command.addFlags(flags); command.setCodec(outputCodec); return command.runCommand({vcsBinary(), args}, workingDir, vcsTimeoutS()); @@ -311,9 +226,7 @@ int VcsBaseClientImpl::vcsTimeoutS() const VcsCommand *VcsBaseClientImpl::createVcsCommand(const FilePath &defaultWorkingDir, const Environment &environment) { - VcsCommand *command = new VcsCommand(defaultWorkingDir, environment); - new VcsCommandDecorator(command); - return command; + return new VcsCommand(defaultWorkingDir, environment); } VcsBaseEditorWidget *VcsBaseClientImpl::createVcsEditor(Id kind, QString title, diff --git a/src/plugins/vcsbase/vcsbaseeditorconfig.cpp b/src/plugins/vcsbase/vcsbaseeditorconfig.cpp index 0a6f580b581..fd90bca5b2b 100644 --- a/src/plugins/vcsbase/vcsbaseeditorconfig.cpp +++ b/src/plugins/vcsbase/vcsbaseeditorconfig.cpp @@ -28,12 +28,11 @@ #include #include -#include #include -#include - -#include +#include #include +#include +#include using namespace Utils; diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp index bdbaa73964e..72f641b7cca 100644 --- a/src/plugins/vcsbase/vcsbaseplugin.cpp +++ b/src/plugins/vcsbase/vcsbaseplugin.cpp @@ -24,9 +24,10 @@ ****************************************************************************/ #include "vcsbaseplugin.h" + +#include "commonvcssettings.h" #include "vcsbasesubmiteditor.h" #include "vcsplugin.h" -#include "commonvcssettings.h" #include #include @@ -43,8 +44,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/src/plugins/vcsbase/vcscommand.cpp b/src/plugins/vcsbase/vcscommand.cpp index faca33c759f..f488d8c9c53 100644 --- a/src/plugins/vcsbase/vcscommand.cpp +++ b/src/plugins/vcsbase/vcscommand.cpp @@ -25,7 +25,15 @@ #include "vcscommand.h" +#include "vcsbaseplugin.h" +#include "vcsoutputwindow.h" +#include "vcsplugin.h" + +#include +#include + #include +#include #include #include #include @@ -56,6 +64,7 @@ when a progress string is detected. */ +using namespace Core; using namespace Utils; namespace VcsBase { @@ -77,7 +86,9 @@ public: VcsCommandPrivate(const FilePath &defaultWorkingDirectory, const Environment &environment) : m_defaultWorkingDirectory(defaultWorkingDirectory), m_environment(environment) - {} + { + VcsBase::setProcessEnvironment(&m_environment); + } ~VcsCommandPrivate() { delete m_progressParser; } @@ -98,6 +109,7 @@ public: QTextCodec *m_codec = nullptr; ProgressParser *m_progressParser = nullptr; QFutureWatcher m_watcher; + QFutureInterface m_futureInterface; QList m_jobs; unsigned m_flags = 0; @@ -106,7 +118,6 @@ public: bool m_progressiveOutput = false; bool m_hadOutput = false; bool m_aborted = false; - bool m_disableUnixTerminal = false; }; VcsCommandPrivate::Job::Job(const FilePath &wd, const CommandLine &command, @@ -127,10 +138,52 @@ VcsCommand::VcsCommand(const FilePath &workingDirectory, const Environment &envi d(new Internal::VcsCommandPrivate(workingDirectory, environment)) { connect(&d->m_watcher, &QFutureWatcher::canceled, this, &VcsCommand::cancel); + + VcsOutputWindow::setRepository(defaultWorkingDirectory().toString()); + 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) { + outputWindow->append(t); + }); + connect(this, &VcsCommand::appendSilently, outputWindow, &VcsOutputWindow::appendSilently); + connect(this, &VcsCommand::appendError, outputWindow, &VcsOutputWindow::appendError); + connect(this, &VcsCommand::appendCommand, outputWindow, &VcsOutputWindow::appendCommand); + connect(this, &VcsCommand::appendMessage, outputWindow, &VcsOutputWindow::appendMessage); + const auto connection = connect(this, &VcsCommand::runCommandFinished, + this, &VcsCommand::postRunCommand); + connect(ICore::instance(), &ICore::coreAboutToClose, this, [this, connection] { + disconnect(connection); + abort(); + }); +} + +void VcsCommand::addTask(const QFuture &future) +{ + if ((d->m_flags & VcsCommand::SuppressCommandLogging)) + return; + + const QString name = displayName(); + const auto id = Id::fromString(name + QLatin1String(".action")); + if (d->m_progressParser) { + ProgressManager::addTask(future, name, id); + } else { + ProgressManager::addTimedTask(d->m_futureInterface, name, id, qMax(2, timeoutS() / 5)); + } + + Internal::VcsPlugin::addFuture(future); +} + +void VcsCommand::postRunCommand(const FilePath &workingDirectory) +{ + if (!(d->m_flags & VcsCommand::ExpectRepoChanges)) + return; + // TODO tell the document manager that the directory now received all expected changes + // Core::DocumentManager::unexpectDirectoryChange(d->m_workingDirectory); + VcsManager::emitRepositoryChanged(workingDirectory); } VcsCommand::~VcsCommand() { + d->m_futureInterface.reportFinished(); delete d; } @@ -164,16 +217,6 @@ const FilePath &VcsCommand::defaultWorkingDirectory() const return d->m_defaultWorkingDirectory; } -Environment VcsCommand::environment() const -{ - return d->m_environment; -} - -void VcsCommand::setEnvironment(const Environment &env) -{ - d->m_environment = env; -} - int VcsCommand::defaultTimeoutS() const { return d->m_defaultTimeoutS; @@ -184,11 +227,6 @@ void VcsCommand::setDefaultTimeoutS(int timeout) d->m_defaultTimeoutS = timeout; } -unsigned VcsCommand::flags() const -{ - return d->m_flags; -} - void VcsCommand::addFlags(unsigned f) { d->m_flags |= f; @@ -216,7 +254,7 @@ void VcsCommand::execute() QFuture task = runAsync(&VcsCommand::run, this); d->m_watcher.setFuture(task); - emit executedAsync(task); + addTask(task); } void VcsCommand::abort() @@ -253,7 +291,11 @@ void VcsCommand::run(QFutureInterface &future) QString stdOut; QString stdErr; - emit started(); + if (d->m_flags & VcsCommand::ExpectRepoChanges) { + QMetaObject::invokeMethod(this, [] { + GlobalFileChangeBlocker::instance()->forceBlocked(true); + }); + } if (d->m_progressParser) d->m_progressParser->setFuture(&future); else @@ -278,6 +320,11 @@ void VcsCommand::run(QFutureInterface &future) emit stdErrText(stdErr); } + if (d->m_flags & VcsCommand::ExpectRepoChanges) { + QMetaObject::invokeMethod(this, [] { + GlobalFileChangeBlocker::instance()->forceBlocked(false); + }); + } emit finished(lastExecSuccess, cookie()); if (lastExecSuccess) future.setProgressValue(future.progressMaximum()); @@ -292,7 +339,7 @@ void VcsCommand::run(QFutureInterface &future) } CommandResult VcsCommand::runCommand(const CommandLine &command, const FilePath &workingDirectory, - int timeoutS, const ExitCodeInterpreter &interpreter) + int timeoutS, const ExitCodeInterpreter &interpreter) { QtcProcess proc; if (command.executable().isEmpty()) @@ -309,8 +356,7 @@ CommandResult VcsCommand::runCommand(const CommandLine &command, const FilePath emit appendCommand(dir, command); proc.setCommand(command); - if (d->m_disableUnixTerminal) - proc.setDisableUnixTerminal(); + proc.setDisableUnixTerminal(); proc.setEnvironment(d->environment()); if (d->m_flags & MergeOutputChannels) proc.setProcessChannelMode(QProcess::MergedChannels); @@ -404,11 +450,6 @@ void VcsCommand::setCookie(const QVariant &cookie) d->m_cookie = cookie; } -QTextCodec *VcsCommand::codec() const -{ - return d->m_codec; -} - void VcsCommand::setCodec(QTextCodec *codec) { d->m_codec = codec; @@ -421,21 +462,11 @@ void VcsCommand::setProgressParser(ProgressParser *parser) d->m_progressParser = parser; } -bool VcsCommand::hasProgressParser() const -{ - return d->m_progressParser; -} - void VcsCommand::setProgressiveOutput(bool progressive) { d->m_progressiveOutput = progressive; } -void VcsCommand::setDisableUnixTerminal() -{ - d->m_disableUnixTerminal = true; -} - ProgressParser::ProgressParser() : m_futureMutex(new QMutex) { } diff --git a/src/plugins/vcsbase/vcscommand.h b/src/plugins/vcsbase/vcscommand.h index e2d77498c51..9ee4635bd9a 100644 --- a/src/plugins/vcsbase/vcscommand.h +++ b/src/plugins/vcsbase/vcscommand.h @@ -36,9 +36,9 @@ QT_BEGIN_NAMESPACE class QMutex; class QVariant; template -class QFutureInterface; -template class QFuture; +template +class QFutureInterface; class QTextCodec; QT_END_NAMESPACE @@ -119,18 +119,13 @@ public: NoOutput = SuppressStdErr | SuppressFailMessage | SuppressCommandLogging }; - VcsCommand(const Utils::FilePath &workingDirectory, const Utils::Environment &environment); ~VcsCommand() override; - QString displayName() const; void setDisplayName(const QString &name); const Utils::FilePath &defaultWorkingDirectory() const; - Utils::Environment environment() const; - void setEnvironment(const Utils::Environment &env); - void addJob(const Utils::CommandLine &command, const Utils::FilePath &workingDirectory = {}, const Utils::ExitCodeInterpreter &interpreter = {}); @@ -143,17 +138,14 @@ public: int defaultTimeoutS() const; void setDefaultTimeoutS(int timeout); - unsigned flags() const; void addFlags(unsigned f); const QVariant &cookie() const; void setCookie(const QVariant &cookie); - QTextCodec *codec() const; void setCodec(QTextCodec *codec); void setProgressParser(ProgressParser *parser); - bool hasProgressParser() const; void setProgressiveOutput(bool progressive); // This is called once per job in a thread. @@ -162,16 +154,11 @@ public: CommandResult runCommand(const Utils::CommandLine &command, const Utils::FilePath &workingDirectory = {}, int timeoutS = 10, const Utils::ExitCodeInterpreter &interpreter = {}); - void cancel(); - void setDisableUnixTerminal(); - int timeoutS() const; - signals: void stdOutText(const QString &); void stdErrText(const QString &); - void started(); void finished(bool success, const QVariant &cookie); void terminate(); // Internal @@ -179,16 +166,19 @@ signals: void append(const QString &text); void appendSilently(const QString &text); void appendError(const QString &text); - // TODO: remove Utils:: scope when support for Qt5 is dropped (Creator 9.0) void appendCommand(const Utils::FilePath &workingDirectory, const Utils::CommandLine &command); void appendMessage(const QString &text); - void executedAsync(const QFuture &future); void runCommandFinished(const Utils::FilePath &workingDirectory); private: Utils::FilePath workDirectory(const Utils::FilePath &wd) const; void run(QFutureInterface &future); + void addTask(const QFuture &future); + void postRunCommand(const Utils::FilePath &workingDirectory); + + QString displayName() const; + int timeoutS() const; // Run without a event loop in fully blocking mode. No signals will be delivered. void runFullySynchronous(Utils::QtcProcess &proc); diff --git a/src/plugins/vcsbase/vcsoutputwindow.cpp b/src/plugins/vcsbase/vcsoutputwindow.cpp index 2d3c5f54181..2afa3c31831 100644 --- a/src/plugins/vcsbase/vcsoutputwindow.cpp +++ b/src/plugins/vcsbase/vcsoutputwindow.cpp @@ -25,16 +25,18 @@ #include "vcsoutputwindow.h" -#include +#include "vcsoutputformatter.h" +#include #include -#include -#include + #include #include #include + +#include +#include #include -#include #include #include diff --git a/src/plugins/vcsbase/vcsoutputwindow.h b/src/plugins/vcsbase/vcsoutputwindow.h index 198d8532d33..9425ced05f1 100644 --- a/src/plugins/vcsbase/vcsoutputwindow.h +++ b/src/plugins/vcsbase/vcsoutputwindow.h @@ -27,7 +27,7 @@ #include "vcsbase_global.h" -#include +#include namespace Utils { class CommandLine; diff --git a/src/plugins/vcsbase/vcsplugin.cpp b/src/plugins/vcsbase/vcsplugin.cpp index fc2726c5c8e..432a103e049 100644 --- a/src/plugins/vcsbase/vcsplugin.cpp +++ b/src/plugins/vcsbase/vcsplugin.cpp @@ -25,11 +25,10 @@ #include "vcsplugin.h" -#include "vcsbaseconstants.h" -#include "vcsbasesubmiteditor.h" - #include "commonvcssettings.h" #include "nicknamedialog.h" +#include "vcsbaseconstants.h" +#include "vcsbasesubmiteditor.h" #include "vcsoutputwindow.h" #include "wizard/vcscommandpage.h" #include "wizard/vcsconfigurationpage.h"