VcsCommand: Merge with VcsCommandDecorator

Change-Id: I84df1779377648624984c9e57806f1307ae62b5b
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
Jarek Kobus
2022-08-01 18:35:07 +02:00
parent 7c2ab8cf8f
commit 83739bde38
8 changed files with 94 additions and 159 deletions

View File

@@ -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 <coreplugin/icore.h>
#include <coreplugin/vcsmanager.h>
#include <coreplugin/editormanager/documentmodel.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/idocument.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <utils/commandline.h>
#include <utils/environment.h>
#include <utils/globalfilechangeblocker.h>
#include <utils/qtcassert.h>
#include <vcsbase/vcsbaseeditor.h>
#include <vcsbase/vcsoutputwindow.h>
#include <vcsbase/vcsbaseplugin.h>
#include <QDebug>
#include <QFileInfo>
#include <QFutureInterface>
@@ -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<void> &future);
void postRunCommand(const FilePath &workingDirectory);
VcsCommand *m_command;
QFutureInterface<void> 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<void> &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,

View File

@@ -28,12 +28,11 @@
#include <utils/aspects.h>
#include <utils/utilsicons.h>
#include <QComboBox>
#include <QAction>
#include <QHBoxLayout>
#include <QStringList>
#include <QComboBox>
#include <QDebug>
#include <QHBoxLayout>
#include <QStringList>
using namespace Utils;

View File

@@ -24,9 +24,10 @@
****************************************************************************/
#include "vcsbaseplugin.h"
#include "commonvcssettings.h"
#include "vcsbasesubmiteditor.h"
#include "vcsplugin.h"
#include "commonvcssettings.h"
#include <coreplugin/documentmanager.h>
#include <coreplugin/icore.h>
@@ -43,8 +44,8 @@
#include <QDir>
#include <QLoggingCategory>
#include <QMessageBox>
#include <QSharedData>
#include <QScopedPointer>
#include <QSharedData>
#include <QSharedPointer>
#include <QProcessEnvironment>
#include <QTextCodec>

View File

@@ -25,7 +25,15 @@
#include "vcscommand.h"
#include "vcsbaseplugin.h"
#include "vcsoutputwindow.h"
#include "vcsplugin.h"
#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <utils/environment.h>
#include <utils/globalfilechangeblocker.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <utils/runextensions.h>
@@ -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<void> m_watcher;
QFutureInterface<void> m_futureInterface;
QList<Job> 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<void>::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<void> &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<void> 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<void> &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<void> &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<void> &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)
{ }

View File

@@ -36,9 +36,9 @@ QT_BEGIN_NAMESPACE
class QMutex;
class QVariant;
template <typename T>
class QFutureInterface;
template <typename T>
class QFuture;
template <typename T>
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<void> &future);
void runCommandFinished(const Utils::FilePath &workingDirectory);
private:
Utils::FilePath workDirectory(const Utils::FilePath &wd) const;
void run(QFutureInterface<void> &future);
void addTask(const QFuture<void> &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);

View File

@@ -25,16 +25,18 @@
#include "vcsoutputwindow.h"
#include <coreplugin/editormanager/editormanager.h>
#include "vcsoutputformatter.h"
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/outputwindow.h>
#include <utils/fileutils.h>
#include <utils/qtcprocess.h>
#include <texteditor/behaviorsettings.h>
#include <texteditor/fontsettings.h>
#include <texteditor/texteditorsettings.h>
#include <utils/fileutils.h>
#include <utils/qtcprocess.h>
#include <utils/theme/theme.h>
#include <vcsbase/vcsoutputformatter.h>
#include <QAction>
#include <QContextMenuEvent>

View File

@@ -27,7 +27,7 @@
#include "vcsbase_global.h"
#include <coreplugin/ioutputpane.h>
#include <coreplugin/ioutputpane.h>
namespace Utils {
class CommandLine;

View File

@@ -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"