Skip to content
Snippets Groups Projects
Commit 696b0a8b authored by jkobus's avatar jkobus Committed by Jarek Kobus
Browse files

Introduce ExitCodeInterpreter, useful when exit code != 0 is valid


Task-number: QTCREATORBUG-10207

Change-Id: I3b440d40a968f09afc613b686ee50da6465ad88e
Reviewed-by: default avatarTobias Hunger <tobias.hunger@digia.com>
parent 005bef92
No related branches found
No related tags found
No related merge requests found
...@@ -149,6 +149,12 @@ QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const SynchronousProcessRes ...@@ -149,6 +149,12 @@ QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const SynchronousProcessRes
return str; return str;
} }
SynchronousProcessResponse::Result ExitCodeInterpreter::interpretExitCode(int code) const
{
return code ? SynchronousProcessResponse::FinishedError
: SynchronousProcessResponse::Finished;
}
// Data for one channel buffer (stderr/stdout) // Data for one channel buffer (stderr/stdout)
struct ChannelBuffer { struct ChannelBuffer {
ChannelBuffer(); ChannelBuffer();
...@@ -197,6 +203,7 @@ struct SynchronousProcessPrivate { ...@@ -197,6 +203,7 @@ struct SynchronousProcessPrivate {
void clearForRun(); void clearForRun();
QTextCodec *m_codec; QTextCodec *m_codec;
ExitCodeInterpreter *m_exitCodeInterpreter;
QTextCodec::ConverterState m_stdOutState; QTextCodec::ConverterState m_stdOutState;
QTextCodec::ConverterState m_stdErrState; QTextCodec::ConverterState m_stdErrState;
TerminalControllingProcess m_process; TerminalControllingProcess m_process;
...@@ -216,6 +223,7 @@ struct SynchronousProcessPrivate { ...@@ -216,6 +223,7 @@ struct SynchronousProcessPrivate {
SynchronousProcessPrivate::SynchronousProcessPrivate() : SynchronousProcessPrivate::SynchronousProcessPrivate() :
m_codec(QTextCodec::codecForLocale()), m_codec(QTextCodec::codecForLocale()),
m_exitCodeInterpreter(0),
m_hangTimerCount(0), m_hangTimerCount(0),
m_maxHangTimerCount(defaultMaxHangTimerCount), m_maxHangTimerCount(defaultMaxHangTimerCount),
m_startFailure(false), m_startFailure(false),
...@@ -339,6 +347,16 @@ void SynchronousProcess::setFlags(unsigned tc) ...@@ -339,6 +347,16 @@ void SynchronousProcess::setFlags(unsigned tc)
d->m_process.setFlags(tc); d->m_process.setFlags(tc);
} }
void SynchronousProcess::setExitCodeInterpreter(ExitCodeInterpreter *interpreter)
{
d->m_exitCodeInterpreter = interpreter;
}
ExitCodeInterpreter *SynchronousProcess::exitCodeInterpreter() const
{
return d->m_exitCodeInterpreter;
}
void SynchronousProcess::setWorkingDirectory(const QString &workingDirectory) void SynchronousProcess::setWorkingDirectory(const QString &workingDirectory)
{ {
d->m_process.setWorkingDirectory(workingDirectory); d->m_process.setWorkingDirectory(workingDirectory);
...@@ -451,9 +469,14 @@ void SynchronousProcess::finished(int exitCode, QProcess::ExitStatus e) ...@@ -451,9 +469,14 @@ void SynchronousProcess::finished(int exitCode, QProcess::ExitStatus e)
if (debug) if (debug)
qDebug() << Q_FUNC_INFO << exitCode << e; qDebug() << Q_FUNC_INFO << exitCode << e;
d->m_hangTimerCount = 0; d->m_hangTimerCount = 0;
ExitCodeInterpreter defaultInterpreter(this);
ExitCodeInterpreter *currentInterpreter = d->m_exitCodeInterpreter
? d->m_exitCodeInterpreter : &defaultInterpreter;
switch (e) { switch (e) {
case QProcess::NormalExit: case QProcess::NormalExit:
d->m_result.result = exitCode ? SynchronousProcessResponse::FinishedError : SynchronousProcessResponse::Finished; d->m_result.result = currentInterpreter->interpretExitCode(exitCode);
d->m_result.exitCode = exitCode; d->m_result.exitCode = exitCode;
break; break;
case QProcess::CrashExit: case QProcess::CrashExit:
......
...@@ -71,6 +71,14 @@ struct QTCREATOR_UTILS_EXPORT SynchronousProcessResponse ...@@ -71,6 +71,14 @@ struct QTCREATOR_UTILS_EXPORT SynchronousProcessResponse
QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const SynchronousProcessResponse &); QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const SynchronousProcessResponse &);
class QTCREATOR_UTILS_EXPORT ExitCodeInterpreter : public QObject
{
Q_OBJECT
public:
ExitCodeInterpreter(QObject *parent) : QObject(parent) {}
virtual SynchronousProcessResponse::Result interpretExitCode(int code) const;
};
class QTCREATOR_UTILS_EXPORT SynchronousProcess : public QObject class QTCREATOR_UTILS_EXPORT SynchronousProcess : public QObject
{ {
Q_OBJECT Q_OBJECT
...@@ -115,6 +123,9 @@ public: ...@@ -115,6 +123,9 @@ public:
unsigned flags() const; unsigned flags() const;
void setFlags(unsigned); void setFlags(unsigned);
void setExitCodeInterpreter(ExitCodeInterpreter *interpreter);
ExitCodeInterpreter *exitCodeInterpreter() const;
SynchronousProcessResponse run(const QString &binary, const QStringList &args); SynchronousProcessResponse run(const QString &binary, const QStringList &args);
// Create a (derived) processes with flags applied. // Create a (derived) processes with flags applied.
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <vcsbase/vcsbaseplugin.h> #include <vcsbase/vcsbaseplugin.h>
#include <vcsbase/vcsbaseeditorparameterwidget.h> #include <vcsbase/vcsbaseeditorparameterwidget.h>
#include <utils/synchronousprocess.h>
#include <QDir> #include <QDir>
#include <QFileInfo> #include <QFileInfo>
...@@ -40,6 +41,22 @@ ...@@ -40,6 +41,22 @@
namespace Bazaar { namespace Bazaar {
namespace Internal { namespace Internal {
class BazaarDiffExitCodeInterpreter : public Utils::ExitCodeInterpreter
{
Q_OBJECT
public:
BazaarDiffExitCodeInterpreter(QObject *parent) : Utils::ExitCodeInterpreter(parent) {}
Utils::SynchronousProcessResponse::Result interpretExitCode(int code) const;
};
Utils::SynchronousProcessResponse::Result BazaarDiffExitCodeInterpreter::interpretExitCode(int code) const
{
if (code < 0 || code > 2)
return Utils::SynchronousProcessResponse::FinishedError;
return Utils::SynchronousProcessResponse::Finished;
}
BazaarClient::BazaarClient(BazaarSettings *settings) : BazaarClient::BazaarClient(BazaarSettings *settings) :
VcsBase::VcsBaseClient(settings) VcsBase::VcsBaseClient(settings)
{ {
...@@ -142,6 +159,16 @@ QString BazaarClient::vcsCommandString(VcsCommand cmd) const ...@@ -142,6 +159,16 @@ QString BazaarClient::vcsCommandString(VcsCommand cmd) const
} }
} }
Utils::ExitCodeInterpreter *BazaarClient::exitCodeInterpreter(VcsCommand cmd, QObject *parent) const
{
switch (cmd) {
case DiffCommand:
return new BazaarDiffExitCodeInterpreter(parent);
default:
return 0;
}
}
QStringList BazaarClient::revisionSpec(const QString &revision) const QStringList BazaarClient::revisionSpec(const QString &revision) const
{ {
QStringList args; QStringList args;
......
...@@ -61,6 +61,7 @@ public: ...@@ -61,6 +61,7 @@ public:
protected: protected:
Core::Id vcsEditorKind(VcsCommand cmd) const; Core::Id vcsEditorKind(VcsCommand cmd) const;
QString vcsCommandString(VcsCommand cmd) const; QString vcsCommandString(VcsCommand cmd) const;
Utils::ExitCodeInterpreter *exitCodeInterpreter(VcsCommand cmd, QObject *parent) const;
QStringList revisionSpec(const QString &revision) const; QStringList revisionSpec(const QString &revision) const;
VcsBase::VcsBaseEditorParameterWidget *createDiffEditor(const QString &workingDir, VcsBase::VcsBaseEditorParameterWidget *createDiffEditor(const QString &workingDir,
const QStringList &files, const QStringList &files,
......
...@@ -78,10 +78,11 @@ class CommandPrivate ...@@ -78,10 +78,11 @@ class CommandPrivate
{ {
public: public:
struct Job { struct Job {
explicit Job(const QStringList &a, int t); explicit Job(const QStringList &a, int t, Utils::ExitCodeInterpreter *interpreter = 0);
QStringList arguments; QStringList arguments;
int timeout; int timeout;
Utils::ExitCodeInterpreter *exitCodeInterpreter;
}; };
CommandPrivate(const QString &binary, CommandPrivate(const QString &binary,
...@@ -130,9 +131,10 @@ CommandPrivate::~CommandPrivate() ...@@ -130,9 +131,10 @@ CommandPrivate::~CommandPrivate()
delete m_progressParser; delete m_progressParser;
} }
CommandPrivate::Job::Job(const QStringList &a, int t) : CommandPrivate::Job::Job(const QStringList &a, int t, Utils::ExitCodeInterpreter *interpreter) :
arguments(a), arguments(a),
timeout(t) timeout(t),
exitCodeInterpreter(interpreter)
{ {
// Finished cookie is emitted via queued slot, needs metatype // Finished cookie is emitted via queued slot, needs metatype
static const int qvMetaId = qRegisterMetaType<QVariant>(); static const int qvMetaId = qRegisterMetaType<QVariant>();
...@@ -188,14 +190,14 @@ void Command::addFlags(unsigned f) ...@@ -188,14 +190,14 @@ void Command::addFlags(unsigned f)
d->m_flags |= f; d->m_flags |= f;
} }
void Command::addJob(const QStringList &arguments) void Command::addJob(const QStringList &arguments, Utils::ExitCodeInterpreter *interpreter)
{ {
addJob(arguments, defaultTimeout()); addJob(arguments, defaultTimeout(), interpreter);
} }
void Command::addJob(const QStringList &arguments, int timeout) void Command::addJob(const QStringList &arguments, int timeout, Utils::ExitCodeInterpreter *interpreter)
{ {
d->m_jobs.push_back(Internal::CommandPrivate::Job(arguments, timeout)); d->m_jobs.push_back(Internal::CommandPrivate::Job(arguments, timeout, interpreter));
} }
void Command::execute() void Command::execute()
...@@ -249,10 +251,12 @@ void Command::run(QFutureInterface<void> &future) ...@@ -249,10 +251,12 @@ void Command::run(QFutureInterface<void> &future)
d->m_lastExecExitCode = -1; d->m_lastExecExitCode = -1;
d->m_lastExecSuccess = true; d->m_lastExecSuccess = true;
for (int j = 0; j < count; j++) { for (int j = 0; j < count; j++) {
const int timeOutSeconds = d->m_jobs.at(j).timeout; const Internal::CommandPrivate::Job &job = d->m_jobs.at(j);
const int timeOutSeconds = job.timeout;
Utils::SynchronousProcessResponse resp = runVcs( Utils::SynchronousProcessResponse resp = runVcs(
d->m_jobs.at(j).arguments, job.arguments,
timeOutSeconds >= 0 ? timeOutSeconds * 1000 : -1); timeOutSeconds >= 0 ? timeOutSeconds * 1000 : -1,
job.exitCodeInterpreter);
stdOut += resp.stdOut; stdOut += resp.stdOut;
stdErr += resp.stdErr; stdErr += resp.stdErr;
d->m_lastExecExitCode = resp.exitCode; d->m_lastExecExitCode = resp.exitCode;
...@@ -309,7 +313,8 @@ signals: ...@@ -309,7 +313,8 @@ signals:
void appendMessage(const QString &text); void appendMessage(const QString &text);
}; };
Utils::SynchronousProcessResponse Command::runVcs(const QStringList &arguments, int timeoutMS) Utils::SynchronousProcessResponse Command::runVcs(const QStringList &arguments, int timeoutMS,
Utils::ExitCodeInterpreter *interpreter)
{ {
Utils::SynchronousProcessResponse response; Utils::SynchronousProcessResponse response;
OutputProxy outputProxy; OutputProxy outputProxy;
...@@ -353,9 +358,10 @@ Utils::SynchronousProcessResponse Command::runVcs(const QStringList &arguments, ...@@ -353,9 +358,10 @@ Utils::SynchronousProcessResponse Command::runVcs(const QStringList &arguments,
// if (d->m_flags & ExpectRepoChanges) // if (d->m_flags & ExpectRepoChanges)
// Core::DocumentManager::expectDirectoryChange(d->m_workingDirectory); // Core::DocumentManager::expectDirectoryChange(d->m_workingDirectory);
if (d->m_flags & VcsBasePlugin::FullySynchronously) { if (d->m_flags & VcsBasePlugin::FullySynchronously) {
response = runSynchronous(arguments, timeoutMS); response = runSynchronous(arguments, timeoutMS, interpreter);
} else { } else {
Utils::SynchronousProcess process; Utils::SynchronousProcess process;
process.setExitCodeInterpreter(interpreter);
connect(this, SIGNAL(doTerminate()), &process, SLOT(terminate())); connect(this, SIGNAL(doTerminate()), &process, SLOT(terminate()));
if (!d->m_workingDirectory.isEmpty()) if (!d->m_workingDirectory.isEmpty())
process.setWorkingDirectory(d->m_workingDirectory); process.setWorkingDirectory(d->m_workingDirectory);
...@@ -412,7 +418,8 @@ Utils::SynchronousProcessResponse Command::runVcs(const QStringList &arguments, ...@@ -412,7 +418,8 @@ Utils::SynchronousProcessResponse Command::runVcs(const QStringList &arguments,
return response; return response;
} }
Utils::SynchronousProcessResponse Command::runSynchronous(const QStringList &arguments, int timeoutMS) Utils::SynchronousProcessResponse Command::runSynchronous(const QStringList &arguments, int timeoutMS,
Utils::ExitCodeInterpreter *interpreter)
{ {
Utils::SynchronousProcessResponse response; Utils::SynchronousProcessResponse response;
...@@ -465,15 +472,15 @@ Utils::SynchronousProcessResponse Command::runSynchronous(const QStringList &arg ...@@ -465,15 +472,15 @@ Utils::SynchronousProcessResponse Command::runSynchronous(const QStringList &arg
} }
} }
Utils::ExitCodeInterpreter defaultInterpreter(this);
Utils::ExitCodeInterpreter *currentInterpreter = interpreter ? interpreter : &defaultInterpreter;
// Result // Result
if (timedOut) { if (timedOut) {
response.result = Utils::SynchronousProcessResponse::Hang; response.result = Utils::SynchronousProcessResponse::Hang;
} else if (process->exitStatus() != QProcess::NormalExit) { } else if (process->exitStatus() != QProcess::NormalExit) {
response.result = Utils::SynchronousProcessResponse::TerminatedAbnormally; response.result = Utils::SynchronousProcessResponse::TerminatedAbnormally;
} else { } else {
response.result = process->exitCode() == 0 ? response.result = currentInterpreter->interpretExitCode(process->exitCode());
Utils::SynchronousProcessResponse::Finished :
Utils::SynchronousProcessResponse::FinishedError;
} }
return response; return response;
} }
......
...@@ -77,8 +77,8 @@ public: ...@@ -77,8 +77,8 @@ public:
const QProcessEnvironment &environment); const QProcessEnvironment &environment);
~Command(); ~Command();
void addJob(const QStringList &arguments); void addJob(const QStringList &arguments, Utils::ExitCodeInterpreter *interpreter = 0);
void addJob(const QStringList &arguments, int timeout); void addJob(const QStringList &arguments, int timeout, Utils::ExitCodeInterpreter *interpreter = 0);
void execute(); void execute();
void terminate(); void terminate();
bool lastExecutionSuccess() const; bool lastExecutionSuccess() const;
...@@ -103,14 +103,16 @@ public: ...@@ -103,14 +103,16 @@ public:
void setProgressParser(ProgressParser *parser); void setProgressParser(ProgressParser *parser);
void setProgressiveOutput(bool progressive); void setProgressiveOutput(bool progressive);
Utils::SynchronousProcessResponse runVcs(const QStringList &arguments, int timeoutMS); Utils::SynchronousProcessResponse runVcs(const QStringList &arguments, int timeoutMS,
Utils::ExitCodeInterpreter *interpreter = 0);
// Make sure to not pass through the event loop at all: // Make sure to not pass through the event loop at all:
bool runFullySynchronous(const QStringList &arguments, int timeoutMS, bool runFullySynchronous(const QStringList &arguments, int timeoutMS,
QByteArray *outputData, QByteArray *errorData); QByteArray *outputData, QByteArray *errorData);
private: private:
void run(QFutureInterface<void> &future); void run(QFutureInterface<void> &future);
Utils::SynchronousProcessResponse runSynchronous(const QStringList &arguments, int timeoutMS); Utils::SynchronousProcessResponse runSynchronous(const QStringList &arguments, int timeoutMS,
Utils::ExitCodeInterpreter *interpreter = 0);
private slots: private slots:
void bufferedOutput(const QString &text); void bufferedOutput(const QString &text);
......
...@@ -365,7 +365,8 @@ void VcsBaseClient::diff(const QString &workingDir, const QStringList &files, ...@@ -365,7 +365,8 @@ void VcsBaseClient::diff(const QString &workingDir, const QStringList &files,
QStringList args; QStringList args;
const QStringList paramArgs = paramWidget != 0 ? paramWidget->arguments() : QStringList(); const QStringList paramArgs = paramWidget != 0 ? paramWidget->arguments() : QStringList();
args << vcsCmdString << extraOptions << paramArgs << files; args << vcsCmdString << extraOptions << paramArgs << files;
enqueueJob(createCommand(workingDir, editor), args); Command *command = createCommand(workingDir, editor);
enqueueJob(command, args, exitCodeInterpreter(DiffCommand, command));
} }
void VcsBaseClient::log(const QString &workingDir, const QStringList &files, void VcsBaseClient::log(const QString &workingDir, const QStringList &files,
...@@ -461,6 +462,13 @@ QString VcsBaseClient::vcsCommandString(VcsCommand cmd) const ...@@ -461,6 +462,13 @@ QString VcsBaseClient::vcsCommandString(VcsCommand cmd) const
return QString(); return QString();
} }
Utils::ExitCodeInterpreter *VcsBaseClient::exitCodeInterpreter(VcsCommand cmd, QObject *parent) const
{
Q_UNUSED(cmd)
Q_UNUSED(parent)
return 0;
}
void VcsBaseClient::import(const QString &repositoryRoot, const QStringList &files, void VcsBaseClient::import(const QString &repositoryRoot, const QStringList &files,
const QStringList &extraOptions) const QStringList &extraOptions)
{ {
...@@ -605,9 +613,9 @@ Command *VcsBaseClient::createCommand(const QString &workingDirectory, ...@@ -605,9 +613,9 @@ Command *VcsBaseClient::createCommand(const QString &workingDirectory,
return cmd; return cmd;
} }
void VcsBaseClient::enqueueJob(Command *cmd, const QStringList &args) void VcsBaseClient::enqueueJob(Command *cmd, const QStringList &args, Utils::ExitCodeInterpreter *interpreter)
{ {
cmd->addJob(args); cmd->addJob(args, interpreter);
cmd->execute(); cmd->execute();
} }
......
...@@ -44,6 +44,7 @@ QT_END_NAMESPACE ...@@ -44,6 +44,7 @@ QT_END_NAMESPACE
namespace Utils { namespace Utils {
struct SynchronousProcessResponse; struct SynchronousProcessResponse;
class ExitCodeInterpreter;
} }
namespace VcsBase { namespace VcsBase {
...@@ -150,6 +151,7 @@ protected: ...@@ -150,6 +151,7 @@ protected:
}; };
virtual QString vcsCommandString(VcsCommand cmd) const; virtual QString vcsCommandString(VcsCommand cmd) const;
virtual Core::Id vcsEditorKind(VcsCommand cmd) const = 0; virtual Core::Id vcsEditorKind(VcsCommand cmd) const = 0;
virtual Utils::ExitCodeInterpreter *exitCodeInterpreter(VcsCommand cmd, QObject *parent) const;
virtual QStringList revisionSpec(const QString &revision) const = 0; virtual QStringList revisionSpec(const QString &revision) const = 0;
virtual VcsBaseEditorParameterWidget *createDiffEditor(const QString &workingDir, virtual VcsBaseEditorParameterWidget *createDiffEditor(const QString &workingDir,
...@@ -183,7 +185,7 @@ protected: ...@@ -183,7 +185,7 @@ protected:
Command *createCommand(const QString &workingDirectory, Command *createCommand(const QString &workingDirectory,
VcsBase::VcsBaseEditorWidget *editor = 0, VcsBase::VcsBaseEditorWidget *editor = 0,
JobOutputBindMode mode = NoOutputBind); JobOutputBindMode mode = NoOutputBind);
void enqueueJob(Command *cmd, const QStringList &args); void enqueueJob(Command *cmd, const QStringList &args, Utils::ExitCodeInterpreter *interpreter = 0);
void resetCachedVcsInfo(const QString &workingDir); void resetCachedVcsInfo(const QString &workingDir);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment