Commit ddf01f35 authored by Tobias Hunger's avatar Tobias Hunger
Browse files

Git: Remove GitCommand

Use VCSBase::Command instead.

Change-Id: I819e61c2fdf705717709f49ea42ad822d25300fb
Reviewed-on: http://codereview.qt-project.org/6079

Reviewed-by: default avatarTobias Hunger <tobias.hunger@nokia.com>
parent 6a72edb2
......@@ -20,7 +20,6 @@ HEADERS += gitplugin.h \
gitsettings.h \
branchdialog.h \
branchmodel.h \
gitcommand.h \
clonewizard.h \
clonewizardpage.h \
stashdialog.h \
......@@ -42,7 +41,6 @@ SOURCES += gitplugin.cpp \
gitsettings.cpp \
branchdialog.cpp \
branchmodel.cpp \
gitcommand.cpp \
clonewizard.cpp \
clonewizardpage.cpp \
stashdialog.cpp \
......
......@@ -31,7 +31,6 @@
**************************************************************************/
#include "gitclient.h"
#include "gitcommand.h"
#include "gitutils.h"
#include "commitdata.h"
......@@ -57,6 +56,7 @@
#include <utils/synchronousprocess.h>
#include <utils/environment.h>
#include <utils/fileutils.h>
#include <vcsbase/command.h>
#include <vcsbase/vcsbaseeditor.h>
#include <vcsbase/vcsbaseeditorparameterwidget.h>
#include <vcsbase/vcsbaseoutputwindow.h>
......@@ -406,7 +406,7 @@ void GitClient::diff(const QString &workingDirectory,
// Create a batch of 2 commands to be run after each other in case
// we have a mixture of staged/unstaged files as is the case
// when using the submit dialog.
GitCommand *command = createCommand(workingDirectory, editor);
VCSBase::Command *command = createCommand(workingDirectory, editor);
// Directory diff?
QStringList cmdArgs;
......@@ -500,7 +500,7 @@ void GitClient::status(const QString &workingDirectory)
statusArgs << QLatin1String("-u");
VCSBase::VCSBaseOutputWindow *outwin = outputWindow();
outwin->setRepository(workingDirectory);
GitCommand *command = executeGit(workingDirectory, statusArgs, 0, true);
VCSBase::Command *command = executeGit(workingDirectory, statusArgs, 0, true);
connect(command, SIGNAL(finished(bool,int,QVariant)), outwin, SLOT(clearRepository()),
Qt::QueuedConnection);
}
......@@ -643,14 +643,14 @@ void GitClient::blame(const QString &workingDirectory,
arguments << QLatin1String("--") << fileName;
if (!revision.isEmpty())
arguments << revision;
executeGit(workingDirectory, arguments, editor, false, GitCommand::NoReport, lineNumber);
executeGit(workingDirectory, arguments, editor, false, VCSBase::Command::NoReport, lineNumber);
}
void GitClient::checkoutBranch(const QString &workingDirectory, const QString &branch)
{
QStringList arguments(QLatin1String("checkout"));
arguments << branch;
GitCommand *cmd = executeGit(workingDirectory, arguments, 0, true);
VCSBase::Command *cmd = executeGit(workingDirectory, arguments, 0, true);
connectRepositoryChanged(workingDirectory, cmd);
}
......@@ -700,7 +700,7 @@ void GitClient::hardReset(const QString &workingDirectory, const QString &commit
if (!commit.isEmpty())
arguments << commit;
GitCommand *cmd = executeGit(workingDirectory, arguments, 0, true);
VCSBase::Command *cmd = executeGit(workingDirectory, arguments, 0, true);
connectRepositoryChanged(workingDirectory, cmd);
}
......@@ -1253,12 +1253,13 @@ bool GitClient::synchronousApplyPatch(const QString &workingDirectory,
}
// Factory function to create an asynchronous command
GitCommand *GitClient::createCommand(const QString &workingDirectory,
VCSBase::VCSBaseEditorWidget* editor,
bool useOutputToWindow,
int editorLineNumber)
VCSBase::Command *GitClient::createCommand(const QString &workingDirectory,
VCSBase::VCSBaseEditorWidget* editor,
bool useOutputToWindow,
int editorLineNumber)
{
GitCommand *command = new GitCommand(gitBinaryPath(), workingDirectory, processEnvironment(), QVariant(editorLineNumber));
VCSBase::Command *command = new VCSBase::Command(gitBinaryPath(), workingDirectory, processEnvironment());
command->setCookie(QVariant(editorLineNumber));
if (editor)
connect(command, SIGNAL(finished(bool,int,QVariant)), editor, SLOT(commandFinishedGotoLine(bool,int,QVariant)));
if (useOutputToWindow) {
......@@ -1277,16 +1278,16 @@ GitCommand *GitClient::createCommand(const QString &workingDirectory,
}
// Execute a single command
GitCommand *GitClient::executeGit(const QString &workingDirectory,
const QStringList &arguments,
VCSBase::VCSBaseEditorWidget* editor,
bool useOutputToWindow,
GitCommand::TerminationReportMode tm,
int editorLineNumber,
bool unixTerminalDisabled)
VCSBase::Command *GitClient::executeGit(const QString &workingDirectory,
const QStringList &arguments,
VCSBase::VCSBaseEditorWidget* editor,
bool useOutputToWindow,
VCSBase::Command::TerminationReportMode tm,
int editorLineNumber,
bool unixTerminalDisabled)
{
outputWindow()->appendCommand(workingDirectory, settings()->stringValue(GitSettings::binaryPathKey), arguments);
GitCommand *command = createCommand(workingDirectory, editor, useOutputToWindow, editorLineNumber);
VCSBase::Command *command = createCommand(workingDirectory, editor, useOutputToWindow, editorLineNumber);
command->addJob(arguments, settings()->intValue(GitSettings::timeoutKey));
command->setTerminationReportMode(tm);
command->setUnixTerminalDisabled(unixTerminalDisabled);
......@@ -1415,7 +1416,7 @@ GitClient::StatusResult GitClient::gitStatus(const QString &workingDirectory,
if (untracked)
statusArgs << QLatin1String("-u");
const bool statusRc = fullySynchronousGit(workingDirectory, statusArgs, &outputText, &errorText);
GitCommand::removeColorCodes(&outputText);
VCSBase::Command::removeColorCodes(&outputText);
if (output)
*output = commandOutputFromLocal8Bit(outputText);
const bool branchKnown = outputText.contains(kBranchIndicatorC);
......@@ -1941,7 +1942,7 @@ void GitClient::stashPop(const QString &workingDirectory)
{
QStringList arguments(QLatin1String("stash"));
arguments << QLatin1String("pop");
GitCommand *cmd = executeGit(workingDirectory, arguments, 0, true);
VCSBase::Command *cmd = executeGit(workingDirectory, arguments, 0, true);
connectRepositoryChanged(workingDirectory, cmd);
}
......@@ -2140,7 +2141,7 @@ GitSettings *GitClient::settings() const
return m_settings;
}
void GitClient::connectRepositoryChanged(const QString & repository, GitCommand *cmd)
void GitClient::connectRepositoryChanged(const QString & repository, VCSBase::Command *cmd)
{
// Bind command success termination with repository to changed signal
if (!m_repositoryChangedSignalMapper) {
......
......@@ -34,9 +34,9 @@
#define GITCLIENT_H
#include "gitsettings.h"
#include "gitcommand.h"
#include <coreplugin/editormanager/ieditor.h>
#include <vcsbase/command.h>
#include <QtCore/QObject>
#include <QtCore/QString>
......@@ -68,7 +68,6 @@ namespace Internal {
class GitPlugin;
class GitOutputWindow;
class GitCommand;
class CommitData;
struct GitSubmitEditorPanelData;
class Stash;
......@@ -245,16 +244,16 @@ private:
const QString &dynamicPropertyValue,
QWidget *configWidget) const;
GitCommand *createCommand(const QString &workingDirectory,
VCSBase::Command *createCommand(const QString &workingDirectory,
VCSBase::VCSBaseEditorWidget* editor = 0,
bool useOutputToWindow = false,
int editorLineNumber = -1);
GitCommand *executeGit(const QString &workingDirectory,
VCSBase::Command *executeGit(const QString &workingDirectory,
const QStringList &arguments,
VCSBase::VCSBaseEditorWidget* editor = 0,
bool useOutputToWindow = false,
GitCommand::TerminationReportMode tm = GitCommand::NoReport,
VCSBase::Command::TerminationReportMode tm = VCSBase::Command::NoReport,
int editorLineNumber = -1,
bool unixTerminalDisabled = false);
......@@ -279,7 +278,7 @@ private:
bool *isDirectory,
QString *errorMessage,
bool revertStaging);
void connectRepositoryChanged(const QString & repository, GitCommand *cmd);
void connectRepositoryChanged(const QString & repository, VCSBase::Command *cmd);
bool synchronousPull(const QString &workingDirectory, bool rebase);
void syncAbortPullRebase(const QString &workingDir);
bool tryLauchingGitK(const QProcessEnvironment &env,
......
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#include "gitcommand.h"
#include "gitconstants.h"
#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/synchronousprocess.h>
#include <QtCore/QDebug>
#include <QtCore/QProcess>
#include <QtCore/QFuture>
#include <QtCore/QtConcurrentRun>
#include <QtCore/QFileInfo>
#include <QtCore/QCoreApplication>
Q_DECLARE_METATYPE(QVariant)
namespace Git {
namespace Internal {
static QString msgTermination(int exitCode, const QString &binaryPath, const QStringList &args)
{
QString cmd = QFileInfo(binaryPath).baseName();
if (!args.empty()) {
cmd += QLatin1Char(' ');
cmd += args.front();
}
return exitCode ?
QCoreApplication::translate("GitCommand", "\n'%1' failed (exit code %2).\n").arg(cmd).arg(exitCode) :
QCoreApplication::translate("GitCommand", "\n'%1' completed (exit code %2).\n").arg(cmd).arg(exitCode);
}
GitCommand::Job::Job(const QStringList &a, int t) :
arguments(a),
timeout(t)
{
// Finished cookie is emitted via queued slot, needs metatype
static const int qvMetaId = qRegisterMetaType<QVariant>();
Q_UNUSED(qvMetaId)
}
GitCommand::GitCommand(const QString &binary,
const QString &workingDirectory,
const QProcessEnvironment&environment,
const QVariant &cookie) :
m_binaryPath(binary),
m_workingDirectory(workingDirectory),
m_environment(environment),
m_cookie(cookie),
m_unixTerminalDisabled(false),
m_reportTerminationMode(NoReport)
{
}
GitCommand::TerminationReportMode GitCommand::reportTerminationMode() const
{
return m_reportTerminationMode;
}
void GitCommand::setTerminationReportMode(TerminationReportMode m)
{
m_reportTerminationMode = m;
}
bool GitCommand::unixTerminalDisabled() const
{
return m_unixTerminalDisabled;
}
void GitCommand::setUnixTerminalDisabled(bool e)
{
m_unixTerminalDisabled = e;
}
void GitCommand::addJob(const QStringList &arguments, int timeout)
{
m_jobs.push_back(Job(arguments, timeout));
}
void GitCommand::execute()
{
if (m_jobs.empty())
return;
// For some reason QtConcurrent::run() only works on this
QFuture<void> task = QtConcurrent::run(this, &GitCommand::run);
const QString taskName = QLatin1String("Git ") + m_jobs.front().arguments.at(0);
Core::ICore::instance()->progressManager()->addTask(task, taskName,
QLatin1String("Git.action"));
}
void GitCommand::run()
{
const unsigned processFlags = m_unixTerminalDisabled ?
unsigned(Utils::SynchronousProcess::UnixTerminalDisabled) :
unsigned(0);
const QSharedPointer<QProcess> process =
Utils::SynchronousProcess::createProcess(processFlags);
if (!m_workingDirectory.isEmpty())
process->setWorkingDirectory(m_workingDirectory);
process->setProcessEnvironment(m_environment);
QByteArray stdOut;
QByteArray stdErr;
QString error;
const int count = m_jobs.size();
int exitCode = -1;
bool ok = true;
for (int j = 0; j < count; j++) {
process->start(m_binaryPath, m_jobs.at(j).arguments);
if (!process->waitForStarted()) {
ok = false;
error += QString::fromLatin1("Error: \"%1\" could not be started: %2").arg(m_binaryPath, process->errorString());
break;
}
process->closeWriteChannel();
const int timeOutSeconds = m_jobs.at(j).timeout;
if (!Utils::SynchronousProcess::readDataFromProcess(*process, timeOutSeconds * 1000,
&stdOut, &stdErr, false)) {
Utils::SynchronousProcess::stopProcess(*process);
ok = false;
error += tr("Error: Git timed out after %1s.").arg(timeOutSeconds);
break;
}
error += QString::fromLocal8Bit(stdErr);
exitCode = process->exitCode();
switch (m_reportTerminationMode) {
case NoReport:
break;
case ReportStdout:
stdOut += msgTermination(exitCode, m_binaryPath, m_jobs.at(j).arguments).toUtf8();
break;
case ReportStderr:
error += msgTermination(exitCode, m_binaryPath, m_jobs.at(j).arguments);
break;
}
}
// Special hack: Always produce output for diff
if (ok && stdOut.isEmpty() && m_jobs.front().arguments.at(0) == QLatin1String("diff")) {
stdOut += "No difference to HEAD";
} else {
// @TODO: Remove, see below
if (ok && m_jobs.front().arguments.at(0) == QLatin1String("status"))
removeColorCodes(&stdOut);
}
if (ok && !stdOut.isEmpty())
emit outputData(stdOut);
if (!error.isEmpty())
emit errorText(error);
emit finished(ok, exitCode, m_cookie);
if (ok)
emit success();
// As it is used asynchronously, we need to delete ourselves
this->deleteLater();
}
// Clean output from carriage return and ANSI color codes.
// @TODO: Remove once all relevant commands support "--no-color",
//("status" is missing it as of git 1.6.2)
void GitCommand::removeColorCodes(QByteArray *data)
{
// Remove ansi color codes that look like "ESC[<stuff>m"
const QByteArray ansiColorEscape("\033[");
int escapePos = 0;
while (true) {
const int nextEscapePos = data->indexOf(ansiColorEscape, escapePos);
if (nextEscapePos == -1)
break;
const int endEscapePos = data->indexOf('m', nextEscapePos + ansiColorEscape.size());
if (endEscapePos != -1) {
data->remove(nextEscapePos, endEscapePos - nextEscapePos + 1);
escapePos = nextEscapePos;
} else {
escapePos = nextEscapePos + ansiColorEscape.size();
}
}
}
void GitCommand::setCookie(const QVariant &cookie)
{
m_cookie = cookie;
}
QVariant GitCommand::cookie() const
{
return m_cookie;
}
} // namespace Internal
} // namespace Git
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#ifndef GITCOMMAND_H
#define GITCOMMAND_H
#include <QtCore/QObject>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QtCore/QProcessEnvironment>
namespace Git {
namespace Internal {
// Asynchronous command with output signals and a finished
// signal with a magic cookie
class GitCommand : public QObject
{
Q_OBJECT
public:
// Where to report command termination with exit code if desired
enum TerminationReportMode { NoReport,
ReportStdout, // This assumes UTF8
ReportStderr };
GitCommand(const QString &binary,
const QString &workingDirectory,
const QProcessEnvironment &environment,
const QVariant &cookie = QVariant());
void addJob(const QStringList &arguments, int timeout);
void execute();
// Clean output from carriage return and ANSI color codes.
// Workaround until all relevant commands support "--no-color".
static void removeColorCodes(QByteArray *data);
// Report command termination with exit code
TerminationReportMode reportTerminationMode() const;
void setTerminationReportMode(TerminationReportMode m);
// Disable Terminal on UNIX (see VCS SSH handling).
bool unixTerminalDisabled() const;
void setUnixTerminalDisabled(bool);
void setCookie(const QVariant &cookie);
QVariant cookie() const;
private:
void run();
signals:
void outputData(const QByteArray &);
void errorText(const QString &);
void finished(bool ok, int exitCode, const QVariant &cookie);
void success();
private:
struct Job {
explicit Job(const QStringList &a, int t);
QStringList arguments;
int timeout;
};
const QString m_binaryPath;
const QString m_workingDirectory;
const QProcessEnvironment m_environment;
QVariant m_cookie;
bool m_unixTerminalDisabled;
QList<Job> m_jobs;
TerminationReportMode m_reportTerminationMode;
};
} // namespace Internal
} // namespace Git
#endif // GITCOMMAND_H
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment