Add common/command

This commit is contained in:
2026-02-05 13:59:13 +01:00
parent 553782a2ea
commit 47e7e1e796
2 changed files with 177 additions and 0 deletions

49
common/include/command.h Normal file
View File

@@ -0,0 +1,49 @@
#ifndef COMMAND_H_INCLUDED
#define COMMAND_H_INCLUDED
#include <QObject>
#include <QCoreApplication>
#include <QString>
#include <QStringList>
#include <QProcess>
#include <QScopedPointer>
class Command : public QObject {
Q_OBJECT
QString m_command;
QString m_commandResult;
int m_waitForStartTimeout;
int m_waitForFinishTimeout;
bool m_verbose;
int m_exitCode;
QString m_workingDirectory;
QScopedPointer<QProcess> m_p;
QStringList m_args;
public:
Command(QString command,
QStringList args,
QString workingDirectory,
bool verbose = true,
int start_timeout = 100000,
int finish_timeout = 100000);
void resetCommandResult() { m_commandResult.clear(); }
QString getCommandResult(bool reset = false);
QString const &command() const { return m_command; }
QString const &commandResult() const { return m_commandResult; }
QStringList const &args() const { return m_args; }
bool exec();
int exitCode() const { return m_exitCode; }
private slots:
virtual void readyReadStandardOutput();
virtual void readyReadStandardError();
};
#endif // COMMAND_H_INCLUDED

128
common/src/command.cpp Normal file
View File

@@ -0,0 +1,128 @@
#include "command.h"
#include <QProcess>
#include <QDebug>
#include <QDir>
#include <QRegularExpression>
#include <QDateTime>
Command::Command(QString command, QStringList args, QString workingDirectory,
bool verbose, int start_timeout, int finish_timeout)
: m_command(command.trimmed())
, m_commandResult("")
, m_waitForStartTimeout(start_timeout)
, m_waitForFinishTimeout(finish_timeout)
, m_verbose(verbose)
, m_exitCode(-1)
, m_workingDirectory(workingDirectory)
, m_args(args) {
m_p.reset(new QProcess(this));
if (m_p) {
m_p->setWorkingDirectory(workingDirectory);
m_p->setProcessChannelMode(QProcess::MergedChannels);
connect(m_p.get(), SIGNAL(readyReadStandardOutput()), this, SLOT(readyReadStandardOutput()));
connect(m_p.get(), SIGNAL(readyReadStandardError()), this, SLOT(readyReadStandardError()));
}
}
void Command::readyReadStandardOutput() {
QProcess *p = (QProcess *)sender();
if (p) {
QString s = p->readAllStandardOutput();
if (m_verbose) {
// qCritical().noquote() << s;
m_commandResult += s;
}
}
}
void Command::readyReadStandardError() {
QProcess *p = (QProcess *)sender();
if (p) {
QString s = p->readAllStandardError();
// qCritical().noquote() << s;
m_commandResult += s;
}
}
QString Command::getCommandResult(bool reset) {
if (reset == false) {
return m_commandResult;
}
QString commandResult = m_commandResult;
m_commandResult.clear();
return commandResult;
}
bool Command::exec() {
if (!m_args.isEmpty()) {
m_p->start(m_command, m_args);
} else {
m_p->start(m_command);
}
qint64 const start = QDateTime::currentDateTime().toMSecsSinceEpoch();
bool started = false;
if ((started = m_p->waitForStarted(m_waitForStartTimeout)) == true) {
// qCritical() << "PROCESS" << m_command << "STARTED IN" << m_p->workingDirectory();
if (m_p->state() == QProcess::ProcessState::Running) {
// qDebug() << "PROCESS" << m_command << "RUNNING IN" << p->workingDirectory();
// wait forever for git/opkg-commands to finish
int wait = m_waitForFinishTimeout;
if (m_command.trimmed().startsWith("git", Qt::CaseInsensitive) ||
m_command.trimmed().startsWith("opkg", Qt::CaseInsensitive)) {
wait = -1;
}
bool const no_timeout = m_p->waitForFinished(wait);
if (no_timeout) {
// qDebug() << "PROCESS" << m_command << "FINISHED IN" << p->workingDirectory();
if (m_p->exitStatus() == QProcess::NormalExit) {
if ((m_exitCode = m_p->exitCode()) == 0) {
qCritical().noquote() << m_p->readAllStandardOutput();
//qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();
//qDebug() << "EXECUTED" << m_command
// << QString("(runtime %1ms)").arg(end-start)
// << "with code" << m_exitCode
// << "IN" << m_p->workingDirectory();
return true;
} else {
qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();
qCritical() << "EXECUTED" << m_command
<< QString("(runtime %1ms)").arg(end-start)
<< "with code" << m_exitCode
<< "IN" << m_p->workingDirectory();
}
} else {
qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();
qCritical() << "PROCESS" << m_command << "CRASHED with code"
<< m_p->exitCode()
<< QString("(after %1ms)").arg(end-start)
<< "IN" << m_p->workingDirectory();
}
} else {
qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();
qCritical() << "PROCESS" << m_command
<< "DID NOT FINISH WITH" << wait
<< "MS IN" << m_p->workingDirectory()
<< QString("(runtime %1ms)").arg(end-start);
}
} else {
qCritical() << "WRONG PROCESS STATE" << m_p->state()
<< "IN" << m_p->workingDirectory();
}
} else {
qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();
qCritical() << "PROCESS" << m_command << "TIMEOUT AT START"
<< QString("(runtime %1ms)").arg(end-start)
<< "IN" << m_p->workingDirectory() << m_waitForStartTimeout;
}
return false;
}