From 5f7e89d914920d3b9fa0798c233af5c96cf7cf28 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 27 Aug 2014 18:55:41 +0200 Subject: Vcs: Some naming re-organization Rename VcsCommand to VcsCommandTag, Command into VcsCommand (Too generic to not mistake for Core::Command IMNSHO), remove the now unneeded namespace qualification when not needed, adjust surrounding code. Change-Id: Iceb18a21e5e6dffa1a622241286f766985bb8d22 Reviewed-by: Christian Stenger --- src/plugins/bazaar/bazaarclient.cpp | 44 +- src/plugins/bazaar/bazaarclient.h | 6 +- src/plugins/bazaar/clonewizard.cpp | 19 +- src/plugins/bazaar/clonewizard.h | 2 +- src/plugins/cvs/checkoutwizard.cpp | 14 +- src/plugins/cvs/checkoutwizard.h | 2 +- src/plugins/cvs/cvsclient.cpp | 33 +- src/plugins/cvs/cvsclient.h | 4 +- src/plugins/git/clonewizard.cpp | 8 +- src/plugins/git/clonewizard.h | 2 +- src/plugins/git/clonewizardpage.cpp | 17 +- src/plugins/git/clonewizardpage.h | 4 +- src/plugins/git/gitclient.cpp | 193 +++--- src/plugins/git/gitclient.h | 8 +- src/plugins/git/gitorious/gitoriousclonewizard.cpp | 2 +- src/plugins/git/gitorious/gitoriousclonewizard.h | 2 +- src/plugins/mercurial/clonewizard.cpp | 16 +- src/plugins/mercurial/clonewizard.h | 2 +- src/plugins/mercurial/mercurialclient.cpp | 67 +-- src/plugins/mercurial/mercurialclient.h | 2 +- src/plugins/mercurial/mercurialplugin.cpp | 23 +- src/plugins/subversion/checkoutwizard.cpp | 21 +- src/plugins/subversion/checkoutwizard.h | 2 +- src/plugins/subversion/subversionclient.cpp | 43 +- src/plugins/subversion/subversionclient.h | 13 +- src/plugins/subversion/subversionplugin.cpp | 8 +- src/plugins/vcsbase/basecheckoutwizard.cpp | 2 +- src/plugins/vcsbase/basecheckoutwizard.h | 4 +- src/plugins/vcsbase/basecheckoutwizardfactory.h | 2 +- src/plugins/vcsbase/checkoutprogresswizardpage.cpp | 4 +- src/plugins/vcsbase/checkoutprogresswizardpage.h | 6 +- src/plugins/vcsbase/command.cpp | 643 -------------------- src/plugins/vcsbase/command.h | 142 ----- src/plugins/vcsbase/vcsbase.pro | 4 +- src/plugins/vcsbase/vcsbase.qbs | 4 +- src/plugins/vcsbase/vcsbaseclient.cpp | 85 ++- src/plugins/vcsbase/vcsbaseclient.h | 25 +- src/plugins/vcsbase/vcsbaseeditor.cpp | 6 +- src/plugins/vcsbase/vcsbaseeditor.h | 4 +- src/plugins/vcsbase/vcsbaseplugin.cpp | 6 +- src/plugins/vcsbase/vcscommand.cpp | 644 +++++++++++++++++++++ src/plugins/vcsbase/vcscommand.h | 142 +++++ 42 files changed, 1149 insertions(+), 1131 deletions(-) delete mode 100644 src/plugins/vcsbase/command.cpp delete mode 100644 src/plugins/vcsbase/command.h create mode 100644 src/plugins/vcsbase/vcscommand.cpp create mode 100644 src/plugins/vcsbase/vcscommand.h diff --git a/src/plugins/bazaar/bazaarclient.cpp b/src/plugins/bazaar/bazaarclient.cpp index 0004b37006..6a9ff8e956 100644 --- a/src/plugins/bazaar/bazaarclient.cpp +++ b/src/plugins/bazaar/bazaarclient.cpp @@ -39,35 +39,35 @@ #include #include +using namespace Utils; using namespace VcsBase; namespace Bazaar { namespace Internal { -class BazaarDiffExitCodeInterpreter : public Utils::ExitCodeInterpreter +class BazaarDiffExitCodeInterpreter : public ExitCodeInterpreter { Q_OBJECT public: - BazaarDiffExitCodeInterpreter(QObject *parent) : Utils::ExitCodeInterpreter(parent) {} - Utils::SynchronousProcessResponse::Result interpretExitCode(int code) const; - + BazaarDiffExitCodeInterpreter(QObject *parent) : ExitCodeInterpreter(parent) {} + SynchronousProcessResponse::Result interpretExitCode(int code) const; }; -Utils::SynchronousProcessResponse::Result BazaarDiffExitCodeInterpreter::interpretExitCode(int code) const +SynchronousProcessResponse::Result BazaarDiffExitCodeInterpreter::interpretExitCode(int code) const { if (code < 0 || code > 2) - return Utils::SynchronousProcessResponse::FinishedError; - return Utils::SynchronousProcessResponse::Finished; + return SynchronousProcessResponse::FinishedError; + return SynchronousProcessResponse::Finished; } BazaarClient::BazaarClient(BazaarSettings *settings) : - VcsBase::VcsBaseClient(settings) + VcsBaseClient(settings) { } BazaarSettings *BazaarClient::settings() const { - return dynamic_cast(VcsBase::VcsBaseClient::settings()); + return dynamic_cast(VcsBaseClient::settings()); } bool BazaarClient::synchronousSetUserId() @@ -143,10 +143,10 @@ QString BazaarClient::findTopLevelForFile(const QFileInfo &file) const const QString repositoryCheckFile = QLatin1String(Constants::BAZAARREPO) + QLatin1String("/branch-format"); return file.isDir() ? - VcsBase::VcsBasePlugin::findRepositoryForDirectory(file.absoluteFilePath(), - repositoryCheckFile) : - VcsBase::VcsBasePlugin::findRepositoryForDirectory(file.absolutePath(), - repositoryCheckFile); + VcsBasePlugin::findRepositoryForDirectory(file.absoluteFilePath(), + repositoryCheckFile) : + VcsBasePlugin::findRepositoryForDirectory(file.absolutePath(), + repositoryCheckFile); } bool BazaarClient::managesFile(const QString &workingDirectory, const QString &fileName) const @@ -166,7 +166,7 @@ void BazaarClient::view(const QString &source, const QString &id, const QStringL VcsBaseClient::view(source, id, args); } -Core::Id BazaarClient::vcsEditorKind(VcsCommand cmd) const +Core::Id BazaarClient::vcsEditorKind(VcsCommandTag cmd) const { switch (cmd) { case AnnotateCommand: @@ -180,7 +180,7 @@ Core::Id BazaarClient::vcsEditorKind(VcsCommand cmd) const } } -QString BazaarClient::vcsCommandString(VcsCommand cmd) const +QString BazaarClient::vcsCommandString(VcsCommandTag cmd) const { switch (cmd) { case CloneCommand: @@ -190,7 +190,7 @@ QString BazaarClient::vcsCommandString(VcsCommand cmd) const } } -Utils::ExitCodeInterpreter *BazaarClient::exitCodeInterpreter(VcsCommand cmd, QObject *parent) const +ExitCodeInterpreter *BazaarClient::exitCodeInterpreter(VcsCommandTag cmd, QObject *parent) const { switch (cmd) { case DiffCommand: @@ -269,13 +269,13 @@ struct BazaarCommandParameters }; // Parameter widget controlling whitespace diff mode, associated with a parameter -class BazaarDiffParameterWidget : public VcsBase::VcsBaseEditorParameterWidget +class BazaarDiffParameterWidget : public VcsBaseEditorParameterWidget { Q_OBJECT public: BazaarDiffParameterWidget(BazaarClient *client, const BazaarCommandParameters &p, QWidget *parent = 0) : - VcsBase::VcsBaseEditorParameterWidget(parent), m_client(client), m_params(p) + VcsBaseEditorParameterWidget(parent), m_client(client), m_params(p) { mapSetting(addToggleButton(QLatin1String("-w"), tr("Ignore Whitespace")), client->settings()->boolPointer(BazaarSettings::diffIgnoreWhiteSpaceKey)); @@ -306,20 +306,20 @@ private: const BazaarCommandParameters m_params; }; -VcsBase::VcsBaseEditorParameterWidget *BazaarClient::createDiffEditor( +VcsBaseEditorParameterWidget *BazaarClient::createDiffEditor( const QString &workingDir, const QStringList &files, const QStringList &extraOptions) { const BazaarCommandParameters parameters(workingDir, files, extraOptions); return new BazaarDiffParameterWidget(this, parameters); } -class BazaarLogParameterWidget : public VcsBase::VcsBaseEditorParameterWidget +class BazaarLogParameterWidget : public VcsBaseEditorParameterWidget { Q_OBJECT public: BazaarLogParameterWidget(BazaarClient *client, const BazaarCommandParameters &p, QWidget *parent = 0) : - VcsBase::VcsBaseEditorParameterWidget(parent), m_client(client), m_params(p) + VcsBaseEditorParameterWidget(parent), m_client(client), m_params(p) { BazaarSettings *settings = m_client->settings(); mapSetting(addToggleButton(QLatin1String("--verbose"), tr("Verbose"), @@ -351,7 +351,7 @@ private: const BazaarCommandParameters m_params; }; -VcsBase::VcsBaseEditorParameterWidget *BazaarClient::createLogEditor( +VcsBaseEditorParameterWidget *BazaarClient::createLogEditor( const QString &workingDir, const QStringList &files, const QStringList &extraOptions) { const BazaarCommandParameters parameters(workingDir, files, extraOptions); diff --git a/src/plugins/bazaar/bazaarclient.h b/src/plugins/bazaar/bazaarclient.h index 8896d933fa..1239d72740 100644 --- a/src/plugins/bazaar/bazaarclient.h +++ b/src/plugins/bazaar/bazaarclient.h @@ -63,9 +63,9 @@ public: bool managesFile(const QString &workingDirectory, const QString &fileName) const; protected: - Core::Id vcsEditorKind(VcsCommand cmd) const; - QString vcsCommandString(VcsCommand cmd) const; - Utils::ExitCodeInterpreter *exitCodeInterpreter(VcsCommand cmd, QObject *parent) const; + Core::Id vcsEditorKind(VcsCommandTag cmd) const; + QString vcsCommandString(VcsCommandTag cmd) const; + Utils::ExitCodeInterpreter *exitCodeInterpreter(VcsCommandTag cmd, QObject *parent) const; QStringList revisionSpec(const QString &revision) const; VcsBase::VcsBaseEditorParameterWidget *createDiffEditor(const QString &workingDir, const QStringList &files, diff --git a/src/plugins/bazaar/clonewizard.cpp b/src/plugins/bazaar/clonewizard.cpp index c41cc177b9..ab5a3ab2c9 100644 --- a/src/plugins/bazaar/clonewizard.cpp +++ b/src/plugins/bazaar/clonewizard.cpp @@ -35,34 +35,36 @@ #include "bazaarsettings.h" #include -#include +#include #include #include #include -using namespace Bazaar::Internal; +using namespace VcsBase; +namespace Bazaar { +namespace Internal { // -------------------------------------------------------------------- // CloneWizard: // -------------------------------------------------------------------- CloneWizard::CloneWizard(const Utils::FileName &path, QWidget *parent) : - VcsBase::BaseCheckoutWizard(path, parent) + BaseCheckoutWizard(path, parent) { setTitle(tr("Cloning")); setStartedStatus(tr("Cloning started...")); const Core::IVersionControl *vc = BazaarPlugin::instance()->versionControl(); if (!vc->isConfigured()) - addPage(new VcsBase::VcsConfigurationPage(vc)); + addPage(new VcsConfigurationPage(vc)); CloneWizardPage *page = new CloneWizardPage; page->setPath(path.toString()); addPage(page); } -VcsBase::Command *CloneWizard::createCommand(Utils::FileName *checkoutDir) +VcsCommand *CloneWizard::createCommand(Utils::FileName *checkoutDir) { const CloneWizardPage *cwp = 0; foreach (int pageId, pageIds()) { @@ -99,8 +101,11 @@ VcsBase::Command *CloneWizard::createCommand(Utils::FileName *checkoutDir) args << client->vcsCommandString(BazaarClient::CloneCommand) << extraOptions << cwp->repository() << cwp->directory(); - VcsBase::Command *command = new VcsBase::Command(settings.binaryPath(), cwp->path(), - client->processEnvironment()); + VcsCommand *command = new VcsCommand(settings.binaryPath(), cwp->path(), + client->processEnvironment()); command->addJob(args, -1); return command; } + +} // namespace Internal +} // namespace Bazaar diff --git a/src/plugins/bazaar/clonewizard.h b/src/plugins/bazaar/clonewizard.h index 20a273acd4..7aeafcf0fb 100644 --- a/src/plugins/bazaar/clonewizard.h +++ b/src/plugins/bazaar/clonewizard.h @@ -44,7 +44,7 @@ public: CloneWizard(const Utils::FileName &path, QWidget *parent = 0); protected: - VcsBase::Command *createCommand(Utils::FileName *checkoutDir); + VcsBase::VcsCommand *createCommand(Utils::FileName *checkoutDir); }; } // namespace Internal diff --git a/src/plugins/cvs/checkoutwizard.cpp b/src/plugins/cvs/checkoutwizard.cpp index 9cca9a7139..1a8fb59168 100644 --- a/src/plugins/cvs/checkoutwizard.cpp +++ b/src/plugins/cvs/checkoutwizard.cpp @@ -32,11 +32,13 @@ #include "cvsplugin.h" #include -#include +#include #include #include #include +using namespace VcsBase; + namespace Cvs { namespace Internal { @@ -45,17 +47,17 @@ namespace Internal { // -------------------------------------------------------------------- CheckoutWizard::CheckoutWizard(const Utils::FileName &path, QWidget *parent) : - VcsBase::BaseCheckoutWizard(path, parent) + BaseCheckoutWizard(path, parent) { const Core::IVersionControl *vc = CvsPlugin::instance()->versionControl(); if (!vc->isConfigured()) - addPage(new VcsBase::VcsConfigurationPage(vc)); + addPage(new VcsConfigurationPage(vc)); CheckoutWizardPage *cwp = new CheckoutWizardPage; cwp->setPath(path.toString()); addPage(cwp); } -VcsBase::Command *CheckoutWizard::createCommand(Utils::FileName *checkoutDir) +VcsCommand *CheckoutWizard::createCommand(Utils::FileName *checkoutDir) { // Collect parameters for the checkout command. // CVS does not allow for checking out into a different directory. @@ -75,8 +77,8 @@ VcsBase::Command *CheckoutWizard::createCommand(Utils::FileName *checkoutDir) const QString workingDirectory = cwp->path(); *checkoutDir = Utils::FileName::fromString(workingDirectory + QLatin1Char('/') + repository); - VcsBase::Command *command = new VcsBase::Command(binary, workingDirectory, - QProcessEnvironment::systemEnvironment()); + VcsCommand *command = new VcsCommand(binary, workingDirectory, + QProcessEnvironment::systemEnvironment()); command->addJob(settings.addOptions(args), -1); return command; } diff --git a/src/plugins/cvs/checkoutwizard.h b/src/plugins/cvs/checkoutwizard.h index fb88cadf1f..a1754d954a 100644 --- a/src/plugins/cvs/checkoutwizard.h +++ b/src/plugins/cvs/checkoutwizard.h @@ -44,7 +44,7 @@ public: CheckoutWizard(const Utils::FileName &path, QWidget *parent = 0); protected: - VcsBase::Command *createCommand(Utils::FileName *checkoutDir); + VcsBase::VcsCommand *createCommand(Utils::FileName *checkoutDir); }; } // namespace Internal diff --git a/src/plugins/cvs/cvsclient.cpp b/src/plugins/cvs/cvsclient.cpp index 1a7f0603d0..067b3f6bfc 100644 --- a/src/plugins/cvs/cvsclient.cpp +++ b/src/plugins/cvs/cvsclient.cpp @@ -42,23 +42,26 @@ #include #include +using namespace Utils; +using namespace VcsBase; + namespace Cvs { namespace Internal { -class CvsDiffExitCodeInterpreter : public Utils::ExitCodeInterpreter +class CvsDiffExitCodeInterpreter : public ExitCodeInterpreter { Q_OBJECT public: - CvsDiffExitCodeInterpreter(QObject *parent) : Utils::ExitCodeInterpreter(parent) {} - Utils::SynchronousProcessResponse::Result interpretExitCode(int code) const; + CvsDiffExitCodeInterpreter(QObject *parent) : ExitCodeInterpreter(parent) {} + SynchronousProcessResponse::Result interpretExitCode(int code) const; }; -Utils::SynchronousProcessResponse::Result CvsDiffExitCodeInterpreter::interpretExitCode(int code) const +SynchronousProcessResponse::Result CvsDiffExitCodeInterpreter::interpretExitCode(int code) const { if (code < 0 || code > 2) - return Utils::SynchronousProcessResponse::FinishedError; - return Utils::SynchronousProcessResponse::Finished; + return SynchronousProcessResponse::FinishedError; + return SynchronousProcessResponse::Finished; } // Collect all parameters required for a diff to be able to associate them @@ -71,7 +74,7 @@ struct CvsDiffParameters }; // Parameter widget controlling whitespace diff mode, associated with a parameter -class CvsDiffParameterWidget : public VcsBase::VcsBaseEditorParameterWidget +class CvsDiffParameterWidget : public VcsBaseEditorParameterWidget { Q_OBJECT public: @@ -90,7 +93,7 @@ private: CvsDiffParameterWidget::CvsDiffParameterWidget(CvsClient *client, const CvsDiffParameters &p, QWidget *parent) - : VcsBase::VcsBaseEditorParameterWidget(parent), m_client(client), m_params(p) + : VcsBaseEditorParameterWidget(parent), m_client(client), m_params(p) { mapSetting(addToggleButton(QLatin1String("-w"), tr("Ignore Whitespace")), client->settings()->boolPointer(CvsSettings::diffIgnoreWhiteSpaceKey)); @@ -112,16 +115,16 @@ void CvsDiffParameterWidget::executeCommand() } CvsClient::CvsClient(CvsSettings *settings) : - VcsBase::VcsBaseClient(settings) + VcsBaseClient(settings) { } CvsSettings *CvsClient::settings() const { - return dynamic_cast(VcsBase::VcsBaseClient::settings()); + return dynamic_cast(VcsBaseClient::settings()); } -Core::Id CvsClient::vcsEditorKind(VcsCommand cmd) const +Core::Id CvsClient::vcsEditorKind(VcsCommandTag cmd) const { switch (cmd) { case DiffCommand: @@ -131,7 +134,7 @@ Core::Id CvsClient::vcsEditorKind(VcsCommand cmd) const } } -Utils::ExitCodeInterpreter *CvsClient::exitCodeInterpreter(VcsCommand cmd, QObject *parent) const +ExitCodeInterpreter *CvsClient::exitCodeInterpreter(VcsCommandTag cmd, QObject *parent) const { switch (cmd) { case DiffCommand: @@ -159,13 +162,13 @@ QStringList CvsClient::revisionSpec(const QString &revision) const return QStringList(); } -VcsBase::VcsBaseClient::StatusItem CvsClient::parseStatusLine(const QString &line) const +VcsBaseClient::StatusItem CvsClient::parseStatusLine(const QString &line) const { Q_UNUSED(line) - return VcsBase::VcsBaseClient::StatusItem(); + return VcsBaseClient::StatusItem(); } -VcsBase::VcsBaseEditorParameterWidget *CvsClient::createDiffEditor( +VcsBaseEditorParameterWidget *CvsClient::createDiffEditor( const QString &workingDir, const QStringList &files, const QStringList &extraOptions) { Q_UNUSED(extraOptions) diff --git a/src/plugins/cvs/cvsclient.h b/src/plugins/cvs/cvsclient.h index 3f3c1ab84a..3c8e834ab1 100644 --- a/src/plugins/cvs/cvsclient.h +++ b/src/plugins/cvs/cvsclient.h @@ -54,8 +54,8 @@ public: protected: - Utils::ExitCodeInterpreter *exitCodeInterpreter(VcsCommand cmd, QObject *parent) const; - Core::Id vcsEditorKind(VcsCommand cmd) const; + Utils::ExitCodeInterpreter *exitCodeInterpreter(VcsCommandTag cmd, QObject *parent) const; + Core::Id vcsEditorKind(VcsCommandTag cmd) const; VcsBase::VcsBaseEditorParameterWidget *createDiffEditor(const QString &workingDir, const QStringList &files, const QStringList &extraOptions); diff --git a/src/plugins/git/clonewizard.cpp b/src/plugins/git/clonewizard.cpp index 3a09dcd5f1..b13bebdf40 100644 --- a/src/plugins/git/clonewizard.cpp +++ b/src/plugins/git/clonewizard.cpp @@ -37,6 +37,8 @@ #include #include +using namespace VcsBase; + namespace Git { namespace Internal { @@ -45,20 +47,20 @@ namespace Internal { // -------------------------------------------------------------------- CloneWizard::CloneWizard(const Utils::FileName &path, QWidget *parent) : - VcsBase::BaseCheckoutWizard(path, parent) + BaseCheckoutWizard(path, parent) { setTitle(tr("Cloning")); setStartedStatus(tr("Cloning started...")); const Internal::GitVersionControl *vc = Internal::GitPlugin::instance()->gitVersionControl(); if (!vc->isConfigured()) - addPage(new VcsBase::VcsConfigurationPage(vc)); + addPage(new VcsConfigurationPage(vc)); CloneWizardPage *cwp = new CloneWizardPage; cwp->setPath(path.toString()); addPage(cwp); } -VcsBase::Command *CloneWizard::createCommand(Utils::FileName *checkoutDir) +VcsCommand *CloneWizard::createCommand(Utils::FileName *checkoutDir) { // Collect parameters for the clone command. const CloneWizardPage *cwp = 0; diff --git a/src/plugins/git/clonewizard.h b/src/plugins/git/clonewizard.h index b86f331dfa..cffab524c0 100644 --- a/src/plugins/git/clonewizard.h +++ b/src/plugins/git/clonewizard.h @@ -44,7 +44,7 @@ public: CloneWizard(const Utils::FileName &path, QWidget *parent = 0); protected: - VcsBase::Command *createCommand(Utils::FileName *checkoutDir); + VcsBase::VcsCommand *createCommand(Utils::FileName *checkoutDir); }; } // namespace Internal diff --git a/src/plugins/git/clonewizardpage.cpp b/src/plugins/git/clonewizardpage.cpp index 0187e5cfe7..b00db9eba2 100644 --- a/src/plugins/git/clonewizardpage.cpp +++ b/src/plugins/git/clonewizardpage.cpp @@ -31,13 +31,16 @@ #include "gitplugin.h" #include "gitclient.h" -#include +#include #include +using namespace VcsBase; + namespace Git { -struct CloneWizardPagePrivate { +struct CloneWizardPagePrivate +{ CloneWizardPagePrivate(); bool urlIsLocal(const QString &url); @@ -64,7 +67,7 @@ bool CloneWizardPagePrivate::urlIsLocal(const QString &url) } CloneWizardPage::CloneWizardPage(QWidget *parent) : - VcsBase::BaseCheckoutWizardPage(parent), + BaseCheckoutWizardPage(parent), d(new CloneWizardPagePrivate) { setTitle(tr("Location")); @@ -104,7 +107,7 @@ QString CloneWizardPage::directoryFromRepository(const QString &urlIn) const return url; } -VcsBase::Command *CloneWizardPage::createCheckoutJob(Utils::FileName *checkoutPath) const +VcsCommand *CloneWizardPage::createCheckoutJob(Utils::FileName *checkoutPath) const { const Internal::GitClient *client = Internal::GitPlugin::instance()->gitClient(); const QString workingDirectory = path(); @@ -119,9 +122,9 @@ VcsBase::Command *CloneWizardPage::createCheckoutJob(Utils::FileName *checkoutPa if (d->recursiveCheckBox->isChecked()) args << QLatin1String("--recursive"); args << QLatin1String("--progress") << repository() << checkoutDir; - VcsBase::Command *command = new VcsBase::Command(client->gitExecutable(), workingDirectory, - client->processEnvironment()); - command->addFlags(VcsBase::VcsBasePlugin::MergeOutputChannels); + VcsCommand *command = new VcsCommand(client->gitExecutable(), workingDirectory, + client->processEnvironment()); + command->addFlags(VcsBasePlugin::MergeOutputChannels); command->addJob(args, -1); return command; } diff --git a/src/plugins/git/clonewizardpage.h b/src/plugins/git/clonewizardpage.h index a89f2871b8..da748973dc 100644 --- a/src/plugins/git/clonewizardpage.h +++ b/src/plugins/git/clonewizardpage.h @@ -34,7 +34,7 @@ #include -namespace VcsBase { class Command; } +namespace VcsBase { class VcsCommand; } namespace Git { @@ -48,7 +48,7 @@ public: explicit CloneWizardPage(QWidget *parent = 0); ~CloneWizardPage(); - VcsBase::Command *createCheckoutJob(Utils::FileName *checkoutPath) const; + VcsBase::VcsCommand *createCheckoutJob(Utils::FileName *checkoutPath) const; protected: QString directoryFromRepository(const QString &r) const; diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 7911bcc895..ac896f72a6 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -53,7 +53,7 @@ #include #include #include -#include +#include #include #include #include @@ -87,19 +87,18 @@ static const char noColorOption[] = "--no-color"; static const char decorateOption[] = "--decorate"; using namespace Core; +using namespace Utils; using namespace VcsBase; namespace Git { namespace Internal { // Suppress git diff warnings about "LF will be replaced by CRLF..." on Windows. -static inline unsigned diffExecutionFlags() +static unsigned diffExecutionFlags() { - return Utils::HostOsInfo::isWindowsHost() ? unsigned(VcsBase::VcsBasePlugin::SuppressStdErrInLogWindow) : 0u; + return HostOsInfo::isWindowsHost() ? unsigned(VcsBasePlugin::SuppressStdErrInLogWindow) : 0u; } -using VcsBase::VcsBasePlugin; - class GitDiffHandler : public QObject { Q_OBJECT @@ -134,13 +133,13 @@ private: void postCollectTextualDiffOutputUsingShowCommand(const QStringList &arguments); void postCollectTextualDiffOutput(const QString &gitCommand, const QList &argumentsList); - void addJob(VcsBase::Command *command, + void addJob(VcsCommand *command, const QString &gitCommand, const QStringList &arguments); QStringList addHeadWhenCommandInProgress() const; int timeout() const; QProcessEnvironment processEnvironment() const; - Utils::FileName gitPath() const; + FileName gitPath() const; QPointer m_controller; const QString m_workingDirectory; @@ -220,9 +219,7 @@ void GitDiffHandler::postCollectShowDescription(const QString &id) m_controller->requestSaveState(); m_controller->clear(m_waitMessage); - VcsBase::Command *command = new VcsBase::Command(gitPath(), - m_workingDirectory, - processEnvironment()); + VcsCommand *command = new VcsCommand(gitPath(), m_workingDirectory, processEnvironment()); command->setCodec(m_gitClient->encoding(m_workingDirectory, "i18n.commitEncoding")); connect(command, SIGNAL(output(QString)), @@ -256,7 +253,7 @@ void GitDiffHandler::slotShowDescriptionReceived(const QString &description) description)); } -void GitDiffHandler::addJob(VcsBase::Command *command, +void GitDiffHandler::addJob(VcsCommand *command, const QString &gitCommand, const QStringList &arguments) { @@ -308,9 +305,7 @@ void GitDiffHandler::postCollectTextualDiffOutput(const QString &gitCommand, con m_controller->requestSaveState(); m_controller->clear(m_waitMessage); - VcsBase::Command *command = new VcsBase::Command(gitPath(), - m_workingDirectory, - processEnvironment()); + VcsCommand *command = new VcsCommand(gitPath(), m_workingDirectory, processEnvironment()); command->setCodec(EditorManager::defaultTextCodec()); connect(command, SIGNAL(output(QString)), this, SLOT(slotTextualDiffOutputReceived(QString))); @@ -348,7 +343,7 @@ QProcessEnvironment GitDiffHandler::processEnvironment() const return m_gitClient->processEnvironment(); } -Utils::FileName GitDiffHandler::gitPath() const +FileName GitDiffHandler::gitPath() const { return m_gitClient->gitExecutable(); } @@ -446,7 +441,7 @@ void GitDiffEditorReloader::reload() /////////////////////////////// -class BaseGitDiffArgumentsWidget : public VcsBase::VcsBaseEditorParameterWidget +class BaseGitDiffArgumentsWidget : public VcsBaseEditorParameterWidget { Q_OBJECT @@ -481,7 +476,7 @@ protected: QToolButton *m_ignoreWSButton; }; -class GitBlameArgumentsWidget : public VcsBase::VcsBaseEditorParameterWidget +class GitBlameArgumentsWidget : public VcsBaseEditorParameterWidget { Q_OBJECT @@ -506,7 +501,7 @@ public: setBaseArguments(args); } - void setEditor(VcsBase::VcsBaseEditorWidget *editor) + void setEditor(VcsBaseEditorWidget *editor) { QTC_ASSERT(editor, return); m_editor = editor; @@ -514,12 +509,12 @@ public: void executeCommand() { - int line = VcsBase::VcsBaseEditor::lineNumberOfCurrentEditor(); + int line = VcsBaseEditor::lineNumberOfCurrentEditor(); m_client->blame(m_workingDirectory, baseArguments(), m_fileName, m_revision, line); } private: - VcsBase::VcsBaseEditorWidget *m_editor; + VcsBaseEditorWidget *m_editor; GitClient *m_client; QString m_workingDirectory; QString m_revision; @@ -579,7 +574,7 @@ class ConflictHandler : public QObject { Q_OBJECT public: - ConflictHandler(VcsBase::Command *parentCommand, + ConflictHandler(VcsCommand *parentCommand, const QString &workingDirectory, const QString &command = QString()) : QObject(parentCommand), @@ -634,10 +629,10 @@ private: QStringList m_files; }; -class ProgressParser : public VcsBase::ProgressParser +class GitProgressParser : public ProgressParser { public: - ProgressParser() : + GitProgressParser() : m_progressExp(QLatin1String("\\((\\d+)/(\\d+)\\)")) // e.g. Rebasing (7/42) { } @@ -666,7 +661,7 @@ IEditor *locateEditor(const char *property, const QString &entry) // Return converted command output, remove '\r' read on Windows static inline QString commandOutputFromLocal8Bit(const QByteArray &a) { - return Utils::SynchronousProcess::normalizeNewlines(QString::fromLocal8Bit(a)); + return SynchronousProcess::normalizeNewlines(QString::fromLocal8Bit(a)); } // Return converted command output split into lines @@ -796,10 +791,10 @@ bool GitClient::managesFile(const QString &workingDirectory, const QString &file VcsBasePlugin::SuppressCommandLogging); } -VcsBase::VcsBaseEditorWidget *GitClient::findExistingVCSEditor(const char *registerDynamicProperty, - const QString &dynamicPropertyValue) const +VcsBaseEditorWidget *GitClient::findExistingVCSEditor(const char *registerDynamicProperty, + const QString &dynamicPropertyValue) const { - VcsBase::VcsBaseEditorWidget *rc = 0; + VcsBaseEditorWidget *rc = 0; IEditor *outputEditor = locateEditor(registerDynamicProperty, dynamicPropertyValue); if (!outputEditor) return 0; @@ -937,16 +932,16 @@ void GitClient::stage(const QString &patch, bool revert) * (using the file's codec). Makes use of a dynamic property to find an * existing instance and to reuse it (in case, say, 'git diff foo' is * already open). */ -VcsBase::VcsBaseEditorWidget *GitClient::createVcsEditor( +VcsBaseEditorWidget *GitClient::createVcsEditor( Id id, QString title, const QString &source, // Source file or directory CodecType codecType, const char *registerDynamicProperty, // Dynamic property and value to identify that editor const QString &dynamicPropertyValue, - VcsBase::VcsBaseEditorParameterWidget *configWidget) const + VcsBaseEditorParameterWidget *configWidget) const { - VcsBase::VcsBaseEditorWidget *rc = 0; + VcsBaseEditorWidget *rc = 0; QTC_CHECK(!findExistingVCSEditor(registerDynamicProperty, dynamicPropertyValue)); // Create new, set wait message, set up with source and codec @@ -1024,8 +1019,7 @@ void GitClient::diff(const QString &workingDirectory, void GitClient::diff(const QString &workingDirectory, const QString &fileName) const { const QString title = tr("Git Diff \"%1\"").arg(fileName); - const QString sourceFile = VcsBase::VcsBaseEditor::getSource( - workingDirectory, fileName); + const QString sourceFile = VcsBaseEditor::getSource(workingDirectory, fileName); const QString documentId = QLatin1String("File:") + sourceFile; DiffEditor::DiffEditorDocument *diffEditorDocument = DiffEditor::DiffEditorManager::find(documentId); @@ -1083,7 +1077,7 @@ void GitClient::status(const QString &workingDirectory) QStringList statusArgs = statusArguments(); statusArgs << QLatin1String("-u"); VcsOutputWindow::setRepository(workingDirectory); - VcsBase::Command *command = executeGit(workingDirectory, statusArgs, 0, true); + VcsCommand *command = executeGit(workingDirectory, statusArgs, 0, true); connect(command, SIGNAL(finished(bool,int,QVariant)), VcsOutputWindow::instance(), SLOT(clearRepository()), Qt::QueuedConnection); } @@ -1095,7 +1089,7 @@ void GitClient::log(const QString &workingDirectory, const QString &fileName, const QString title = tr("Git Log \"%1\"").arg(msgArg); const Id editorId = Git::Constants::GIT_LOG_EDITOR_ID; const QString sourceFile = VcsBaseEditor::getSource(workingDirectory, fileName); - VcsBase::VcsBaseEditorWidget *editor = findExistingVCSEditor("logFileName", sourceFile); + VcsBaseEditorWidget *editor = findExistingVCSEditor("logFileName", sourceFile); if (!editor) editor = createVcsEditor(editorId, title, sourceFile, CodecLogOutput, "logFileName", sourceFile, new GitLogArgumentsWidget(this, workingDirectory, @@ -1129,7 +1123,7 @@ void GitClient::reflog(const QString &workingDirectory) { const QString title = tr("Git Reflog \"%1\"").arg(workingDirectory); const Id editorId = Git::Constants::GIT_LOG_EDITOR_ID; - VcsBase::VcsBaseEditorWidget *editor = findExistingVCSEditor("reflogRepository", workingDirectory); + VcsBaseEditorWidget *editor = findExistingVCSEditor("reflogRepository", workingDirectory); if (!editor) { editor = createVcsEditor(editorId, title, workingDirectory, CodecLogOutput, "reflogRepository", workingDirectory, 0); @@ -1220,7 +1214,7 @@ void GitClient::slotBlameRevisionRequested(const QString &workingDirectory, cons QTextCodec *GitClient::getSourceCodec(const QString &file) const { - return QFileInfo(file).isFile() ? VcsBase::VcsBaseEditor::getCodec(file) + return QFileInfo(file).isFile() ? VcsBaseEditor::getCodec(file) : encoding(file, "gui.encoding"); } @@ -1231,11 +1225,11 @@ void GitClient::blame(const QString &workingDirectory, int lineNumber) { const Id editorId = Git::Constants::GIT_BLAME_EDITOR_ID; - const QString id = VcsBase::VcsBaseEditor::getTitleId(workingDirectory, QStringList(fileName), revision); + const QString id = VcsBaseEditor::getTitleId(workingDirectory, QStringList(fileName), revision); const QString title = tr("Git Blame \"%1\"").arg(id); - const QString sourceFile = VcsBase::VcsBaseEditor::getSource(workingDirectory, fileName); + const QString sourceFile = VcsBaseEditor::getSource(workingDirectory, fileName); - VcsBase::VcsBaseEditorWidget *editor = findExistingVCSEditor("blameFileName", id); + VcsBaseEditorWidget *editor = findExistingVCSEditor("blameFileName", id); if (!editor) { GitBlameArgumentsWidget *argWidget = new GitBlameArgumentsWidget(this, workingDirectory, args, @@ -1793,8 +1787,7 @@ void GitClient::branchesForCommit(const QString &revision) DiffEditor::DiffEditorController *controller = qobject_cast(sender()); QString workingDirectory = controller->workingDirectory(); - VcsBase::Command *command = new VcsBase::Command(gitExecutable(), workingDirectory, - processEnvironment()); + VcsCommand *command = new VcsCommand(gitExecutable(), workingDirectory, processEnvironment()); command->setCodec(getSourceCodec(currentDocumentPath())); connect(command, SIGNAL(output(QString)), controller, @@ -1991,7 +1984,7 @@ bool GitClient::synchronousForEachRefCmd(const QString &workingDirectory, QStrin QByteArray errorText; const bool rc = fullySynchronousGit(workingDirectory, args, &outputText, &errorText, VcsBasePlugin::SuppressCommandLogging); - *output = Utils::SynchronousProcess::normalizeNewlines(QString::fromUtf8(outputText)); + *output = SynchronousProcess::normalizeNewlines(QString::fromUtf8(outputText)); if (!rc) msgCannotRun(args, workingDirectory, errorText, errorMessage); @@ -2191,12 +2184,12 @@ bool GitClient::synchronousApplyPatch(const QString &workingDirectory, } // Factory function to create an asynchronous command -VcsBase::Command *GitClient::createCommand(const QString &workingDirectory, - VcsBase::VcsBaseEditorWidget* editor, - bool useOutputToWindow, - int editorLineNumber) +VcsCommand *GitClient::createCommand(const QString &workingDirectory, + VcsBaseEditorWidget* editor, + bool useOutputToWindow, + int editorLineNumber) { - VcsBase::Command *command = new VcsBase::Command(gitExecutable(), workingDirectory, processEnvironment()); + VcsCommand *command = new VcsCommand(gitExecutable(), workingDirectory, processEnvironment()); command->setCodec(getSourceCodec(currentDocumentPath())); command->setCookie(QVariant(editorLineNumber)); if (editor) { @@ -2217,17 +2210,17 @@ VcsBase::Command *GitClient::createCommand(const QString &workingDirectory, } // Execute a single command -VcsBase::Command *GitClient::executeGit(const QString &workingDirectory, - const QStringList &arguments, - VcsBase::VcsBaseEditorWidget* editor, - bool useOutputToWindow, - unsigned additionalFlags, - int editorLineNumber) +VcsCommand *GitClient::executeGit(const QString &workingDirectory, + const QStringList &arguments, + VcsBaseEditorWidget* editor, + bool useOutputToWindow, + unsigned additionalFlags, + int editorLineNumber) { VcsOutputWindow::appendCommand(workingDirectory, - Utils::FileName::fromUserInput(settings()->stringValue(GitSettings::binaryPathKey)), - arguments); - VcsBase::Command *command = createCommand(workingDirectory, editor, useOutputToWindow, editorLineNumber); + FileName::fromUserInput(settings()->stringValue(GitSettings::binaryPathKey)), + arguments); + VcsCommand *command = createCommand(workingDirectory, editor, useOutputToWindow, editorLineNumber); command->addJob(arguments, settings()->intValue(GitSettings::timeoutKey)); command->addFlags(additionalFlags); command->execute(); @@ -2239,11 +2232,11 @@ QProcessEnvironment GitClient::processEnvironment() const QProcessEnvironment environment = QProcessEnvironment::systemEnvironment(); QString gitPath = settings()->stringValue(GitSettings::pathKey); if (!gitPath.isEmpty()) { - gitPath += Utils::HostOsInfo::pathListSeparator(); + gitPath += HostOsInfo::pathListSeparator(); gitPath += environment.value(QLatin1String("PATH")); environment.insert(QLatin1String("PATH"), gitPath); } - if (Utils::HostOsInfo::isWindowsHost() + if (HostOsInfo::isWindowsHost() && settings()->boolValue(GitSettings::winSetHomeEnvironmentKey)) { environment.insert(QLatin1String("HOME"), QDir::toNativeSeparators(QDir::homePath())); } @@ -2289,10 +2282,10 @@ bool GitClient::isValidRevision(const QString &revision) const // Synchronous git execution using Utils::SynchronousProcess, with // log windows updating. -Utils::SynchronousProcessResponse GitClient::synchronousGit(const QString &workingDirectory, - const QStringList &gitArguments, - unsigned flags, - QTextCodec *outputCodec) const +SynchronousProcessResponse GitClient::synchronousGit(const QString &workingDirectory, + const QStringList &gitArguments, + unsigned flags, + QTextCodec *outputCodec) const { return VcsBasePlugin::runVcs(workingDirectory, gitExecutable(), gitArguments, settings()->intValue(GitSettings::timeoutKey) * 1000, @@ -2305,7 +2298,7 @@ bool GitClient::fullySynchronousGit(const QString &workingDirectory, QByteArray* errorText, unsigned flags) const { - VcsBase::Command command(gitExecutable(), workingDirectory, processEnvironment()); + VcsCommand command(gitExecutable(), workingDirectory, processEnvironment()); command.addFlags(flags); return command.runFullySynchronous(gitArguments, settings()->intValue(GitSettings::timeoutKey) * 1000, @@ -2360,8 +2353,8 @@ void GitClient::updateSubmodulesIfNeeded(const QString &workingDirectory, bool p QStringList arguments; arguments << QLatin1String("submodule") << QLatin1String("update"); - VcsBase::Command *cmd = executeGit(workingDirectory, arguments, 0, true, - VcsBasePlugin::ExpectRepoChanges); + VcsCommand *cmd = executeGit(workingDirectory, arguments, 0, true, + VcsBasePlugin::ExpectRepoChanges); connect(cmd, SIGNAL(finished(bool,int,QVariant)), this, SLOT(finishSubmoduleUpdate())); } @@ -2555,7 +2548,7 @@ QStringList GitClient::synchronousRepositoryBranches(const QString &repositoryUR const unsigned flags = VcsBasePlugin::SshPasswordPrompt | VcsBasePlugin::SuppressStdErrInLogWindow | VcsBasePlugin::SuppressFailMessageInLogWindow; - const Utils::SynchronousProcessResponse resp = synchronousGit(QString(), arguments, flags); + const SynchronousProcessResponse resp = synchronousGit(QString(), arguments, flags); QStringList branches; branches << tr(""); QString headSha; @@ -2605,8 +2598,8 @@ void GitClient::launchGitK(const QString &workingDirectory, const QString &fileN VcsOutputWindow::appendSilently(msgCannotLaunch(gitkPath)); } - Utils::Environment sysEnv = Utils::Environment::systemEnvironment(); - const Utils::FileName exec = sysEnv.searchInPath(QLatin1String("gitk")); + Environment sysEnv = Environment::systemEnvironment(); + const FileName exec = sysEnv.searchInPath(QLatin1String("gitk")); if (!exec.isEmpty() && tryLauchingGitK(env, workingDirectory, fileName, exec.parentDir().toString())) { @@ -2630,7 +2623,7 @@ bool GitClient::tryLauchingGitK(const QProcessEnvironment &env, { QString binary = gitBinDirectory + QLatin1String("/gitk"); QStringList arguments; - if (Utils::HostOsInfo::isWindowsHost()) { + if (HostOsInfo::isWindowsHost()) { // If git/bin is in path, use 'wish' shell to run. Otherwise (git/cmd), directly run gitk QString wish = gitBinDirectory + QLatin1String("/wish"); if (QFileInfo(wish + QLatin1String(".exe")).exists()) { @@ -2640,10 +2633,10 @@ bool GitClient::tryLauchingGitK(const QProcessEnvironment &env, } const QString gitkOpts = settings()->stringValue(GitSettings::gitkOptionsKey); if (!gitkOpts.isEmpty()) - arguments.append(Utils::QtcProcess::splitArgs(gitkOpts, Utils::HostOsInfo::hostOs())); + arguments.append(QtcProcess::splitArgs(gitkOpts, HostOsInfo::hostOs())); if (!fileName.isEmpty()) arguments << QLatin1String("--") << fileName; - VcsOutputWindow::appendCommand(workingDirectory, Utils::FileName::fromString(binary), arguments); + VcsOutputWindow::appendCommand(workingDirectory, FileName::fromString(binary), arguments); // This should always use QProcess::startDetached (as not to kill // the child), but that does not have an environment parameter. bool success = false; @@ -2666,7 +2659,7 @@ bool GitClient::tryLauchingGitK(const QProcessEnvironment &env, bool GitClient::launchGitGui(const QString &workingDirectory) { bool success; - Utils::FileName gitBinary = gitExecutable(&success); + FileName gitBinary = gitExecutable(&success); if (success) { success = QProcess::startDetached(gitBinary.toString(), QStringList(QLatin1String("gui")), workingDirectory); @@ -2678,25 +2671,25 @@ bool GitClient::launchGitGui(const QString &workingDirectory) { return success; } -Utils::FileName GitClient::gitBinDirectory() +FileName GitClient::gitBinDirectory() { const QString git = gitExecutable().toString(); if (git.isEmpty()) - return Utils::FileName(); + return FileName(); // Is 'git\cmd' in the path (folder containing .bats)? QString path = QFileInfo(git).absolutePath(); // Git for Windows (msysGit) has git and gitk redirect executables in {setup dir}/cmd // and the real binaries are in {setup dir}/bin. If cmd is configured in PATH // or in Git settings, return bin instead. - if (Utils::HostOsInfo::isWindowsHost() - && path.endsWith(QLatin1String("/cmd"), Utils::HostOsInfo::fileNameCaseSensitivity())) { + if (HostOsInfo::isWindowsHost() + && path.endsWith(QLatin1String("/cmd"), HostOsInfo::fileNameCaseSensitivity())) { path.replace(path.size() - 3, 3, QLatin1String("bin")); } - return Utils::FileName::fromString(path); + return FileName::fromString(path); } -Utils::FileName GitClient::gitExecutable(bool *ok, QString *errorMessage) const +FileName GitClient::gitExecutable(bool *ok, QString *errorMessage) const { return settings()->gitExecutable(ok, errorMessage); } @@ -2735,7 +2728,7 @@ bool GitClient::readDataFromCommit(const QString &repoDirectory, const QString & *errorMessage = tr("Cannot retrieve last commit data of repository \"%1\".").arg(repoDirectory); return false; } - QTextCodec *authorCodec = Utils::HostOsInfo::isWindowsHost() + QTextCodec *authorCodec = HostOsInfo::isWindowsHost() ? QTextCodec::codecForName("UTF-8") : commitData.commitEncoding; commitData.amendSHA1 = QString::fromLatin1(shiftLogLine(outputText)); @@ -2809,7 +2802,7 @@ bool GitClient::getCommitData(const QString &workingDirectory, // Filter out untracked files that are not part of the project QStringList untrackedFiles = commitData.filterFiles(UntrackedFile); - VcsBase::VcsBaseSubmitEditor::filterUntrackedFilesOfProject(repoDirectory, &untrackedFiles); + VcsBaseSubmitEditor::filterUntrackedFilesOfProject(repoDirectory, &untrackedFiles); QList filteredFiles; QList::const_iterator it = commitData.files.constBegin(); for ( ; it != commitData.files.constEnd(); ++it) { @@ -2855,7 +2848,7 @@ bool GitClient::getCommitData(const QString &workingDirectory, if (!QFile::exists(templateFilename)) templateFilename = gitDirectory.absoluteFilePath(QLatin1String("SQUASH_MSG")); if (!QFile::exists(templateFilename)) { - Utils::FileName templateName = Utils::FileName::fromUserInput( + FileName templateName = FileName::fromUserInput( readConfigValue(workingDirectory, QLatin1String("commit.template"))); templateFilename = templateName.toString(); } @@ -2864,7 +2857,7 @@ bool GitClient::getCommitData(const QString &workingDirectory, const QFileInfo templateFileInfo(templateFilename); if (templateFileInfo.isRelative()) templateFilename = repoDirectory + QLatin1Char('/') + templateFilename; - Utils::FileReader reader; + FileReader reader; if (!reader.fetch(templateFilename, QIODevice::Text, errorMessage)) return false; *commitTemplate = QString::fromLocal8Bit(reader.data()); @@ -2900,7 +2893,7 @@ bool GitClient::addAndCommit(const QString &repositoryDirectory, CommitType commitType, const QString &amendSHA1, const QString &messageFile, - VcsBase::SubmitFileModel *model) + SubmitFileModel *model) { const QString renameSeparator = QLatin1String(" -> "); @@ -3102,7 +3095,7 @@ void GitClient::fetch(const QString &workingDirectory, const QString &remote) { QStringList arguments(QLatin1String("fetch")); arguments << (remote.isEmpty() ? QLatin1String("--all") : remote); - VcsBase::Command *command = executeGit(workingDirectory, arguments, 0, true); + VcsCommand *command = executeGit(workingDirectory, arguments, 0, true); command->setCookie(workingDirectory); connect(command, SIGNAL(success(QVariant)), this, SLOT(fetchFinished(QVariant))); } @@ -3115,10 +3108,10 @@ bool GitClient::executeAndHandleConflicts(const QString &workingDirectory, const unsigned flags = VcsBasePlugin::SshPasswordPrompt | VcsBasePlugin::ShowStdOutInLogWindow | VcsBasePlugin::ExpectRepoChanges; - const Utils::SynchronousProcessResponse resp = synchronousGit(workingDirectory, arguments, flags); + const SynchronousProcessResponse resp = synchronousGit(workingDirectory, arguments, flags); ConflictHandler conflictHandler(0, workingDirectory, abortCommand); // Notify about changed files or abort the rebase. - const bool ok = resp.result == Utils::SynchronousProcessResponse::Finished; + const bool ok = resp.result == SynchronousProcessResponse::Finished; if (!ok) { conflictHandler.readStdOut(resp.stdOut); conflictHandler.readStdErr(resp.stdErr); @@ -3264,8 +3257,8 @@ void GitClient::subversionLog(const QString &workingDirectory) // Create a command editor, no highlighting or interaction. const QString title = tr("Git SVN Log"); const Id editorId = Git::Constants::C_GIT_COMMAND_LOG_EDITOR; - const QString sourceFile = VcsBase::VcsBaseEditor::getSource(workingDirectory, QStringList()); - VcsBase::VcsBaseEditorWidget *editor = findExistingVCSEditor("svnLog", sourceFile); + const QString sourceFile = VcsBaseEditor::getSource(workingDirectory, QStringList()); + VcsBaseEditorWidget *editor = findExistingVCSEditor("svnLog", sourceFile); if (!editor) editor = createVcsEditor(editorId, title, sourceFile, CodecNone, "svnLog", sourceFile, 0); editor->setWorkingDirectory(workingDirectory); @@ -3329,10 +3322,10 @@ void GitClient::asyncCommand(const QString &workingDirectory, const QStringList // and without timeout QString gitCommand = arguments.first(); VcsOutputWindow::appendCommand(workingDirectory, settings()->binaryPath(), arguments); - VcsBase::Command *command = createCommand(workingDirectory, 0, true); + VcsCommand *command = createCommand(workingDirectory, 0, true); new ConflictHandler(command, workingDirectory, gitCommand); if (hasProgress) - command->setProgressParser(new ProgressParser); + command->setProgressParser(new GitProgressParser); command->addJob(arguments, -1); command->execute(); command->setCookie(workingDirectory); @@ -3398,8 +3391,8 @@ void GitClient::stashPop(const QString &workingDirectory, const QString &stash) arguments << QLatin1String("pop"); if (!stash.isEmpty()) arguments << stash; - VcsBase::Command *cmd = executeGit(workingDirectory, arguments, 0, true, - VcsBasePlugin::ExpectRepoChanges); + VcsCommand *cmd = executeGit(workingDirectory, arguments, 0, true, + VcsBasePlugin::ExpectRepoChanges); new ConflictHandler(cmd, workingDirectory); } @@ -3474,7 +3467,7 @@ QByteArray GitClient::readConfigBytes(const QString &workingDirectory, const QSt if (!fullySynchronousGit(workingDirectory, arguments, &outputText, &errorText, VcsBasePlugin::SuppressCommandLogging)) return QByteArray(); - if (Utils::HostOsInfo::isWindowsHost()) + if (HostOsInfo::isWindowsHost()) outputText.replace("\r\n", "\n"); return outputText; } @@ -3484,11 +3477,11 @@ QString GitClient::readConfigValue(const QString &workingDirectory, const QStrin { // msysGit always uses UTF-8 for configuration: // https://github.com/msysgit/msysgit/wiki/Git-for-Windows-Unicode-Support#convert-config-files - static QTextCodec *codec = Utils::HostOsInfo::isWindowsHost() + static QTextCodec *codec = HostOsInfo::isWindowsHost() ? QTextCodec::codecForName("UTF-8") : QTextCodec::codecForLocale(); const QByteArray value = readConfigBytes(workingDirectory, configVar).trimmed(); - return Utils::SynchronousProcess::normalizeNewlines(codec->toUnicode(value)); + return SynchronousProcess::normalizeNewlines(codec->toUnicode(value)); } bool GitClient::cloneRepository(const QString &directory,const QByteArray &url) @@ -3509,9 +3502,9 @@ bool GitClient::cloneRepository(const QString &directory,const QByteArray &url) arguments.clear(); arguments << QLatin1String("fetch"); - const Utils::SynchronousProcessResponse resp = + const SynchronousProcessResponse resp = synchronousGit(workingDirectory.path(), arguments, flags); - if (resp.result != Utils::SynchronousProcessResponse::Finished) + if (resp.result != SynchronousProcessResponse::Finished) return false; arguments.clear(); @@ -3533,11 +3526,11 @@ bool GitClient::cloneRepository(const QString &directory,const QByteArray &url) QStringList arguments(QLatin1String("clone")); arguments << QLatin1String(url) << workingDirectory.dirName(); workingDirectory.cdUp(); - const Utils::SynchronousProcessResponse resp = + const SynchronousProcessResponse resp = synchronousGit(workingDirectory.path(), arguments, flags); // TODO: Turn this into a VcsBaseClient and use resetCachedVcsInfo(...) VcsManager::resetVersionControlForDirectory(workingDirectory.absolutePath()); - return (resp.result == Utils::SynchronousProcessResponse::Finished); + return (resp.result == SynchronousProcessResponse::Finished); } } @@ -3563,7 +3556,7 @@ GitSettings *GitClient::settings() const // determine version as '(major << 16) + (minor << 8) + patch' or 0. unsigned GitClient::gitVersion(QString *errorMessage) const { - const Utils::FileName newGitBinary = gitExecutable(); + const FileName newGitBinary = gitExecutable(); if (m_gitVersionForBinary != newGitBinary && !newGitBinary.isEmpty()) { // Do not execute repeatedly if that fails (due to git // not being installed) until settings are changed. diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h index 07af9a0a48..9dda535bbf 100644 --- a/src/plugins/git/gitclient.h +++ b/src/plugins/git/gitclient.h @@ -54,7 +54,7 @@ QT_END_NAMESPACE namespace Core { class ICore; } namespace VcsBase { - class Command; + class VcsCommand; class SubmitFileModel; class VcsBaseEditorWidget; class VcsBaseEditorParameterWidget; @@ -374,12 +374,12 @@ private: const QString &source, const QString &title) const; - VcsBase::Command *createCommand(const QString &workingDirectory, + VcsBase::VcsCommand *createCommand(const QString &workingDirectory, VcsBase::VcsBaseEditorWidget* editor = 0, bool useOutputToWindow = false, int editorLineNumber = -1); - VcsBase::Command *executeGit(const QString &workingDirectory, + VcsBase::VcsCommand *executeGit(const QString &workingDirectory, const QStringList &arguments, VcsBase::VcsBaseEditorWidget* editor = 0, bool useOutputToWindow = false, @@ -407,7 +407,7 @@ private: bool *isDirectory, QString *errorMessage, bool revertStaging); - void connectRepositoryChanged(const QString & repository, VcsBase::Command *cmd); + void connectRepositoryChanged(const QString & repository, VcsBase::VcsCommand *cmd); bool executeAndHandleConflicts(const QString &workingDirectory, const QStringList &arguments, const QString &abortCommand = QString()) const; bool tryLauchingGitK(const QProcessEnvironment &env, diff --git a/src/plugins/git/gitorious/gitoriousclonewizard.cpp b/src/plugins/git/gitorious/gitoriousclonewizard.cpp index b642ffe3ce..91c461dbce 100644 --- a/src/plugins/git/gitorious/gitoriousclonewizard.cpp +++ b/src/plugins/git/gitorious/gitoriousclonewizard.cpp @@ -94,7 +94,7 @@ GitoriousCloneWizard::GitoriousCloneWizard(const Utils::FileName &path, QWidget addPage(clonePage); } -VcsBase::Command *GitoriousCloneWizard::createCommand(Utils::FileName *checkoutDir) +VcsBase::VcsCommand *GitoriousCloneWizard::createCommand(Utils::FileName *checkoutDir) { const Git::CloneWizardPage *cwp = 0; foreach (int pageId, pageIds()) { diff --git a/src/plugins/git/gitorious/gitoriousclonewizard.h b/src/plugins/git/gitorious/gitoriousclonewizard.h index 9588a51b7c..fe14612638 100644 --- a/src/plugins/git/gitorious/gitoriousclonewizard.h +++ b/src/plugins/git/gitorious/gitoriousclonewizard.h @@ -47,7 +47,7 @@ public: GitoriousCloneWizard(const Utils::FileName &path, QWidget *parent = 0); protected: - VcsBase::Command *createCommand(Utils::FileName *checkoutDir); + VcsBase::VcsCommand *createCommand(Utils::FileName *checkoutDir); }; diff --git a/src/plugins/mercurial/clonewizard.cpp b/src/plugins/mercurial/clonewizard.cpp index 1884958f9b..b13a5d3069 100644 --- a/src/plugins/mercurial/clonewizard.cpp +++ b/src/plugins/mercurial/clonewizard.cpp @@ -33,19 +33,20 @@ #include "mercurialsettings.h" #include -#include +#include #include #include -using namespace Mercurial::Internal; using namespace VcsBase; +namespace Mercurial { +namespace Internal { // -------------------------------------------------------------------- // CloneWizard: // -------------------------------------------------------------------- CloneWizard::CloneWizard(const Utils::FileName &path, QWidget *parent) : - VcsBase::BaseCheckoutWizard(path, parent) + BaseCheckoutWizard(path, parent) { setTitle(tr("Cloning")); setStartedStatus(tr("Cloning started...")); @@ -58,7 +59,7 @@ CloneWizard::CloneWizard(const Utils::FileName &path, QWidget *parent) : addPage(page); } -Command *CloneWizard::createCommand(Utils::FileName *checkoutDir) +VcsCommand *CloneWizard::createCommand(Utils::FileName *checkoutDir) { const CloneWizardPage *cwp = 0; foreach (int pageId, pageIds()) { @@ -77,8 +78,11 @@ Command *CloneWizard::createCommand(Utils::FileName *checkoutDir) QStringList args; args << QLatin1String("clone") << cwp->repository() << directory; *checkoutDir = Utils::FileName::fromString(path + QLatin1Char('/') + directory); - VcsBase::Command *command = new VcsBase::Command(settings.binaryPath(), path, - QProcessEnvironment::systemEnvironment()); + VcsCommand *command = new VcsCommand(settings.binaryPath(), path, + QProcessEnvironment::systemEnvironment()); command->addJob(args, -1); return command; } + +} // namespace Internal +} // namespace Mercurial diff --git a/src/plugins/mercurial/clonewizard.h b/src/plugins/mercurial/clonewizard.h index 05f14ea2cb..0fc3eb3c53 100644 --- a/src/plugins/mercurial/clonewizard.h +++ b/src/plugins/mercurial/clonewizard.h @@ -44,7 +44,7 @@ public: CloneWizard(const Utils::FileName &path, QWidget *parent = 0); protected: - VcsBase::Command *createCommand(Utils::FileName *checkoutDir); + VcsBase::VcsCommand *createCommand(Utils::FileName *checkoutDir); }; } //namespace Internal diff --git a/src/plugins/mercurial/mercurialclient.cpp b/src/plugins/mercurial/mercurialclient.cpp index aabc2b5ca9..4d97982499 100644 --- a/src/plugins/mercurial/mercurialclient.cpp +++ b/src/plugins/mercurial/mercurialclient.cpp @@ -30,7 +30,7 @@ #include "mercurialclient.h" #include "constants.h" -#include +#include #include #include #include @@ -46,19 +46,20 @@ #include #include +using namespace Utils; using namespace VcsBase; namespace Mercurial { namespace Internal { MercurialClient::MercurialClient(MercurialSettings *settings) : - VcsBase::VcsBaseClient(settings) + VcsBaseClient(settings) { } MercurialSettings *MercurialClient::settings() const { - return dynamic_cast(VcsBase::VcsBaseClient::settings()); + return dynamic_cast(VcsBaseClient::settings()); } bool MercurialClient::manifestSync(const QString &repository, const QString &relativeFilename) @@ -90,9 +91,9 @@ bool MercurialClient::synchronousClone(const QString &workingDir, Q_UNUSED(extraOptions); QDir workingDirectory(srcLocation); QByteArray output; - const unsigned flags = VcsBase::VcsBasePlugin::SshPasswordPrompt | - VcsBase::VcsBasePlugin::ShowStdOutInLogWindow | - VcsBase::VcsBasePlugin::ShowSuccessMessage; + const unsigned flags = VcsBasePlugin::SshPasswordPrompt | + VcsBasePlugin::ShowStdOutInLogWindow | + VcsBasePlugin::ShowSuccessMessage; if (workingDirectory.exists()) { // Let's make first init @@ -103,33 +104,33 @@ bool MercurialClient::synchronousClone(const QString &workingDir, // Then pull remote repository arguments.clear(); arguments << QLatin1String("pull") << dstLocation; - const Utils::SynchronousProcessResponse resp1 = + const SynchronousProcessResponse resp1 = vcsSynchronousExec(workingDirectory.path(), arguments, flags); - if (resp1.result != Utils::SynchronousProcessResponse::Finished) + if (resp1.result != SynchronousProcessResponse::Finished) return false; // By now, there is no hgrc file -> create it - Utils::FileSaver saver(workingDirectory.path() + QLatin1String("/.hg/hgrc")); + FileSaver saver(workingDirectory.path() + QLatin1String("/.hg/hgrc")); const QString hgrc = QLatin1String("[paths]\ndefault = ") + dstLocation + QLatin1Char('\n'); saver.write(hgrc.toUtf8()); if (!saver.finalize()) { - VcsBase::VcsOutputWindow::appendError(saver.errorString()); + VcsOutputWindow::appendError(saver.errorString()); return false; } // And last update repository arguments.clear(); arguments << QLatin1String("update"); - const Utils::SynchronousProcessResponse resp2 = + const SynchronousProcessResponse resp2 = vcsSynchronousExec(workingDirectory.path(), arguments, flags); - return resp2.result == Utils::SynchronousProcessResponse::Finished; + return resp2.result == SynchronousProcessResponse::Finished; } else { QStringList arguments(QLatin1String("clone")); arguments << dstLocation << workingDirectory.dirName(); workingDirectory.cdUp(); - const Utils::SynchronousProcessResponse resp = + const SynchronousProcessResponse resp = vcsSynchronousExec(workingDirectory.path(), arguments, flags); - return resp.result == Utils::SynchronousProcessResponse::Finished; + return resp.result == SynchronousProcessResponse::Finished; } } @@ -139,18 +140,18 @@ bool MercurialClient::synchronousPull(const QString &workingDir, const QString & args << vcsCommandString(PullCommand) << extraOptions << srcLocation; // Disable UNIX terminals to suppress SSH prompting const unsigned flags = - VcsBase::VcsBasePlugin::SshPasswordPrompt - | VcsBase::VcsBasePlugin::ShowStdOutInLogWindow - | VcsBase::VcsBasePlugin::ShowSuccessMessage; - const Utils::FileName binary = settings()->binaryPath(); + VcsBasePlugin::SshPasswordPrompt + | VcsBasePlugin::ShowStdOutInLogWindow + | VcsBasePlugin::ShowSuccessMessage; + const FileName binary = settings()->binaryPath(); const int timeoutSec = settings()->value(settings()->timeoutKey).toInt(); // cause mercurial doesn`t understand LANG QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); env.insert(QLatin1String("LANGUAGE"), QLatin1String("C")); - const Utils::SynchronousProcessResponse resp = VcsBase::VcsBasePlugin::runVcs( + const SynchronousProcessResponse resp = VcsBasePlugin::runVcs( workingDir, binary, args, timeoutSec * 1000, flags, 0, env); - const bool ok = resp.result == Utils::SynchronousProcessResponse::Finished; + const bool ok = resp.result == SynchronousProcessResponse::Finished; parsePullOutput(resp.stdOut.trimmed()); return ok; @@ -192,7 +193,7 @@ QStringList MercurialClient::parentRevisionsSync(const QString &workingDirectory QByteArray outputData; if (!vcsFullySynchronousExec(workingDirectory, args, &outputData)) return QStringList(); - const QString output = Utils::SynchronousProcess::normalizeNewlines( + const QString output = SynchronousProcess::normalizeNewlines( QString::fromLocal8Bit(outputData)); /* Looks like: \code changeset: 0:031a48610fba @@ -285,9 +286,9 @@ void MercurialClient::incoming(const QString &repositoryRoot, const QString &rep const QString title = tr("Hg incoming %1").arg(id); - VcsBase::VcsBaseEditorWidget *editor = createVcsEditor(Constants::DIFFLOG, title, repositoryRoot, - true, "incoming", id); - VcsBase::Command *cmd = createCommand(repository, editor); + VcsBaseEditorWidget *editor = createVcsEditor(Constants::DIFFLOG, title, repositoryRoot, + true, "incoming", id); + VcsCommand *cmd = createCommand(repository, editor); enqueueJob(cmd, args); } @@ -299,10 +300,10 @@ void MercurialClient::outgoing(const QString &repositoryRoot) const QString title = tr("Hg outgoing %1"). arg(QDir::toNativeSeparators(repositoryRoot)); - VcsBase::VcsBaseEditorWidget *editor = createVcsEditor(Constants::DIFFLOG, title, repositoryRoot, true, - "outgoing", repositoryRoot); + VcsBaseEditorWidget *editor = createVcsEditor(Constants::DIFFLOG, title, repositoryRoot, true, + "outgoing", repositoryRoot); - VcsBase::Command *cmd = createCommand(repositoryRoot, editor); + VcsCommand *cmd = createCommand(repositoryRoot, editor); enqueueJob(cmd, args); } @@ -358,11 +359,11 @@ QString MercurialClient::findTopLevelForFile(const QFileInfo &file) const { const QString repositoryCheckFile = QLatin1String(Constants::MERCURIALREPO) + QLatin1String("/requires"); return file.isDir() ? - VcsBase::VcsBasePlugin::findRepositoryForDirectory(file.absoluteFilePath(), repositoryCheckFile) : - VcsBase::VcsBasePlugin::findRepositoryForDirectory(file.absolutePath(), repositoryCheckFile); + VcsBasePlugin::findRepositoryForDirectory(file.absoluteFilePath(), repositoryCheckFile) : + VcsBasePlugin::findRepositoryForDirectory(file.absolutePath(), repositoryCheckFile); } -Core::Id MercurialClient::vcsEditorKind(VcsCommand cmd) const +Core::Id MercurialClient::vcsEditorKind(VcsCommandTag cmd) const { switch (cmd) { case AnnotateCommand: @@ -433,13 +434,13 @@ struct MercurialDiffParameters }; // Parameter widget controlling whitespace diff mode, associated with a parameter -class MercurialDiffParameterWidget : public VcsBase::VcsBaseEditorParameterWidget +class MercurialDiffParameterWidget : public VcsBaseEditorParameterWidget { Q_OBJECT public: MercurialDiffParameterWidget(MercurialClient *client, const MercurialDiffParameters &p, QWidget *parent = 0) : - VcsBase::VcsBaseEditorParameterWidget(parent), m_client(client), m_params(p) + VcsBaseEditorParameterWidget(parent), m_client(client), m_params(p) { mapSetting(addToggleButton(QLatin1String("-w"), tr("Ignore Whitespace")), client->settings()->boolPointer(MercurialSettings::diffIgnoreWhiteSpaceKey)); @@ -457,7 +458,7 @@ private: const MercurialDiffParameters m_params; }; -VcsBase::VcsBaseEditorParameterWidget *MercurialClient::createDiffEditor( +VcsBaseEditorParameterWidget *MercurialClient::createDiffEditor( const QString &workingDir, const QStringList &files, const QStringList &extraOptions) { MercurialDiffParameters parameters; diff --git a/src/plugins/mercurial/mercurialclient.h b/src/plugins/mercurial/mercurialclient.h index 8b41db9455..cadb431aa9 100644 --- a/src/plugins/mercurial/mercurialclient.h +++ b/src/plugins/mercurial/mercurialclient.h @@ -84,7 +84,7 @@ public: QString findTopLevelForFile(const QFileInfo &file) const; protected: - Core::Id vcsEditorKind(VcsCommand cmd) const; + Core::Id vcsEditorKind(VcsCommandTag cmd) const; QStringList revisionSpec(const QString &revision) const; VcsBase::VcsBaseEditorParameterWidget *createDiffEditor(const QString &workingDir, const QStringList &files, diff --git a/src/plugins/mercurial/mercurialplugin.cpp b/src/plugins/mercurial/mercurialplugin.cpp index a8b89ba6f7..145b9abb31 100644 --- a/src/plugins/mercurial/mercurialplugin.cpp +++ b/src/plugins/mercurial/mercurialplugin.cpp @@ -79,16 +79,13 @@ using namespace Utils; namespace Mercurial { namespace Internal { -using namespace VcsBase::Constants; -using namespace Mercurial::Constants; - static const VcsBaseEditorParameters editorParameters[] = { { LogOutput, - FILELOG_ID, - FILELOG_DISPLAY_NAME, - FILELOG, - LOGAPP}, + Constants::FILELOG_ID, + Constants::FILELOG_DISPLAY_NAME, + Constants::FILELOG, + Constants::LOGAPP}, { AnnotateOutput, Constants::ANNOTATELOG_ID, @@ -108,7 +105,7 @@ static const VcsBaseSubmitEditorParameters submitEditorParameters = { Constants::COMMIT_ID, Constants::COMMIT_DISPLAY_NAME, Constants::COMMIT_ID, - VcsBase::VcsBaseSubmitEditorParameters::DiffFiles + VcsBaseSubmitEditorParameters::DiffFiles }; MercurialPlugin *MercurialPlugin::m_instance = 0; @@ -551,16 +548,16 @@ void MercurialPlugin::commit() m_submitRepository = state.topLevel(); - connect(m_client, SIGNAL(parsedStatus(QList)), - this, SLOT(showCommitWidget(QList))); + connect(m_client, SIGNAL(parsedStatus(QList)), + this, SLOT(showCommitWidget(QList))); m_client->emitParsedStatus(m_submitRepository); } void MercurialPlugin::showCommitWidget(const QList &status) { //Once we receive our data release the connection so it can be reused elsewhere - disconnect(m_client, SIGNAL(parsedStatus(QList)), - this, SLOT(showCommitWidget(QList))); + disconnect(m_client, SIGNAL(parsedStatus(QList)), + this, SLOT(showCommitWidget(QList))); if (status.isEmpty()) { VcsOutputWindow::appendError(tr("There are no changes to commit.")); @@ -572,7 +569,7 @@ void MercurialPlugin::showCommitWidget(const QList &s // Keep the file alive, else it removes self and forgets its name saver.setAutoRemove(false); if (!saver.finalize()) { - VcsBase::VcsOutputWindow::appendError(saver.errorString()); + VcsOutputWindow::appendError(saver.errorString()); return; } diff --git a/src/plugins/subversion/checkoutwizard.cpp b/src/plugins/subversion/checkoutwizard.cpp index 9c520bd809..6e539133e8 100644 --- a/src/plugins/subversion/checkoutwizard.cpp +++ b/src/plugins/subversion/checkoutwizard.cpp @@ -33,11 +33,14 @@ #include "subversionclient.h" #include -#include +#include #include #include #include +using namespace Utils; +using namespace VcsBase; + namespace Subversion { namespace Internal { @@ -45,18 +48,18 @@ namespace Internal { // CheckoutWizard: // -------------------------------------------------------------------- -CheckoutWizard::CheckoutWizard(const Utils::FileName &path, QWidget *parent) : - VcsBase::BaseCheckoutWizard(path, parent) +CheckoutWizard::CheckoutWizard(const FileName &path, QWidget *parent) : + BaseCheckoutWizard(path, parent) { const Core::IVersionControl *vc = SubversionPlugin::instance()->versionControl(); if (!vc->isConfigured()) - addPage(new VcsBase::VcsConfigurationPage(vc)); + addPage(new VcsConfigurationPage(vc)); CheckoutWizardPage *cwp = new CheckoutWizardPage; cwp->setPath(path.toString()); addPage(cwp); } -VcsBase::Command *CheckoutWizard::createCommand(Utils::FileName *checkoutDir) +VcsCommand *CheckoutWizard::createCommand(FileName *checkoutDir) { // Collect parameters for the checkout command. const CheckoutWizardPage *cwp = 0; @@ -67,21 +70,21 @@ VcsBase::Command *CheckoutWizard::createCommand(Utils::FileName *checkoutDir) QTC_ASSERT(cwp, return 0); const SubversionSettings settings = SubversionPlugin::instance()->settings(); - const Utils::FileName binary = settings.binaryPath(); + const FileName binary = settings.binaryPath(); const QString directory = cwp->directory(); QStringList args; args << QLatin1String("checkout") << cwp->repository() << directory; const QString workingDirectory = cwp->path(); - *checkoutDir = Utils::FileName::fromString(workingDirectory + QLatin1Char('/') + directory); + *checkoutDir = FileName::fromString(workingDirectory + QLatin1Char('/') + directory); if (settings.hasAuthentication()) { const QString user = settings.stringValue(SubversionSettings::userKey); const QString pwd = settings.stringValue(SubversionSettings::passwordKey); args = SubversionClient::addAuthenticationOptions(args, user, pwd); } - VcsBase::Command *command = new VcsBase::Command(binary, workingDirectory, - QProcessEnvironment::systemEnvironment()); + VcsCommand *command = new VcsCommand(binary, workingDirectory, + QProcessEnvironment::systemEnvironment()); command->addJob(args, -1); return command; } diff --git a/src/plugins/subversion/checkoutwizard.h b/src/plugins/subversion/checkoutwizard.h index 690aaf5150..c6ebfe938c 100644 --- a/src/plugins/subversion/checkoutwizard.h +++ b/src/plugins/subversion/checkoutwizard.h @@ -44,7 +44,7 @@ public: CheckoutWizard(const Utils::FileName &path, QWidget *parent = 0); protected: - VcsBase::Command *createCommand(Utils::FileName *checkoutDir); + VcsBase::VcsCommand *createCommand(Utils::FileName *checkoutDir); }; } // namespace Internal diff --git a/src/plugins/subversion/subversionclient.cpp b/src/plugins/subversion/subversionclient.cpp index 2703de39e9..7334287baf 100644 --- a/src/plugins/subversion/subversionclient.cpp +++ b/src/plugins/subversion/subversionclient.cpp @@ -31,7 +31,7 @@ #include "subversionsettings.h" #include "subversionconstants.h" -#include +#include #include #include #include @@ -42,6 +42,9 @@ #include #include +using namespace Utils; +using namespace VcsBase; + namespace Subversion { namespace Internal { @@ -55,7 +58,7 @@ struct SubversionDiffParameters }; // Parameter widget controlling whitespace diff mode, associated with a parameter -class SubversionDiffParameterWidget : public VcsBase::VcsBaseEditorParameterWidget +class SubversionDiffParameterWidget : public VcsBaseEditorParameterWidget { Q_OBJECT public: @@ -73,7 +76,7 @@ private: SubversionDiffParameterWidget::SubversionDiffParameterWidget(SubversionClient *client, const SubversionDiffParameters &p, QWidget *parent) - : VcsBase::VcsBaseEditorParameterWidget(parent), m_client(client), m_params(p) + : VcsBaseEditorParameterWidget(parent), m_client(client), m_params(p) { mapSetting(addToggleButton(QLatin1String("w"), tr("Ignore Whitespace")), client->settings()->boolPointer(SubversionSettings::diffIgnoreWhiteSpaceKey)); @@ -97,19 +100,19 @@ void SubversionDiffParameterWidget::executeCommand() } SubversionClient::SubversionClient(SubversionSettings *settings) : - VcsBase::VcsBaseClient(settings) + VcsBaseClient(settings) { } SubversionSettings *SubversionClient::settings() const { - return dynamic_cast(VcsBase::VcsBaseClient::settings()); + return dynamic_cast(VcsBaseClient::settings()); } -VcsBase::Command *SubversionClient::createCommitCmd(const QString &repositoryRoot, - const QStringList &files, - const QString &commitMessageFile, - const QStringList &extraOptions) const +VcsCommand *SubversionClient::createCommitCmd(const QString &repositoryRoot, + const QStringList &files, + const QString &commitMessageFile, + const QStringList &extraOptions) const { const QStringList svnExtraOptions = QStringList(extraOptions) @@ -117,7 +120,7 @@ VcsBase::Command *SubversionClient::createCommitCmd(const QString &repositoryRoo << QLatin1String(Constants::NON_INTERACTIVE_OPTION) << QLatin1String("--file") << commitMessageFile; - VcsBase::Command *cmd = createCommand(repositoryRoot); + VcsCommand *cmd = createCommand(repositoryRoot); QStringList args(vcsCommandString(CommitCommand)); cmd->addJob(args << svnExtraOptions << files); return cmd; @@ -131,11 +134,11 @@ void SubversionClient::commit(const QString &repositoryRoot, if (Subversion::Constants::debug) qDebug() << Q_FUNC_INFO << commitMessageFile << files; - VcsBase::Command *cmd = createCommitCmd(repositoryRoot, files, commitMessageFile, extraOptions); + VcsCommand *cmd = createCommitCmd(repositoryRoot, files, commitMessageFile, extraOptions); cmd->execute(); } -Core::Id SubversionClient::vcsEditorKind(VcsCommand cmd) const +Core::Id SubversionClient::vcsEditorKind(VcsCommandTag cmd) const { switch (cmd) { case DiffCommand: @@ -150,10 +153,10 @@ SubversionClient::Version SubversionClient::svnVersion() if (m_svnVersionBinary != settings()->binaryPath()) { QStringList args; args << QLatin1String("--version") << QLatin1String("-q"); - const Utils::SynchronousProcessResponse response = - VcsBase::VcsBasePlugin::runVcs(QDir().absolutePath(), settings()->binaryPath(), - args, settings()->timeOutMs()); - if (response.result == Utils::SynchronousProcessResponse::Finished && + const SynchronousProcessResponse response = + VcsBasePlugin::runVcs(QDir().absolutePath(), settings()->binaryPath(), + args, settings()->timeOutMs()); + if (response.result == SynchronousProcessResponse::Finished && response.exitCode == 0) { m_svnVersionBinary = settings()->binaryPath(); m_svnVersion = response.stdOut.trimmed(); @@ -172,7 +175,7 @@ SubversionClient::Version SubversionClient::svnVersion() return v; } -QStringList SubversionClient::authenticationOptions(VcsCommand cmd) const +QStringList SubversionClient::authenticationOptions(VcsCommandTag cmd) const { const bool hasAuth = settings()->hasAuthentication(); const QString userName = hasAuth ? settings()->stringValue(SubversionSettings::userKey) : QString(); @@ -235,13 +238,13 @@ QStringList SubversionClient::revisionSpec(const QString &revision) const return QStringList(); } -VcsBase::VcsBaseClient::StatusItem SubversionClient::parseStatusLine(const QString &line) const +VcsBaseClient::StatusItem SubversionClient::parseStatusLine(const QString &line) const { Q_UNUSED(line) - return VcsBase::VcsBaseClient::StatusItem(); + return VcsBaseClient::StatusItem(); } -VcsBase::VcsBaseEditorParameterWidget *SubversionClient::createDiffEditor( +VcsBaseEditorParameterWidget *SubversionClient::createDiffEditor( const QString &workingDir, const QStringList &files, const QStringList &extraOptions) { Q_UNUSED(extraOptions) diff --git a/src/plugins/subversion/subversionclient.h b/src/plugins/subversion/subversionclient.h index f515219641..b9b5bd612a 100644 --- a/src/plugins/subversion/subversionclient.h +++ b/src/plugins/subversion/subversionclient.h @@ -32,6 +32,7 @@ #include "subversionsettings.h" #include +#include #include @@ -49,10 +50,10 @@ public: SubversionSettings *settings() const; - VcsBase::Command *createCommitCmd(const QString &repositoryRoot, - const QStringList &files, - const QString &commitMessageFile, - const QStringList &extraOptions = QStringList()) const; + VcsBase::VcsCommand *createCommitCmd(const QString &repositoryRoot, + const QStringList &files, + const QString &commitMessageFile, + const QStringList &extraOptions = QStringList()) const; void commit(const QString &repositoryRoot, const QStringList &files, const QString &commitMessageFile, @@ -74,13 +75,13 @@ public: Version svnVersion(); // Add authorization options to the command line arguments. - QStringList authenticationOptions(VcsCommand cmd) const; + QStringList authenticationOptions(VcsCommandTag cmd) const; static QStringList addAuthenticationOptions(const QStringList &args, const QString &userName = QString(), const QString &password = QString()); protected: - Core::Id vcsEditorKind(VcsCommand cmd) const; + Core::Id vcsEditorKind(VcsCommandTag cmd) const; VcsBase::VcsBaseEditorParameterWidget *createDiffEditor(const QString &workingDir, const QStringList &files, const QStringList &extraOptions); diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp index eb93379d31..4a75ce7936 100644 --- a/src/plugins/subversion/subversionplugin.cpp +++ b/src/plugins/subversion/subversionplugin.cpp @@ -39,7 +39,7 @@ #include "checkoutwizard.h" #include -#include +#include #include #include #include @@ -507,9 +507,9 @@ bool SubversionPlugin::submitEditorAboutToClose() // get message & commit closeEditor = DocumentManager::saveDocument(editorDocument); if (closeEditor) { - VcsBase::Command *commitCmd = m_client->createCommitCmd(m_commitRepository, - fileList, - m_commitMessageFileName); + VcsCommand *commitCmd = m_client->createCommitCmd(m_commitRepository, + fileList, + m_commitMessageFileName); QObject::connect(commitCmd, SIGNAL(success(QVariant)), this, SLOT(cleanCommitMessageFile())); commitCmd->execute(); diff --git a/src/plugins/vcsbase/basecheckoutwizard.cpp b/src/plugins/vcsbase/basecheckoutwizard.cpp index d2c83f5314..f248714eae 100644 --- a/src/plugins/vcsbase/basecheckoutwizard.cpp +++ b/src/plugins/vcsbase/basecheckoutwizard.cpp @@ -72,7 +72,7 @@ void BaseCheckoutWizard::slotPageChanged(int id) if (id != m_progressPageId) return; - VcsBase::Command *cmd = createCommand(&m_checkoutDir); + VcsBase::VcsCommand *cmd = createCommand(&m_checkoutDir); QTC_ASSERT(cmd, done(QDialog::Rejected)); // No "back" available while running. diff --git a/src/plugins/vcsbase/basecheckoutwizard.h b/src/plugins/vcsbase/basecheckoutwizard.h index 18d08a16fe..7266ebb7df 100644 --- a/src/plugins/vcsbase/basecheckoutwizard.h +++ b/src/plugins/vcsbase/basecheckoutwizard.h @@ -36,7 +36,7 @@ #include namespace VcsBase { -class Command; +class VcsCommand; namespace Internal { class CheckoutProgressWizardPage; } @@ -53,7 +53,7 @@ public: Utils::FileName run(); protected: - virtual VcsBase::Command *createCommand(Utils::FileName *checkoutDir) = 0; + virtual VcsBase::VcsCommand *createCommand(Utils::FileName *checkoutDir) = 0; private slots: void slotPageChanged(int id); diff --git a/src/plugins/vcsbase/basecheckoutwizardfactory.h b/src/plugins/vcsbase/basecheckoutwizardfactory.h index 95bb2580b4..21100f1228 100644 --- a/src/plugins/vcsbase/basecheckoutwizardfactory.h +++ b/src/plugins/vcsbase/basecheckoutwizardfactory.h @@ -39,7 +39,7 @@ namespace VcsBase { class BaseCheckoutWizard; -class Command; +class VcsCommand; class VCSBASE_EXPORT BaseCheckoutWizardFactory : public Core::IWizardFactory { diff --git a/src/plugins/vcsbase/checkoutprogresswizardpage.cpp b/src/plugins/vcsbase/checkoutprogresswizardpage.cpp index 7bbda50d8a..3e114b1cf9 100644 --- a/src/plugins/vcsbase/checkoutprogresswizardpage.cpp +++ b/src/plugins/vcsbase/checkoutprogresswizardpage.cpp @@ -28,7 +28,7 @@ ****************************************************************************/ #include "checkoutprogresswizardpage.h" -#include "command.h" +#include "vcscommand.h" #include "vcsbaseplugin.h" #include @@ -85,7 +85,7 @@ void CheckoutProgressWizardPage::setStartedStatus(const QString &startedStatus) m_startedStatus = startedStatus; } -void CheckoutProgressWizardPage::start(Command *command) +void CheckoutProgressWizardPage::start(VcsCommand *command) { if (!command) { m_logPlainTextEdit->setPlainText(tr("No job running, please abort.")); diff --git a/src/plugins/vcsbase/checkoutprogresswizardpage.h b/src/plugins/vcsbase/checkoutprogresswizardpage.h index e5c6cfbd84..86c9eebe67 100644 --- a/src/plugins/vcsbase/checkoutprogresswizardpage.h +++ b/src/plugins/vcsbase/checkoutprogresswizardpage.h @@ -41,7 +41,7 @@ QT_END_NAMESPACE namespace Utils { class OutputFormatter; } namespace VcsBase { -class Command; +class VcsCommand; namespace Internal { @@ -56,7 +56,7 @@ public: ~CheckoutProgressWizardPage(); void setStartedStatus(const QString &startedStatus); - void start(Command *command); + void start(VcsCommand *command); virtual bool isComplete() const; bool isRunning() const{ return m_state == Running; } @@ -76,7 +76,7 @@ private: Utils::OutputFormatter *m_formatter; QLabel *m_statusLabel; - Command *m_command; + VcsCommand *m_command; QString m_startedStatus; QString m_error; bool m_overwriteOutput; diff --git a/src/plugins/vcsbase/command.cpp b/src/plugins/vcsbase/command.cpp deleted file mode 100644 index bf9bb3b469..0000000000 --- a/src/plugins/vcsbase/command.cpp +++ /dev/null @@ -1,643 +0,0 @@ -/************************************************************************** -** -** Copyright (c) 2014 Brian McGillion and Hugues Delorme -** Contact: http://www.qt-project.org/legal -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "command.h" -#include "vcsbaseplugin.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -Q_DECLARE_METATYPE(QVariant) - -enum { debugExecution = 0 }; - -/*! - \fn void VcsBase::ProgressParser::parseProgress(const QString &text) - - Reimplement to parse progress as it appears in the standard output. - If a progress string is detected, call \c setProgressAndMaximum() to update - the progress bar accordingly. - - \sa VcsBase::ProgressParser::setProgressAndMaximum() -*/ - -/*! - \fn void VcsBase::ProgressParser::setProgressAndMaximum(int value, int maximum) - - Sets progress \a value and \a maximum for current command. Called by \c parseProgress() - when a progress string is detected. -*/ - -namespace VcsBase { -namespace Internal { - -class CommandPrivate -{ -public: - struct Job { - explicit Job(const QStringList &a, int t, Utils::ExitCodeInterpreter *interpreter = 0); - - QStringList arguments; - int timeout; - Utils::ExitCodeInterpreter *exitCodeInterpreter; - }; - - CommandPrivate(const Utils::FileName &binary, - const QString &workingDirectory, - const QProcessEnvironment &environment); - ~CommandPrivate(); - - const Utils::FileName m_binaryPath; - const QString m_workingDirectory; - const QProcessEnvironment m_environment; - QVariant m_cookie; - int m_defaultTimeout; - unsigned m_flags; - QTextCodec *m_codec; - const QString m_sshPasswordPrompt; - ProgressParser *m_progressParser; - bool m_progressiveOutput; - bool m_hadOutput; - bool m_preventRepositoryChanged; - bool m_aborted; - QFutureWatcher m_watcher; - - QList m_jobs; - - bool m_lastExecSuccess; - int m_lastExecExitCode; -}; - -CommandPrivate::CommandPrivate(const Utils::FileName &binary, - const QString &workingDirectory, - const QProcessEnvironment &environment) : - m_binaryPath(binary), - m_workingDirectory(workingDirectory), - m_environment(environment), - m_defaultTimeout(10), - m_flags(0), - m_codec(0), - m_sshPasswordPrompt(VcsBasePlugin::sshPrompt()), - m_progressParser(0), - m_progressiveOutput(false), - m_hadOutput(false), - m_preventRepositoryChanged(false), - m_aborted(false), - m_lastExecSuccess(false), - m_lastExecExitCode(-1) -{ -} - -CommandPrivate::~CommandPrivate() -{ - delete m_progressParser; -} - -CommandPrivate::Job::Job(const QStringList &a, int t, Utils::ExitCodeInterpreter *interpreter) : - arguments(a), - timeout(t), - exitCodeInterpreter(interpreter) -{ - // Finished cookie is emitted via queued slot, needs metatype - static const int qvMetaId = qRegisterMetaType(); - Q_UNUSED(qvMetaId) -} - -} // namespace Internal - -Command::Command(const Utils::FileName &binary, - const QString &workingDirectory, - const QProcessEnvironment &environment) : - d(new Internal::CommandPrivate(binary, workingDirectory, environment)) -{ - connect(Core::ICore::instance(), SIGNAL(coreAboutToClose()), - this, SLOT(coreAboutToClose())); -} - -Command::~Command() -{ - delete d; -} - -const Utils::FileName &Command::binaryPath() const -{ - return d->m_binaryPath; -} - -const QString &Command::workingDirectory() const -{ - return d->m_workingDirectory; -} - -const QProcessEnvironment &Command::processEnvironment() const -{ - return d->m_environment; -} - -int Command::defaultTimeout() const -{ - return d->m_defaultTimeout; -} - -void Command::setDefaultTimeout(int timeout) -{ - d->m_defaultTimeout = timeout; -} - -unsigned Command::flags() const -{ - return d->m_flags; -} - -void Command::addFlags(unsigned f) -{ - d->m_flags |= f; -} - -void Command::addJob(const QStringList &arguments, Utils::ExitCodeInterpreter *interpreter) -{ - addJob(arguments, defaultTimeout(), interpreter); -} - -void Command::addJob(const QStringList &arguments, int timeout, Utils::ExitCodeInterpreter *interpreter) -{ - d->m_jobs.push_back(Internal::CommandPrivate::Job(arguments, timeout, interpreter)); -} - -void Command::execute() -{ - d->m_lastExecSuccess = false; - d->m_lastExecExitCode = -1; - - if (d->m_jobs.empty()) - return; - - // For some reason QtConcurrent::run() only works on this - QFuture task = QtConcurrent::run(&Command::run, this); - d->m_watcher.setFuture(task); - connect(&d->m_watcher, SIGNAL(canceled()), this, SLOT(cancel())); - QString binary = d->m_binaryPath.toFileInfo().baseName(); - if (!binary.isEmpty()) - binary = binary.replace(0, 1, binary[0].toUpper()); // Upper the first letter - const QString taskName = binary + QLatin1Char(' ') + d->m_jobs.front().arguments.at(0); - - Core::ProgressManager::addTask(task, taskName, - Core::Id::fromString(binary + QLatin1String(".action"))); -} - -void Command::abort() -{ - d->m_aborted = true; - d->m_watcher.future().cancel(); -} - -void Command::cancel() -{ - emit terminate(); -} - -bool Command::lastExecutionSuccess() const -{ - return d->m_lastExecSuccess; -} - -int Command::lastExecutionExitCode() const -{ - return d->m_lastExecExitCode; -} - -void Command::run(QFutureInterface &future) -{ - // Check that the binary path is not empty - if (binaryPath().isEmpty()) { - emit errorText(tr("Unable to start process, binary is empty")); - return; - } - - QString stdOut; - QString stdErr; - - if (d->m_progressParser) - d->m_progressParser->setFuture(&future); - else - future.setProgressRange(0, 1); - const int count = d->m_jobs.size(); - d->m_lastExecExitCode = -1; - d->m_lastExecSuccess = true; - for (int j = 0; j < count; j++) { - const Internal::CommandPrivate::Job &job = d->m_jobs.at(j); - const int timeOutSeconds = job.timeout; - Utils::SynchronousProcessResponse resp = runVcs( - job.arguments, - timeOutSeconds >= 0 ? timeOutSeconds * 1000 : -1, - job.exitCodeInterpreter); - stdOut += resp.stdOut; - stdErr += resp.stdErr; - d->m_lastExecExitCode = resp.exitCode; - d->m_lastExecSuccess = resp.result == Utils::SynchronousProcessResponse::Finished; - if (!d->m_lastExecSuccess) - break; - } - - if (!d->m_aborted) { - if (!d->m_progressiveOutput) { - emit output(stdOut); - if (!stdErr.isEmpty()) - emit errorText(stdErr); - } - - emit finished(d->m_lastExecSuccess, d->m_lastExecExitCode, cookie()); - if (d->m_lastExecSuccess) - emit success(cookie()); - future.setProgressValue(future.progressMaximum()); - } - - if (d->m_progressParser) - d->m_progressParser->setFuture(0); - // As it is used asynchronously, we need to delete ourselves - this->deleteLater(); -} - -class OutputProxy : public QObject -{ - Q_OBJECT - - friend class Command; - -public: - OutputProxy() - { - // Users of this class can either be in the GUI thread or in other threads. - // Use Qt::AutoConnection to always append in the GUI thread (directly or queued) - VcsOutputWindow *outputWindow = VcsOutputWindow::instance(); - connect(this, SIGNAL(append(QString)), outputWindow, SLOT(append(QString))); - connect(this, SIGNAL(appendSilently(QString)), outputWindow, SLOT(appendSilently(QString))); - connect(this, SIGNAL(appendError(QString)), outputWindow, SLOT(appendError(QString))); - connect(this, SIGNAL(appendCommand(QString,Utils::FileName,QStringList)), - outputWindow, SLOT(appendCommand(QString,Utils::FileName,QStringList))); - connect(this, SIGNAL(appendMessage(QString)), outputWindow, SLOT(appendMessage(QString))); - } - -signals: - void append(const QString &text); - void appendSilently(const QString &text); - void appendError(const QString &text); - void appendCommand(const QString &workingDirectory, - const Utils::FileName &binary, - const QStringList &args); - void appendMessage(const QString &text); -}; - -Utils::SynchronousProcessResponse Command::runVcs(const QStringList &arguments, int timeoutMS, - Utils::ExitCodeInterpreter *interpreter) -{ - Utils::SynchronousProcessResponse response; - OutputProxy outputProxy; - - if (d->m_binaryPath.isEmpty()) { - response.result = Utils::SynchronousProcessResponse::StartFailed; - return response; - } - - if (!(d->m_flags & VcsBasePlugin::SuppressCommandLogging)) - emit outputProxy.appendCommand(d->m_workingDirectory, d->m_binaryPath, arguments); - - const bool sshPromptConfigured = !d->m_sshPasswordPrompt.isEmpty(); - if (debugExecution) { - QDebug nsp = qDebug().nospace(); - nsp << "Command::runVcs" << d->m_workingDirectory << d->m_binaryPath << arguments - << timeoutMS; - if (d->m_flags & VcsBasePlugin::ShowStdOutInLogWindow) - nsp << "stdout"; - if (d->m_flags & VcsBasePlugin::SuppressStdErrInLogWindow) - nsp << "suppress_stderr"; - if (d->m_flags & VcsBasePlugin::SuppressFailMessageInLogWindow) - nsp << "suppress_fail_msg"; - if (d->m_flags & VcsBasePlugin::MergeOutputChannels) - nsp << "merge_channels"; - if (d->m_flags & VcsBasePlugin::SshPasswordPrompt) - nsp << "ssh (" << sshPromptConfigured << ')'; - if (d->m_flags & VcsBasePlugin::SuppressCommandLogging) - nsp << "suppress_log"; - if (d->m_flags & VcsBasePlugin::ForceCLocale) - nsp << "c_locale"; - if (d->m_flags & VcsBasePlugin::FullySynchronously) - nsp << "fully_synchronously"; - if (d->m_flags & VcsBasePlugin::ExpectRepoChanges) - nsp << "expect_repo_changes"; - if (d->m_codec) - nsp << " Codec: " << d->m_codec->name(); - } - - // TODO tell the document manager about expected repository changes - // if (d->m_flags & ExpectRepoChanges) - // Core::DocumentManager::expectDirectoryChange(d->m_workingDirectory); - if (d->m_flags & VcsBasePlugin::FullySynchronously) { - response = runSynchronous(arguments, timeoutMS, interpreter); - } else { - Utils::SynchronousProcess process; - process.setExitCodeInterpreter(interpreter); - connect(this, SIGNAL(terminate()), &process, SLOT(terminate())); - if (!d->m_workingDirectory.isEmpty()) - process.setWorkingDirectory(d->m_workingDirectory); - - QProcessEnvironment env = d->m_environment; - VcsBasePlugin::setProcessEnvironment(&env, - (d->m_flags & VcsBasePlugin::ForceCLocale), - d->m_sshPasswordPrompt); - process.setProcessEnvironment(env); - process.setTimeout(timeoutMS); - if (d->m_codec) - process.setCodec(d->m_codec); - - // Suppress terminal on UNIX for ssh prompts if it is configured. - if (sshPromptConfigured && (d->m_flags & VcsBasePlugin::SshPasswordPrompt)) - process.setFlags(Utils::SynchronousProcess::UnixTerminalDisabled); - - // connect stderr to the output window if desired - if (d->m_flags & VcsBasePlugin::MergeOutputChannels) { - process.setProcessChannelMode(QProcess::MergedChannels); - } else if (d->m_progressiveOutput - || !(d->m_flags & VcsBasePlugin::SuppressStdErrInLogWindow)) { - process.setStdErrBufferedSignalsEnabled(true); - connect(&process, SIGNAL(stdErrBuffered(QString,bool)), - this, SLOT(bufferedError(QString))); - } - - // connect stdout to the output window if desired - if (d->m_progressParser || d->m_progressiveOutput - || (d->m_flags & VcsBasePlugin::ShowStdOutInLogWindow)) { - process.setStdOutBufferedSignalsEnabled(true); - connect(&process, SIGNAL(stdOutBuffered(QString,bool)), this, SLOT(bufferedOutput(QString))); - } - - process.setTimeOutMessageBoxEnabled(true); - - // Run! - response = process.run(d->m_binaryPath.toString(), arguments); - } - - if (!d->m_aborted) { - // Success/Fail message in appropriate window? - if (response.result == Utils::SynchronousProcessResponse::Finished) { - if (d->m_flags & VcsBasePlugin::ShowSuccessMessage) { - emit outputProxy.appendMessage(response.exitMessage(d->m_binaryPath.toUserOutput(), - timeoutMS)); - } - } else if (!(d->m_flags & VcsBasePlugin::SuppressFailMessageInLogWindow)) { - emit outputProxy.appendError(response.exitMessage(d->m_binaryPath.toUserOutput(), - timeoutMS)); - } - } - emitRepositoryChanged(); - - return response; -} - -Utils::SynchronousProcessResponse Command::runSynchronous(const QStringList &arguments, int timeoutMS, - Utils::ExitCodeInterpreter *interpreter) -{ - Utils::SynchronousProcessResponse response; - - // Set up process - unsigned processFlags = 0; - if (!d->m_sshPasswordPrompt.isEmpty() && (d->m_flags & VcsBasePlugin::SshPasswordPrompt)) - processFlags |= Utils::SynchronousProcess::UnixTerminalDisabled; - QSharedPointer process = Utils::SynchronousProcess::createProcess(processFlags); - if (!d->m_workingDirectory.isEmpty()) - process->setWorkingDirectory(d->m_workingDirectory); - QProcessEnvironment env = d->m_environment; - VcsBasePlugin::setProcessEnvironment(&env, - (d->m_flags & VcsBasePlugin::ForceCLocale), - d->m_sshPasswordPrompt); - process->setProcessEnvironment(env); - if (d->m_flags & VcsBasePlugin::MergeOutputChannels) - process->setProcessChannelMode(QProcess::MergedChannels); - - // Start - process->start(d->m_binaryPath.toString(), arguments, QIODevice::ReadOnly); - process->closeWriteChannel(); - if (!process->waitForStarted()) { - response.result = Utils::SynchronousProcessResponse::StartFailed; - return response; - } - - // process output - QByteArray stdOut; - QByteArray stdErr; - const bool timedOut = - !Utils::SynchronousProcess::readDataFromProcess(*process.data(), timeoutMS, - &stdOut, &stdErr, true); - - if (!d->m_aborted) { - OutputProxy outputProxy; - if (!stdErr.isEmpty()) { - response.stdErr = Utils::SynchronousProcess::normalizeNewlines( - d->m_codec ? d->m_codec->toUnicode(stdErr) : QString::fromLocal8Bit(stdErr)); - if (!(d->m_flags & VcsBasePlugin::SuppressStdErrInLogWindow)) - emit outputProxy.append(response.stdErr); - } - - if (!stdOut.isEmpty()) { - response.stdOut = Utils::SynchronousProcess::normalizeNewlines( - d->m_codec ? d->m_codec->toUnicode(stdOut) : QString::fromLocal8Bit(stdOut)); - if (d->m_flags & VcsBasePlugin::ShowStdOutInLogWindow) { - if (d->m_flags & VcsBasePlugin::SilentOutput) - emit outputProxy.appendSilently(response.stdOut); - else - emit outputProxy.append(response.stdOut); - } - } - } - - Utils::ExitCodeInterpreter defaultInterpreter(this); - Utils::ExitCodeInterpreter *currentInterpreter = interpreter ? interpreter : &defaultInterpreter; - // Result - if (timedOut) - response.result = Utils::SynchronousProcessResponse::Hang; - else if (process->exitStatus() != QProcess::NormalExit) - response.result = Utils::SynchronousProcessResponse::TerminatedAbnormally; - else - response.result = currentInterpreter->interpretExitCode(process->exitCode()); - return response; -} - -void Command::emitRepositoryChanged() -{ - if (d->m_preventRepositoryChanged || !(d->m_flags & VcsBasePlugin::ExpectRepoChanges)) - return; - // TODO tell the document manager that the directory now received all expected changes - // Core::DocumentManager::unexpectDirectoryChange(d->m_workingDirectory); - Core::VcsManager::emitRepositoryChanged(d->m_workingDirectory); -} - -bool Command::runFullySynchronous(const QStringList &arguments, int timeoutMS, - QByteArray *outputData, QByteArray *errorData) -{ - if (d->m_binaryPath.isEmpty()) - return false; - - OutputProxy outputProxy; - if (!(d->m_flags & VcsBasePlugin::SuppressCommandLogging)) - emit outputProxy.appendCommand(d->m_workingDirectory, d->m_binaryPath, arguments); - - // TODO tell the document manager about expected repository changes - // if (d->m_flags & ExpectRepoChanges) - // Core::DocumentManager::expectDirectoryChange(workingDirectory); - QProcess process; - process.setWorkingDirectory(d->m_workingDirectory); - process.setProcessEnvironment(d->m_environment); - - process.start(d->m_binaryPath.toString(), arguments); - process.closeWriteChannel(); - if (!process.waitForStarted()) { - if (errorData) { - const QString msg = QString::fromLatin1("Unable to execute \"%1\": %2:") - .arg(d->m_binaryPath.toUserOutput(), process.errorString()); - *errorData = msg.toLocal8Bit(); - } - return false; - } - - if (!Utils::SynchronousProcess::readDataFromProcess(process, timeoutMS, outputData, errorData, true)) { - if (errorData) - errorData->append(tr("Error: Executable timed out after %1s.").arg(timeoutMS / 1000).toLocal8Bit()); - Utils::SynchronousProcess::stopProcess(process); - return false; - } - - emitRepositoryChanged(); - return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0; -} - -void Command::bufferedOutput(const QString &text) -{ - if (d->m_progressParser) - d->m_progressParser->parseProgress(text); - if (d->m_flags & VcsBasePlugin::ShowStdOutInLogWindow) - VcsOutputWindow::append(text); - if (d->m_progressiveOutput) { - emit output(text); - d->m_hadOutput = true; - } -} - -void Command::bufferedError(const QString &text) -{ - if (!(d->m_flags & VcsBasePlugin::SuppressStdErrInLogWindow)) - VcsOutputWindow::appendError(text); - if (d->m_progressiveOutput) - emit errorText(text); -} - -void Command::coreAboutToClose() -{ - d->m_preventRepositoryChanged = true; - abort(); -} - -const QVariant &Command::cookie() const -{ - return d->m_cookie; -} - -void Command::setCookie(const QVariant &cookie) -{ - d->m_cookie = cookie; -} - -QTextCodec *Command::codec() const -{ - return d->m_codec; -} - -void Command::setCodec(QTextCodec *codec) -{ - d->m_codec = codec; -} - -//! Use \a parser to parse progress data from stdout. Command takes ownership of \a parser -void Command::setProgressParser(ProgressParser *parser) -{ - QTC_ASSERT(!d->m_progressParser, return); - d->m_progressParser = parser; -} - -void Command::setProgressiveOutput(bool progressive) -{ - d->m_progressiveOutput = progressive; -} - -ProgressParser::ProgressParser() : - m_future(0), - m_futureMutex(new QMutex) -{ -} - -ProgressParser::~ProgressParser() -{ - delete m_futureMutex; -} - -void ProgressParser::setProgressAndMaximum(int value, int maximum) -{ - QMutexLocker lock(m_futureMutex); - if (!m_future) - return; - m_future->setProgressRange(0, maximum); - m_future->setProgressValue(value); -} - -void ProgressParser::setFuture(QFutureInterface *future) -{ - QMutexLocker lock(m_futureMutex); - m_future = future; -} - -} // namespace VcsBase - -#include "command.moc" diff --git a/src/plugins/vcsbase/command.h b/src/plugins/vcsbase/command.h deleted file mode 100644 index cde50a7b62..0000000000 --- a/src/plugins/vcsbase/command.h +++ /dev/null @@ -1,142 +0,0 @@ -/************************************************************************** -** -** Copyright (c) 2014 Brian McGillion and Hugues Delorme -** Contact: http://www.qt-project.org/legal -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef VCSBASE_COMMAND_H -#define VCSBASE_COMMAND_H - -#include "vcsbase_global.h" - -#include -#include - -#include - -QT_BEGIN_NAMESPACE -class QMutex; -class QStringList; -class QVariant; -class QProcessEnvironment; -template -class QFutureInterface; -QT_END_NAMESPACE - -namespace VcsBase { - -namespace Internal { class CommandPrivate; } - -class VCSBASE_EXPORT ProgressParser -{ -public: - ProgressParser(); - virtual ~ProgressParser(); - -protected: - virtual void parseProgress(const QString &text) = 0; - void setProgressAndMaximum(int value, int maximum); - -private: - void setFuture(QFutureInterface *future); - - QFutureInterface *m_future; - QMutex *m_futureMutex; - friend class Command; -}; - -class VCSBASE_EXPORT Command : public QObject -{ - Q_OBJECT - -public: - Command(const Utils::FileName &binary, - const QString &workingDirectory, - const QProcessEnvironment &environment); - ~Command(); - - void addJob(const QStringList &arguments, Utils::ExitCodeInterpreter *interpreter = 0); - void addJob(const QStringList &arguments, int timeout, Utils::ExitCodeInterpreter *interpreter = 0); - void execute(); - void abort(); - bool lastExecutionSuccess() const; - int lastExecutionExitCode() const; - - const Utils::FileName &binaryPath() const; - const QString &workingDirectory() const; - const QProcessEnvironment &processEnvironment() const; - - int defaultTimeout() const; - void setDefaultTimeout(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); - void setProgressiveOutput(bool progressive); - - Utils::SynchronousProcessResponse runVcs(const QStringList &arguments, int timeoutMS, - Utils::ExitCodeInterpreter *interpreter = 0); - // Make sure to not pass through the event loop at all: - bool runFullySynchronous(const QStringList &arguments, int timeoutMS, - QByteArray *outputData, QByteArray *errorData); - -private: - void run(QFutureInterface &future); - Utils::SynchronousProcessResponse runSynchronous(const QStringList &arguments, int timeoutMS, - Utils::ExitCodeInterpreter *interpreter = 0); - void emitRepositoryChanged(); - -public slots: - void cancel(); - -signals: - void output(const QString &); - void errorText(const QString &); - void finished(bool ok, int exitCode, const QVariant &cookie); - void success(const QVariant &cookie); - -private slots: - void bufferedOutput(const QString &text); - void bufferedError(const QString &text); - void coreAboutToClose(); - -signals: - void terminate(); // Internal - -private: - class Internal::CommandPrivate *const d; -}; - -} // namespace VcsBase - -#endif // VCSBASE_COMMAND_H diff --git a/src/plugins/vcsbase/vcsbase.pro b/src/plugins/vcsbase/vcsbase.pro index c431e39999..b90ae857c7 100644 --- a/src/plugins/vcsbase/vcsbase.pro +++ b/src/plugins/vcsbase/vcsbase.pro @@ -24,7 +24,7 @@ HEADERS += vcsbase_global.h \ vcsoutputwindow.h \ cleandialog.h \ vcsbaseoptionspage.h \ - command.h \ + vcscommand.h \ vcsbaseclient.h \ vcsbaseclientsettings.h \ vcsbaseeditorparameterwidget.h \ @@ -53,7 +53,7 @@ SOURCES += vcsplugin.cpp \ vcsoutputwindow.cpp \ cleandialog.cpp \ vcsbaseoptionspage.cpp \ - command.cpp \ + vcscommand.cpp \ vcsbaseclient.cpp \ vcsbaseclientsettings.cpp \ vcsbaseeditorparameterwidget.cpp \ diff --git a/src/plugins/vcsbase/vcsbase.qbs b/src/plugins/vcsbase/vcsbase.qbs index 117a8491a2..61de33b1d4 100644 --- a/src/plugins/vcsbase/vcsbase.qbs +++ b/src/plugins/vcsbase/vcsbase.qbs @@ -34,8 +34,6 @@ QtcPlugin { "cleandialog.cpp", "cleandialog.h", "cleandialog.ui", - "command.cpp", - "command.h", "commonsettingspage.cpp", "commonsettingspage.h", "commonsettingspage.ui", @@ -74,6 +72,8 @@ QtcPlugin { "vcsbaseplugin.h", "vcsbasesubmiteditor.cpp", "vcsbasesubmiteditor.h", + "vcscommand.cpp", + "vcscommand.h", "vcsconfigurationpage.cpp", "vcsconfigurationpage.h", "vcsoutputwindow.cpp", diff --git a/src/plugins/vcsbase/vcsbaseclient.cpp b/src/plugins/vcsbase/vcsbaseclient.cpp index 5bf6d3fd07..a56e6842c4 100644 --- a/src/plugins/vcsbase/vcsbaseclient.cpp +++ b/src/plugins/vcsbase/vcsbaseclient.cpp @@ -28,7 +28,7 @@ ****************************************************************************/ #include "vcsbaseclient.h" -#include "command.h" +#include "vcscommand.h" #include "vcsbaseclientsettings.h" #include "vcsbaseeditorparameterwidget.h" @@ -85,7 +85,7 @@ public: QString change, int lineNumber); void saveSettings(); - void bindCommandToEditor(Command *cmd, VcsBaseEditorWidget *editor); + void bindCommandToEditor(VcsCommand *cmd, VcsBaseEditorWidget *editor); void commandFinishedGotoLine(QWidget *editorObject); VcsBaseClientSettings *m_clientSettings; @@ -133,7 +133,7 @@ void VcsBaseClientPrivate::saveSettings() m_clientSettings->writeSettings(Core::ICore::settings()); } -void VcsBaseClientPrivate::bindCommandToEditor(Command *cmd, VcsBaseEditorWidget *editor) +void VcsBaseClientPrivate::bindCommandToEditor(VcsCommand *cmd, VcsBaseEditorWidget *editor) { editor->setCommand(cmd); QObject::connect(cmd, SIGNAL(finished(bool,int,QVariant)), m_cmdFinishedMapper, SLOT(map())); @@ -142,8 +142,8 @@ void VcsBaseClientPrivate::bindCommandToEditor(Command *cmd, VcsBaseEditorWidget void VcsBaseClientPrivate::commandFinishedGotoLine(QWidget *editorObject) { - VcsBase::VcsBaseEditorWidget *editor = qobject_cast(editorObject); - Command *cmd = qobject_cast(m_cmdFinishedMapper->mapping(editor)); + VcsBaseEditorWidget *editor = qobject_cast(editorObject); + VcsCommand *cmd = qobject_cast(m_cmdFinishedMapper->mapping(editor)); if (editor && cmd) { if (!cmd->lastExecutionSuccess()) { editor->reportCommandFinished(false, cmd->lastExecutionExitCode(), cmd->cookie()); @@ -240,9 +240,9 @@ bool VcsBaseClient::synchronousPull(const QString &workingDir, args << vcsCommandString(PullCommand) << extraOptions << srcLocation; // Disable UNIX terminals to suppress SSH prompting const unsigned flags = - VcsBase::VcsBasePlugin::SshPasswordPrompt - | VcsBase::VcsBasePlugin::ShowStdOutInLogWindow - | VcsBase::VcsBasePlugin::ShowSuccessMessage; + VcsBasePlugin::SshPasswordPrompt + | VcsBasePlugin::ShowStdOutInLogWindow + | VcsBasePlugin::ShowSuccessMessage; const Utils::SynchronousProcessResponse resp = vcsSynchronousExec(workingDir, args, flags); const bool ok = resp.result == Utils::SynchronousProcessResponse::Finished; if (ok) @@ -258,9 +258,9 @@ bool VcsBaseClient::synchronousPush(const QString &workingDir, args << vcsCommandString(PushCommand) << extraOptions << dstLocation; // Disable UNIX terminals to suppress SSH prompting const unsigned flags = - VcsBase::VcsBasePlugin::SshPasswordPrompt - | VcsBase::VcsBasePlugin::ShowStdOutInLogWindow - | VcsBase::VcsBasePlugin::ShowSuccessMessage; + VcsBasePlugin::SshPasswordPrompt + | VcsBasePlugin::ShowStdOutInLogWindow + | VcsBasePlugin::ShowSuccessMessage; const Utils::SynchronousProcessResponse resp = vcsSynchronousExec(workingDir, args, flags); return resp.result == Utils::SynchronousProcessResponse::Finished; } @@ -311,8 +311,8 @@ Utils::SynchronousProcessResponse VcsBaseClient::vcsSynchronousExec( { const Utils::FileName binary = settings()->binaryPath(); const int timeoutSec = settings()->intValue(VcsBaseClientSettings::timeoutKey); - return VcsBase::VcsBasePlugin::runVcs(workingDirectory, binary, args, - timeoutSec * 1000, flags, outputCodec); + return VcsBasePlugin::runVcs(workingDirectory, binary, args, + timeoutSec * 1000, flags, outputCodec); } void VcsBaseClient::annotate(const QString &workingDir, const QString &file, @@ -328,10 +328,10 @@ void VcsBaseClient::annotate(const QString &workingDir, const QString &file, const QString title = vcsEditorTitle(vcsCmdString, id); const QString source = VcsBaseEditor::getSource(workingDir, file); - VcsBase::VcsBaseEditorWidget *editor = createVcsEditor(kind, title, source, true, - vcsCmdString.toLatin1().constData(), id); + VcsBaseEditorWidget *editor = createVcsEditor(kind, title, source, true, + vcsCmdString.toLatin1().constData(), id); - Command *cmd = createCommand(workingDir, editor); + VcsCommand *cmd = createCommand(workingDir, editor); cmd->setCookie(lineNumber); enqueueJob(cmd, args); } @@ -344,14 +344,14 @@ void VcsBaseClient::diff(const QString &workingDir, const QStringList &files, const QString id = VcsBaseEditor::getTitleId(workingDir, files); const QString title = vcsEditorTitle(vcsCmdString, id); const QString source = VcsBaseEditor::getSource(workingDir, files); - VcsBase::VcsBaseEditorWidget *editor = createVcsEditor(kind, title, source, true, - vcsCmdString.toLatin1().constData(), id); + VcsBaseEditorWidget *editor = createVcsEditor(kind, title, source, true, + vcsCmdString.toLatin1().constData(), id); editor->setWorkingDirectory(workingDir); VcsBaseEditorParameterWidget *paramWidget = editor->configurationWidget(); if (!paramWidget && (paramWidget = createDiffEditor(workingDir, files, extraOptions))) { // editor has been just created, createVcsEditor() didn't set a configuration widget yet - connect(editor, SIGNAL(diffChunkReverted(VcsBase::DiffChunk)), paramWidget, SLOT(executeCommand())); + connect(editor, SIGNAL(diffChunkReverted(DiffChunk)), paramWidget, SLOT(executeCommand())); editor->setConfigurationWidget(paramWidget); } @@ -359,7 +359,7 @@ void VcsBaseClient::diff(const QString &workingDir, const QStringList &files, const QStringList paramArgs = paramWidget != 0 ? paramWidget->arguments() : QStringList(); args << vcsCmdString << extraOptions << paramArgs << files; QTextCodec *codec = source.isEmpty() ? static_cast(0) : VcsBaseEditor::getCodec(source); - Command *command = createCommand(workingDir, editor); + VcsCommand *command = createCommand(workingDir, editor); command->setCodec(codec); enqueueJob(command, args, exitCodeInterpreter(DiffCommand, command)); } @@ -373,8 +373,8 @@ void VcsBaseClient::log(const QString &workingDir, const QStringList &files, const QString id = VcsBaseEditor::getTitleId(workingDir, files); const QString title = vcsEditorTitle(vcsCmdString, id); const QString source = VcsBaseEditor::getSource(workingDir, files); - VcsBase::VcsBaseEditorWidget *editor = createVcsEditor(kind, title, source, true, - vcsCmdString.toLatin1().constData(), id); + VcsBaseEditorWidget *editor = createVcsEditor(kind, title, source, true, + vcsCmdString.toLatin1().constData(), id); editor->setFileLogAnnotateEnabled(enableAnnotationContextMenu); VcsBaseEditorParameterWidget *paramWidget = editor->configurationWidget(); @@ -397,7 +397,7 @@ void VcsBaseClient::revertFile(const QString &workingDir, QStringList args(vcsCommandString(RevertCommand)); args << revisionSpec(revision) << extraOptions << file; // Indicate repository change or file list - Command *cmd = createCommand(workingDir); + VcsCommand *cmd = createCommand(workingDir); cmd->setCookie(QStringList(workingDir + QLatin1Char('/') + file)); connect(cmd, SIGNAL(success(QVariant)), this, SIGNAL(changed(QVariant)), Qt::QueuedConnection); enqueueJob(cmd, args); @@ -409,7 +409,7 @@ void VcsBaseClient::revertAll(const QString &workingDir, const QString &revision QStringList args(vcsCommandString(RevertCommand)); args << revisionSpec(revision) << extraOptions; // Indicate repository change or file list - Command *cmd = createCommand(workingDir); + VcsCommand *cmd = createCommand(workingDir); cmd->setCookie(QStringList(workingDir)); connect(cmd, SIGNAL(success(QVariant)), this, SIGNAL(changed(QVariant)), Qt::QueuedConnection); enqueueJob(createCommand(workingDir), args); @@ -421,7 +421,7 @@ void VcsBaseClient::status(const QString &workingDir, const QString &file, QStringList args(vcsCommandString(StatusCommand)); args << extraOptions << file; VcsOutputWindow::setRepository(workingDir); - Command *cmd = createCommand(workingDir, 0, VcsWindowOutputBind); + VcsCommand *cmd = createCommand(workingDir, 0, VcsWindowOutputBind); connect(cmd, SIGNAL(finished(bool,int,QVariant)), VcsOutputWindow::instance(), SLOT(clearRepository()), Qt::QueuedConnection); enqueueJob(cmd, args); @@ -431,12 +431,12 @@ void VcsBaseClient::emitParsedStatus(const QString &repository, const QStringLis { QStringList args(vcsCommandString(StatusCommand)); args << extraOptions; - Command *cmd = createCommand(repository); + VcsCommand *cmd = createCommand(repository); connect(cmd, SIGNAL(output(QString)), this, SLOT(statusParser(QString))); enqueueJob(cmd, args); } -QString VcsBaseClient::vcsCommandString(VcsCommand cmd) const +QString VcsBaseClient::vcsCommandString(VcsCommandTag cmd) const { switch (cmd) { case CreateRepositoryCommand: return QLatin1String("init"); @@ -458,7 +458,7 @@ QString VcsBaseClient::vcsCommandString(VcsCommand cmd) const return QString(); } -Utils::ExitCodeInterpreter *VcsBaseClient::exitCodeInterpreter(VcsCommand cmd, QObject *parent) const +Utils::ExitCodeInterpreter *VcsBaseClient::exitCodeInterpreter(VcsCommandTag cmd, QObject *parent) const { Q_UNUSED(cmd) Q_UNUSED(parent) @@ -481,8 +481,7 @@ void VcsBaseClient::view(const QString &source, const QString &id, const Core::Id kind = vcsEditorKind(DiffCommand); const QString title = vcsEditorTitle(vcsCommandString(LogCommand), id); - VcsBase::VcsBaseEditorWidget *editor = createVcsEditor(kind, title, source, - true, "view", id); + VcsBaseEditorWidget *editor = createVcsEditor(kind, title, source, true, "view", id); const QFileInfo fi(source); const QString workingDirPath = fi.isFile() ? fi.absolutePath() : source; @@ -494,7 +493,7 @@ void VcsBaseClient::update(const QString &repositoryRoot, const QString &revisio { QStringList args(vcsCommandString(UpdateCommand)); args << revisionSpec(revision) << extraOptions; - Command *cmd = createCommand(repositoryRoot); + VcsCommand *cmd = createCommand(repositoryRoot); cmd->setCookie(repositoryRoot); connect(cmd, SIGNAL(success(QVariant)), this, SIGNAL(changed(QVariant)), Qt::QueuedConnection); enqueueJob(cmd, args); @@ -552,12 +551,12 @@ QString VcsBaseClient::vcsEditorTitle(const QString &vcsCmd, const QString &sour QFileInfo(sourceId).fileName(); } -VcsBase::VcsBaseEditorWidget *VcsBaseClient::createVcsEditor(Core::Id kind, QString title, - const QString &source, bool setSourceCodec, - const char *registerDynamicProperty, - const QString &dynamicPropertyValue) const +VcsBaseEditorWidget *VcsBaseClient::createVcsEditor(Core::Id kind, QString title, + const QString &source, bool setSourceCodec, + const char *registerDynamicProperty, + const QString &dynamicPropertyValue) const { - VcsBase::VcsBaseEditorWidget *baseEditor = 0; + VcsBaseEditorWidget *baseEditor = 0; Core::IEditor *outputEditor = locateEditor(registerDynamicProperty, dynamicPropertyValue); const QString progressMsg = tr("Working..."); if (outputEditor) { @@ -585,16 +584,16 @@ VcsBase::VcsBaseEditorWidget *VcsBaseClient::createVcsEditor(Core::Id kind, QStr QProcessEnvironment VcsBaseClient::processEnvironment() const { QProcessEnvironment environment = QProcessEnvironment::systemEnvironment(); - VcsBase::VcsBasePlugin::setProcessEnvironment(&environment, false); + VcsBasePlugin::setProcessEnvironment(&environment, false); return environment; } -Command *VcsBaseClient::createCommand(const QString &workingDirectory, - VcsBase::VcsBaseEditorWidget *editor, - JobOutputBindMode mode) const +VcsCommand *VcsBaseClient::createCommand(const QString &workingDirectory, + VcsBaseEditorWidget *editor, + JobOutputBindMode mode) const { - Command *cmd = new Command(d->m_clientSettings->binaryPath(), workingDirectory, - processEnvironment()); + VcsCommand *cmd = new VcsCommand(d->m_clientSettings->binaryPath(), workingDirectory, + processEnvironment()); cmd->setDefaultTimeout(d->m_clientSettings->intValue(VcsBaseClientSettings::timeoutKey)); if (editor) d->bindCommandToEditor(cmd, editor); @@ -609,7 +608,7 @@ Command *VcsBaseClient::createCommand(const QString &workingDirectory, return cmd; } -void VcsBaseClient::enqueueJob(Command *cmd, const QStringList &args, Utils::ExitCodeInterpreter *interpreter) +void VcsBaseClient::enqueueJob(VcsCommand *cmd, const QStringList &args, Utils::ExitCodeInterpreter *interpreter) { cmd->addJob(args, interpreter); cmd->execute(); diff --git a/src/plugins/vcsbase/vcsbaseclient.h b/src/plugins/vcsbase/vcsbaseclient.h index 0dae176643..11e0b4387b 100644 --- a/src/plugins/vcsbase/vcsbaseclient.h +++ b/src/plugins/vcsbase/vcsbaseclient.h @@ -49,7 +49,7 @@ class ExitCodeInterpreter; namespace VcsBase { -class Command; +class VcsCommand; class VcsBaseEditorWidget; class VcsBaseClientSettings; class VcsJob; @@ -131,7 +131,7 @@ public slots: const QStringList &extraOptions = QStringList()); protected: - enum VcsCommand + enum VcsCommandTag { CreateRepositoryCommand, CloneCommand, @@ -149,9 +149,9 @@ protected: LogCommand, StatusCommand }; - virtual QString vcsCommandString(VcsCommand cmd) const; - virtual Core::Id vcsEditorKind(VcsCommand cmd) const = 0; - virtual Utils::ExitCodeInterpreter *exitCodeInterpreter(VcsCommand cmd, QObject *parent) const; + virtual QString vcsCommandString(VcsCommandTag cmd) const; + virtual Core::Id vcsEditorKind(VcsCommandTag cmd) const = 0; + virtual Utils::ExitCodeInterpreter *exitCodeInterpreter(VcsCommandTag cmd, QObject *parent) const; virtual QStringList revisionSpec(const QString &revision) const = 0; virtual VcsBaseEditorParameterWidget *createDiffEditor(const QString &workingDir, @@ -173,19 +173,20 @@ protected: const QStringList &args, unsigned flags = 0, QTextCodec *outputCodec = 0) const; - VcsBase::VcsBaseEditorWidget *createVcsEditor(Core::Id kind, QString title, - const QString &source, bool setSourceCodec, - const char *registerDynamicProperty, - const QString &dynamicPropertyValue) const; + VcsBaseEditorWidget *createVcsEditor(Core::Id kind, QString title, + const QString &source, bool setSourceCodec, + const char *registerDynamicProperty, + const QString &dynamicPropertyValue) const; enum JobOutputBindMode { NoOutputBind, VcsWindowOutputBind }; - Command *createCommand(const QString &workingDirectory, - VcsBase::VcsBaseEditorWidget *editor = 0, + + VcsCommand *createCommand(const QString &workingDirectory, + VcsBaseEditorWidget *editor = 0, JobOutputBindMode mode = NoOutputBind) const; - void enqueueJob(Command *cmd, const QStringList &args, Utils::ExitCodeInterpreter *interpreter = 0); + void enqueueJob(VcsCommand *cmd, const QStringList &args, Utils::ExitCodeInterpreter *interpreter = 0); void resetCachedVcsInfo(const QString &workingDir); diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp index fd23f7890d..a274840d32 100644 --- a/src/plugins/vcsbase/vcsbaseeditor.cpp +++ b/src/plugins/vcsbase/vcsbaseeditor.cpp @@ -32,7 +32,7 @@ #include "baseannotationhighlighter.h" #include "vcsbaseplugin.h" #include "vcsbaseeditorparameterwidget.h" -#include "command.h" +#include "vcscommand.h" #include #include @@ -558,7 +558,7 @@ public: VcsBaseEditorParameterWidget *m_configurationWidget; bool m_mouseDragging; QList m_textCursorHandlers; - QPointer m_command; + QPointer m_command; QComboBox *m_entriesComboBox; }; @@ -1329,7 +1329,7 @@ VcsBaseEditorParameterWidget *VcsBaseEditorWidget::configurationWidget() const return d->m_configurationWidget; } -void VcsBaseEditorWidget::setCommand(Command *command) +void VcsBaseEditorWidget::setCommand(VcsCommand *command) { if (d->m_command) d->m_command->abort(); diff --git a/src/plugins/vcsbase/vcsbaseeditor.h b/src/plugins/vcsbase/vcsbaseeditor.h index 8b9b9f8f90..2816ed151d 100644 --- a/src/plugins/vcsbase/vcsbaseeditor.h +++ b/src/plugins/vcsbase/vcsbaseeditor.h @@ -52,7 +52,7 @@ class VcsBaseEditorWidgetPrivate; class BaseAnnotationHighlighter; class VcsBaseEditorWidget; class VcsBaseEditorParameterWidget; -class Command; +class VcsCommand; // Documentation inside enum EditorContentType @@ -207,7 +207,7 @@ public: bool setConfigurationWidget(VcsBaseEditorParameterWidget *w); VcsBaseEditorParameterWidget *configurationWidget() const; - void setCommand(Command *command); + void setCommand(VcsCommand *command); signals: // These signals also exist in the opaque editable (IEditor) that is // handled by the editor manager for convenience. They are emitted diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp index b9c9b8f910..752809f519 100644 --- a/src/plugins/vcsbase/vcsbaseplugin.cpp +++ b/src/plugins/vcsbase/vcsbaseplugin.cpp @@ -33,7 +33,7 @@ #include "commonvcssettings.h" #include "vcsoutputwindow.h" #include "corelistener.h" -#include "command.h" +#include "vcscommand.h" #include #include @@ -799,8 +799,8 @@ SynchronousProcessResponse VcsBasePlugin::runVcs(const QString &workingDir, QTextCodec *outputCodec, const QProcessEnvironment &env) { - Command command(binary, workingDir, - env.isEmpty() ? QProcessEnvironment::systemEnvironment() : env); + VcsCommand command(binary, workingDir, + env.isEmpty() ? QProcessEnvironment::systemEnvironment() : env); command.addFlags(flags); command.setCodec(outputCodec); return command.runVcs(arguments, timeOutMS); diff --git a/src/plugins/vcsbase/vcscommand.cpp b/src/plugins/vcsbase/vcscommand.cpp new file mode 100644 index 0000000000..283e20ba7f --- /dev/null +++ b/src/plugins/vcsbase/vcscommand.cpp @@ -0,0 +1,644 @@ +/************************************************************************** +** +** Copyright (c) 2014 Brian McGillion and Hugues Delorme +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "vcscommand.h" +#include "vcsbaseplugin.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +Q_DECLARE_METATYPE(QVariant) + +enum { debugExecution = 0 }; + +/*! + \fn void VcsBase::ProgressParser::parseProgress(const QString &text) + + Reimplement to parse progress as it appears in the standard output. + If a progress string is detected, call \c setProgressAndMaximum() to update + the progress bar accordingly. + + \sa VcsBase::ProgressParser::setProgressAndMaximum() +*/ + +/*! + \fn void VcsBase::ProgressParser::setProgressAndMaximum(int value, int maximum) + + Sets progress \a value and \a maximum for current command. Called by \c parseProgress() + when a progress string is detected. +*/ + +namespace VcsBase { +namespace Internal { + +class VcsCommandPrivate +{ +public: + struct Job { + explicit Job(const QStringList &a, int t, Utils::ExitCodeInterpreter *interpreter = 0); + + QStringList arguments; + int timeout; + Utils::ExitCodeInterpreter *exitCodeInterpreter; + }; + + VcsCommandPrivate(const Utils::FileName &binary, + const QString &workingDirectory, + const QProcessEnvironment &environment); + ~VcsCommandPrivate(); + + const Utils::FileName m_binaryPath; + const QString m_workingDirectory; + const QProcessEnvironment m_environment; + QVariant m_cookie; + int m_defaultTimeout; + unsigned m_flags; + QTextCodec *m_codec; + const QString m_sshPasswordPrompt; + ProgressParser *m_progressParser; + bool m_progressiveOutput; + bool m_hadOutput; + bool m_preventRepositoryChanged; + bool m_aborted; + QFutureWatcher m_watcher; + + QList m_jobs; + + bool m_lastExecSuccess; + int m_lastExecExitCode; +}; + +VcsCommandPrivate::VcsCommandPrivate(const Utils::FileName &binary, + const QString &workingDirectory, + const QProcessEnvironment &environment) : + m_binaryPath(binary), + m_workingDirectory(workingDirectory), + m_environment(environment), + m_defaultTimeout(10), + m_flags(0), + m_codec(0), + m_sshPasswordPrompt(VcsBasePlugin::sshPrompt()), + m_progressParser(0), + m_progressiveOutput(false), + m_hadOutput(false), + m_preventRepositoryChanged(false), + m_aborted(false), + m_lastExecSuccess(false), + m_lastExecExitCode(-1) +{ +} + +VcsCommandPrivate::~VcsCommandPrivate() +{ + delete m_progressParser; +} + +VcsCommandPrivate::Job::Job(const QStringList &a, int t, Utils::ExitCodeInterpreter *interpreter) : + arguments(a), + timeout(t), + exitCodeInterpreter(interpreter) +{ + // Finished cookie is emitted via queued slot, needs metatype + static const int qvMetaId = qRegisterMetaType(); + Q_UNUSED(qvMetaId) +} + +} // namespace Internal + +VcsCommand::VcsCommand(const Utils::FileName &binary, + const QString &workingDirectory, + const QProcessEnvironment &environment) : + d(new Internal::VcsCommandPrivate(binary, workingDirectory, environment)) +{ + connect(Core::ICore::instance(), SIGNAL(coreAboutToClose()), + this, SLOT(coreAboutToClose())); +} + +VcsCommand::~VcsCommand() +{ + delete d; +} + +const Utils::FileName &VcsCommand::binaryPath() const +{ + return d->m_binaryPath; +} + +const QString &VcsCommand::workingDirectory() const +{ + return d->m_workingDirectory; +} + +const QProcessEnvironment &VcsCommand::processEnvironment() const +{ + return d->m_environment; +} + +int VcsCommand::defaultTimeout() const +{ + return d->m_defaultTimeout; +} + +void VcsCommand::setDefaultTimeout(int timeout) +{ + d->m_defaultTimeout = timeout; +} + +unsigned VcsCommand::flags() const +{ + return d->m_flags; +} + +void VcsCommand::addFlags(unsigned f) +{ + d->m_flags |= f; +} + +void VcsCommand::addJob(const QStringList &arguments, Utils::ExitCodeInterpreter *interpreter) +{ + addJob(arguments, defaultTimeout(), interpreter); +} + +void VcsCommand::addJob(const QStringList &arguments, int timeout, Utils::ExitCodeInterpreter *interpreter) +{ + d->m_jobs.push_back(Internal::VcsCommandPrivate::Job(arguments, timeout, interpreter)); +} + +void VcsCommand::execute() +{ + d->m_lastExecSuccess = false; + d->m_lastExecExitCode = -1; + + if (d->m_jobs.empty()) + return; + + // For some reason QtConcurrent::run() only works on this + QFuture task = QtConcurrent::run(&VcsCommand::run, this); + d->m_watcher.setFuture(task); + connect(&d->m_watcher, SIGNAL(canceled()), this, SLOT(cancel())); + QString binary = d->m_binaryPath.toFileInfo().baseName(); + if (!binary.isEmpty()) + binary = binary.replace(0, 1, binary[0].toUpper()); // Upper the first letter + const QString taskName = binary + QLatin1Char(' ') + d->m_jobs.front().arguments.at(0); + + Core::ProgressManager::addTask(task, taskName, + Core::Id::fromString(binary + QLatin1String(".action"))); +} + +void VcsCommand::abort() +{ + d->m_aborted = true; + d->m_watcher.future().cancel(); +} + +void VcsCommand::cancel() +{ + emit terminate(); +} + +bool VcsCommand::lastExecutionSuccess() const +{ + return d->m_lastExecSuccess; +} + +int VcsCommand::lastExecutionExitCode() const +{ + return d->m_lastExecExitCode; +} + +void VcsCommand::run(QFutureInterface &future) +{ + // Check that the binary path is not empty + if (binaryPath().isEmpty()) { + emit errorText(tr("Unable to start process, binary is empty")); + return; + } + + QString stdOut; + QString stdErr; + + if (d->m_progressParser) + d->m_progressParser->setFuture(&future); + else + future.setProgressRange(0, 1); + const int count = d->m_jobs.size(); + d->m_lastExecExitCode = -1; + d->m_lastExecSuccess = true; + for (int j = 0; j < count; j++) { + const Internal::VcsCommandPrivate::Job &job = d->m_jobs.at(j); + const int timeOutSeconds = job.timeout; + Utils::SynchronousProcessResponse resp = runVcs( + job.arguments, + timeOutSeconds >= 0 ? timeOutSeconds * 1000 : -1, + job.exitCodeInterpreter); + stdOut += resp.stdOut; + stdErr += resp.stdErr; + d->m_lastExecExitCode = resp.exitCode; + d->m_lastExecSuccess = resp.result == Utils::SynchronousProcessResponse::Finished; + if (!d->m_lastExecSuccess) + break; + } + + if (!d->m_aborted) { + if (!d->m_progressiveOutput) { + emit output(stdOut); + if (!stdErr.isEmpty()) + emit errorText(stdErr); + } + + emit finished(d->m_lastExecSuccess, d->m_lastExecExitCode, cookie()); + if (d->m_lastExecSuccess) + emit success(cookie()); + future.setProgressValue(future.progressMaximum()); + } + + if (d->m_progressParser) + d->m_progressParser->setFuture(0); + // As it is used asynchronously, we need to delete ourselves + this->deleteLater(); +} + +class OutputProxy : public QObject +{ + Q_OBJECT + + friend class VcsCommand; + +public: + OutputProxy() + { + // Users of this class can either be in the GUI thread or in other threads. + // Use Qt::AutoConnection to always append in the GUI thread (directly or queued) + VcsOutputWindow *outputWindow = VcsOutputWindow::instance(); + connect(this, SIGNAL(append(QString)), outputWindow, SLOT(append(QString))); + connect(this, SIGNAL(appendSilently(QString)), outputWindow, SLOT(appendSilently(QString))); + connect(this, SIGNAL(appendError(QString)), outputWindow, SLOT(appendError(QString))); + connect(this, SIGNAL(appendCommand(QString,Utils::FileName,QStringList)), + outputWindow, SLOT(appendCommand(QString,Utils::FileName,QStringList))); + connect(this, SIGNAL(appendMessage(QString)), outputWindow, SLOT(appendMessage(QString))); + } + +signals: + void append(const QString &text); + void appendSilently(const QString &text); + void appendError(const QString &text); + void appendCommand(const QString &workingDirectory, + const Utils::FileName &binary, + const QStringList &args); + void appendMessage(const QString &text); +}; + +Utils::SynchronousProcessResponse VcsCommand::runVcs(const QStringList &arguments, int timeoutMS, + Utils::ExitCodeInterpreter *interpreter) +{ + Utils::SynchronousProcessResponse response; + OutputProxy outputProxy; + + if (d->m_binaryPath.isEmpty()) { + response.result = Utils::SynchronousProcessResponse::StartFailed; + return response; + } + + if (!(d->m_flags & VcsBasePlugin::SuppressCommandLogging)) + emit outputProxy.appendCommand(d->m_workingDirectory, d->m_binaryPath, arguments); + + const bool sshPromptConfigured = !d->m_sshPasswordPrompt.isEmpty(); + if (debugExecution) { + QDebug nsp = qDebug().nospace(); + nsp << "Command::runVcs" << d->m_workingDirectory << d->m_binaryPath << arguments + << timeoutMS; + if (d->m_flags & VcsBasePlugin::ShowStdOutInLogWindow) + nsp << "stdout"; + if (d->m_flags & VcsBasePlugin::SuppressStdErrInLogWindow) + nsp << "suppress_stderr"; + if (d->m_flags & VcsBasePlugin::SuppressFailMessageInLogWindow) + nsp << "suppress_fail_msg"; + if (d->m_flags & VcsBasePlugin::MergeOutputChannels) + nsp << "merge_channels"; + if (d->m_flags & VcsBasePlugin::SshPasswordPrompt) + nsp << "ssh (" << sshPromptConfigured << ')'; + if (d->m_flags & VcsBasePlugin::SuppressCommandLogging) + nsp << "suppress_log"; + if (d->m_flags & VcsBasePlugin::ForceCLocale) + nsp << "c_locale"; + if (d->m_flags & VcsBasePlugin::FullySynchronously) + nsp << "fully_synchronously"; + if (d->m_flags & VcsBasePlugin::ExpectRepoChanges) + nsp << "expect_repo_changes"; + if (d->m_codec) + nsp << " Codec: " << d->m_codec->name(); + } + + // TODO tell the document manager about expected repository changes + // if (d->m_flags & ExpectRepoChanges) + // Core::DocumentManager::expectDirectoryChange(d->m_workingDirectory); + if (d->m_flags & VcsBasePlugin::FullySynchronously) { + response = runSynchronous(arguments, timeoutMS, interpreter); + } else { + Utils::SynchronousProcess process; + process.setExitCodeInterpreter(interpreter); + connect(this, SIGNAL(terminate()), &process, SLOT(terminate())); + if (!d->m_workingDirectory.isEmpty()) + process.setWorkingDirectory(d->m_workingDirectory); + + QProcessEnvironment env = d->m_environment; + VcsBasePlugin::setProcessEnvironment(&env, + (d->m_flags & VcsBasePlugin::ForceCLocale), + d->m_sshPasswordPrompt); + process.setProcessEnvironment(env); + process.setTimeout(timeoutMS); + if (d->m_codec) + process.setCodec(d->m_codec); + + // Suppress terminal on UNIX for ssh prompts if it is configured. + if (sshPromptConfigured && (d->m_flags & VcsBasePlugin::SshPasswordPrompt)) + process.setFlags(Utils::SynchronousProcess::UnixTerminalDisabled); + + // connect stderr to the output window if desired + if (d->m_flags & VcsBasePlugin::MergeOutputChannels) { + process.setProcessChannelMode(QProcess::MergedChannels); + } else if (d->m_progressiveOutput + || !(d->m_flags & VcsBasePlugin::SuppressStdErrInLogWindow)) { + process.setStdErrBufferedSignalsEnabled(true); + connect(&process, SIGNAL(stdErrBuffered(QString,bool)), + this, SLOT(bufferedError(QString))); + } + + // connect stdout to the output window if desired + if (d->m_progressParser || d->m_progressiveOutput + || (d->m_flags & VcsBasePlugin::ShowStdOutInLogWindow)) { + process.setStdOutBufferedSignalsEnabled(true); + connect(&process, SIGNAL(stdOutBuffered(QString,bool)), this, SLOT(bufferedOutput(QString))); + } + + process.setTimeOutMessageBoxEnabled(true); + + // Run! + response = process.run(d->m_binaryPath.toString(), arguments); + } + + if (!d->m_aborted) { + // Success/Fail message in appropriate window? + if (response.result == Utils::SynchronousProcessResponse::Finished) { + if (d->m_flags & VcsBasePlugin::ShowSuccessMessage) { + emit outputProxy.appendMessage(response.exitMessage(d->m_binaryPath.toUserOutput(), + timeoutMS)); + } + } else if (!(d->m_flags & VcsBasePlugin::SuppressFailMessageInLogWindow)) { + emit outputProxy.appendError(response.exitMessage(d->m_binaryPath.toUserOutput(), + timeoutMS)); + } + } + emitRepositoryChanged(); + + return response; +} + +Utils::SynchronousProcessResponse VcsCommand::runSynchronous(const QStringList &arguments, + int timeoutMS, + Utils::ExitCodeInterpreter *interpreter) +{ + Utils::SynchronousProcessResponse response; + + // Set up process + unsigned processFlags = 0; + if (!d->m_sshPasswordPrompt.isEmpty() && (d->m_flags & VcsBasePlugin::SshPasswordPrompt)) + processFlags |= Utils::SynchronousProcess::UnixTerminalDisabled; + QSharedPointer process = Utils::SynchronousProcess::createProcess(processFlags); + if (!d->m_workingDirectory.isEmpty()) + process->setWorkingDirectory(d->m_workingDirectory); + QProcessEnvironment env = d->m_environment; + VcsBasePlugin::setProcessEnvironment(&env, + (d->m_flags & VcsBasePlugin::ForceCLocale), + d->m_sshPasswordPrompt); + process->setProcessEnvironment(env); + if (d->m_flags & VcsBasePlugin::MergeOutputChannels) + process->setProcessChannelMode(QProcess::MergedChannels); + + // Start + process->start(d->m_binaryPath.toString(), arguments, QIODevice::ReadOnly); + process->closeWriteChannel(); + if (!process->waitForStarted()) { + response.result = Utils::SynchronousProcessResponse::StartFailed; + return response; + } + + // process output + QByteArray stdOut; + QByteArray stdErr; + const bool timedOut = + !Utils::SynchronousProcess::readDataFromProcess(*process.data(), timeoutMS, + &stdOut, &stdErr, true); + + if (!d->m_aborted) { + OutputProxy outputProxy; + if (!stdErr.isEmpty()) { + response.stdErr = Utils::SynchronousProcess::normalizeNewlines( + d->m_codec ? d->m_codec->toUnicode(stdErr) : QString::fromLocal8Bit(stdErr)); + if (!(d->m_flags & VcsBasePlugin::SuppressStdErrInLogWindow)) + emit outputProxy.append(response.stdErr); + } + + if (!stdOut.isEmpty()) { + response.stdOut = Utils::SynchronousProcess::normalizeNewlines( + d->m_codec ? d->m_codec->toUnicode(stdOut) : QString::fromLocal8Bit(stdOut)); + if (d->m_flags & VcsBasePlugin::ShowStdOutInLogWindow) { + if (d->m_flags & VcsBasePlugin::SilentOutput) + emit outputProxy.appendSilently(response.stdOut); + else + emit outputProxy.append(response.stdOut); + } + } + } + + Utils::ExitCodeInterpreter defaultInterpreter(this); + Utils::ExitCodeInterpreter *currentInterpreter = interpreter ? interpreter : &defaultInterpreter; + // Result + if (timedOut) + response.result = Utils::SynchronousProcessResponse::Hang; + else if (process->exitStatus() != QProcess::NormalExit) + response.result = Utils::SynchronousProcessResponse::TerminatedAbnormally; + else + response.result = currentInterpreter->interpretExitCode(process->exitCode()); + return response; +} + +void VcsCommand::emitRepositoryChanged() +{ + if (d->m_preventRepositoryChanged || !(d->m_flags & VcsBasePlugin::ExpectRepoChanges)) + return; + // TODO tell the document manager that the directory now received all expected changes + // Core::DocumentManager::unexpectDirectoryChange(d->m_workingDirectory); + Core::VcsManager::emitRepositoryChanged(d->m_workingDirectory); +} + +bool VcsCommand::runFullySynchronous(const QStringList &arguments, int timeoutMS, + QByteArray *outputData, QByteArray *errorData) +{ + if (d->m_binaryPath.isEmpty()) + return false; + + OutputProxy outputProxy; + if (!(d->m_flags & VcsBasePlugin::SuppressCommandLogging)) + emit outputProxy.appendCommand(d->m_workingDirectory, d->m_binaryPath, arguments); + + // TODO tell the document manager about expected repository changes + // if (d->m_flags & ExpectRepoChanges) + // Core::DocumentManager::expectDirectoryChange(workingDirectory); + QProcess process; + process.setWorkingDirectory(d->m_workingDirectory); + process.setProcessEnvironment(d->m_environment); + + process.start(d->m_binaryPath.toString(), arguments); + process.closeWriteChannel(); + if (!process.waitForStarted()) { + if (errorData) { + const QString msg = QString::fromLatin1("Unable to execute \"%1\": %2:") + .arg(d->m_binaryPath.toUserOutput(), process.errorString()); + *errorData = msg.toLocal8Bit(); + } + return false; + } + + if (!Utils::SynchronousProcess::readDataFromProcess(process, timeoutMS, outputData, errorData, true)) { + if (errorData) + errorData->append(tr("Error: Executable timed out after %1s.").arg(timeoutMS / 1000).toLocal8Bit()); + Utils::SynchronousProcess::stopProcess(process); + return false; + } + + emitRepositoryChanged(); + return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0; +} + +void VcsCommand::bufferedOutput(const QString &text) +{ + if (d->m_progressParser) + d->m_progressParser->parseProgress(text); + if (d->m_flags & VcsBasePlugin::ShowStdOutInLogWindow) + VcsOutputWindow::append(text); + if (d->m_progressiveOutput) { + emit output(text); + d->m_hadOutput = true; + } +} + +void VcsCommand::bufferedError(const QString &text) +{ + if (!(d->m_flags & VcsBasePlugin::SuppressStdErrInLogWindow)) + VcsOutputWindow::appendError(text); + if (d->m_progressiveOutput) + emit errorText(text); +} + +void VcsCommand::coreAboutToClose() +{ + d->m_preventRepositoryChanged = true; + abort(); +} + +const QVariant &VcsCommand::cookie() const +{ + return d->m_cookie; +} + +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; +} + +//! Use \a parser to parse progress data from stdout. Command takes ownership of \a parser +void VcsCommand::setProgressParser(ProgressParser *parser) +{ + QTC_ASSERT(!d->m_progressParser, return); + d->m_progressParser = parser; +} + +void VcsCommand::setProgressiveOutput(bool progressive) +{ + d->m_progressiveOutput = progressive; +} + +ProgressParser::ProgressParser() : + m_future(0), + m_futureMutex(new QMutex) +{ +} + +ProgressParser::~ProgressParser() +{ + delete m_futureMutex; +} + +void ProgressParser::setProgressAndMaximum(int value, int maximum) +{ + QMutexLocker lock(m_futureMutex); + if (!m_future) + return; + m_future->setProgressRange(0, maximum); + m_future->setProgressValue(value); +} + +void ProgressParser::setFuture(QFutureInterface *future) +{ + QMutexLocker lock(m_futureMutex); + m_future = future; +} + +} // namespace VcsBase + +#include "vcscommand.moc" diff --git a/src/plugins/vcsbase/vcscommand.h b/src/plugins/vcsbase/vcscommand.h new file mode 100644 index 0000000000..bd6fed9aed --- /dev/null +++ b/src/plugins/vcsbase/vcscommand.h @@ -0,0 +1,142 @@ +/************************************************************************** +** +** Copyright (c) 2014 Brian McGillion and Hugues Delorme +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef VCSBASE_COMMAND_H +#define VCSBASE_COMMAND_H + +#include "vcsbase_global.h" + +#include +#include + +#include + +QT_BEGIN_NAMESPACE +class QMutex; +class QStringList; +class QVariant; +class QProcessEnvironment; +template +class QFutureInterface; +QT_END_NAMESPACE + +namespace VcsBase { + +namespace Internal { class VcsCommandPrivate; } + +class VCSBASE_EXPORT ProgressParser +{ +public: + ProgressParser(); + virtual ~ProgressParser(); + +protected: + virtual void parseProgress(const QString &text) = 0; + void setProgressAndMaximum(int value, int maximum); + +private: + void setFuture(QFutureInterface *future); + + QFutureInterface *m_future; + QMutex *m_futureMutex; + friend class VcsCommand; +}; + +class VCSBASE_EXPORT VcsCommand : public QObject +{ + Q_OBJECT + +public: + VcsCommand(const Utils::FileName &binary, + const QString &workingDirectory, + const QProcessEnvironment &environment); + ~VcsCommand(); + + void addJob(const QStringList &arguments, Utils::ExitCodeInterpreter *interpreter = 0); + void addJob(const QStringList &arguments, int timeout, Utils::ExitCodeInterpreter *interpreter = 0); + void execute(); + void abort(); + bool lastExecutionSuccess() const; + int lastExecutionExitCode() const; + + const Utils::FileName &binaryPath() const; + const QString &workingDirectory() const; + const QProcessEnvironment &processEnvironment() const; + + int defaultTimeout() const; + void setDefaultTimeout(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); + void setProgressiveOutput(bool progressive); + + Utils::SynchronousProcessResponse runVcs(const QStringList &arguments, int timeoutMS, + Utils::ExitCodeInterpreter *interpreter = 0); + // Make sure to not pass through the event loop at all: + bool runFullySynchronous(const QStringList &arguments, int timeoutMS, + QByteArray *outputData, QByteArray *errorData); + +private: + void run(QFutureInterface &future); + Utils::SynchronousProcessResponse runSynchronous(const QStringList &arguments, int timeoutMS, + Utils::ExitCodeInterpreter *interpreter = 0); + void emitRepositoryChanged(); + +public slots: + void cancel(); + +signals: + void output(const QString &); + void errorText(const QString &); + void finished(bool ok, int exitCode, const QVariant &cookie); + void success(const QVariant &cookie); + +private slots: + void bufferedOutput(const QString &text); + void bufferedError(const QString &text); + void coreAboutToClose(); + +signals: + void terminate(); // Internal + +private: + class Internal::VcsCommandPrivate *const d; +}; + +} // namespace VcsBase + +#endif // VCSBASE_COMMAND_H -- cgit v1.2.1