From b979fb5b2a28a60f920661901fc4b8c956e43e66 Mon Sep 17 00:00:00 2001 From: Gerhard Hoffmann Date: Mon, 10 Jul 2023 15:57:59 +0200 Subject: [PATCH] command-class as abstraction for executing git-commands. --- process/command.cpp | 73 +++++++++++++++++++++++++++++++++++++++++++++ process/command.h | 33 ++++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 process/command.cpp create mode 100644 process/command.h diff --git a/process/command.cpp b/process/command.cpp new file mode 100644 index 0000000..bfb1580 --- /dev/null +++ b/process/command.cpp @@ -0,0 +1,73 @@ +#include "command.h" + +#include +#include +#include + +Command::Command(QString const &command, int start_timeout, int finish_timeout) + : m_command(command.trimmed()) + , m_commandResult("") + , m_waitForStartTimeout(start_timeout) + , m_waitForFinishTimeout(finish_timeout) { +} + +QString Command::getCommandResult() const { + return m_commandResult; +} + +void Command::readyReadStandardOutput() { + QProcess *p = (QProcess *)sender(); + m_commandResult += p->readAllStandardOutput(); + // qCritical() << m_commandResult; +} + +void Command::readyReadStandardError() { + QProcess *p = (QProcess *)sender(); + QByteArray buf = p->readAllStandardError(); + qCritical() << buf; +} + +void Command::finished(int /*exitCode*/, QProcess::ExitStatus /*exitStatus*/) { + QProcess *p = (QProcess *)sender(); + // read all remaining data sent to the process, just in case + QString d = p->readAllStandardOutput(); + if (!d.isEmpty()) { + m_commandResult += d; + } + disconnect(p, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(readyReadStandardOutput())); + disconnect(p, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(readyReadStandardError())); +} + +bool Command::execute(QString workingDirectory) { + QScopedPointer p(new QProcess(this)); + p->setProcessChannelMode(QProcess::MergedChannels); + + connect(&(*p), SIGNAL(readyReadStandardOutput()), this, SLOT(readyReadStandardOutput())); + connect(&(*p), SIGNAL(readyReadStandardError()), this, SLOT(readyReadStandardError())); + + p->setWorkingDirectory(workingDirectory); + p->start(m_command); + + if (p->waitForStarted(m_waitForStartTimeout)) { + if (p->state() == QProcess::ProcessState::Running) { + if (p->waitForFinished(m_waitForFinishTimeout)) { + if (p->exitStatus() == QProcess::NormalExit) { + qInfo() << "EXECUTED" << m_command + << "with code" << p->exitCode(); + // qInfo() << "RESULT" << m_commandResult; + return true; + } else { + qCritical() << "PROCESS" << m_command << "CRASHED with code" + << p->exitCode(); + } + } else { + qCritical() << "PROCESS" << m_command << "DID NOT FINISH"; + } + } else { + qCritical() << "WRONG PROCESS STATE" << p->state(); + } + } else { + qCritical() << "PROCESS" << m_command << "TIMEOUT AT START"; + } + return false; +} diff --git a/process/command.h b/process/command.h new file mode 100644 index 0000000..9ab0f09 --- /dev/null +++ b/process/command.h @@ -0,0 +1,33 @@ +#ifndef COMMAND_H_INCLUDED +#define COMMAND_H_INCLUDED +#endif // COMMAND_H_INCLUDED + +#include +#include +#include +#include +#include + + +class Command : public QObject { + Q_OBJECT + + QString m_command; + QString m_commandResult; + int m_waitForStartTimeout; + int m_waitForFinishTimeout; + +public: + explicit Command(QString const &command, + int start_timeout = 100000, + int finish_timeout = 100000); + + QString getCommandResult() const; + + bool execute(QString workingDirectory = QCoreApplication::applicationDirPath()); + +private slots: + void readyReadStandardOutput(); + void readyReadStandardError(); + void finished(int exitCode, QProcess::ExitStatus exitStatus); +};