4#include <QCoreApplication>
6#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
9#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
10#include <QStringDecoder>
24 static_cast<void (QProcess::*)(
int, QProcess::ExitStatus)
>(
27 static_cast<void (
Executor::*)(
int, QProcess::ExitStatus)
>(
28 &Executor::finished));
35void Executor::executeNext() {
37 if (!m_execQueue.isEmpty()) {
38 const execQueueItem &i = m_execQueue.head();
40 if (!i.workingDir.isEmpty()) {
41 m_process.setWorkingDirectory(i.workingDir);
43 if (i.app.startsWith(
"wsl ")) {
44 QStringList tmp = i.args;
46 tmp.prepend(app.remove(0, 4));
47 m_process.start(
"wsl", tmp);
49 m_process.start(i.app, i.args);
51 if (!i.input.isEmpty()) {
52 m_process.waitForStarted(-1);
53 QByteArray data = i.input.toUtf8();
54 if (m_process.write(data) != data.length()) {
56 dbg() <<
"Not all data written to process:" << i.id <<
" " << i.app;
60 m_process.closeWriteChannel();
74 bool readStdout,
bool readStderr) {
75 execute(
id, QString(), app, args, QString(), readStdout, readStderr);
88 const QStringList &args,
bool readStdout,
90 execute(
id, workDir, app, args, QString(), readStdout, readStderr);
103 QString input,
bool readStdout,
bool readStderr) {
104 execute(
id, QString(), app, args, std::move(input), readStdout, readStderr);
119 const QStringList &args, QString input,
bool readStdout,
126 dbg() <<
"Trying to execute nothing...";
130 QString appPath = app;
131 if (!appPath.startsWith(
"wsl ")) {
133 QDir(QCoreApplication::applicationDirPath()).absoluteFilePath(app);
135 m_execQueue.push_back(
136 {id, appPath, args, std::move(input), readStdout, readStderr, workDir});
150static auto decodeAssumingUtf8(
const QByteArray &in) -> QString {
151#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
152 QTextCodec *codec = QTextCodec::codecForName(
"UTF-8");
153 QTextCodec::ConverterState state;
154 QString out = codec->toUnicode(in.constData(), in.size(), &state);
155 if (!state.invalidChars)
157 codec = QTextCodec::codecForUtfText(in);
158 return codec->toUnicode(in);
160 auto converter = QStringDecoder(QStringDecoder::Utf8);
161 return converter(in);
178 const QString &input, QString *process_out,
179 QString *process_err) ->
int {
181 if (app.startsWith(
"wsl ")) {
182 QStringList tmp = args;
183 tmp.prepend(app.remove(0, 4));
184 internal.start(
"wsl", tmp);
186 internal.start(app, args);
188 if (!input.isEmpty()) {
189 QByteArray data = input.toUtf8();
190 internal.waitForStarted(-1);
191 if (internal.write(data) != data.length()) {
193 dbg() <<
"Not all input written:" << app;
196 internal.closeWriteChannel();
198 internal.waitForFinished(-1);
199 if (internal.exitStatus() == QProcess::NormalExit) {
200 QString pout = decodeAssumingUtf8(internal.readAllStandardOutput());
201 QString perr = decodeAssumingUtf8(internal.readAllStandardError());
202 if (process_out !=
nullptr) {
205 if (process_err !=
nullptr) {
208 return internal.exitCode();
223 QString *process_out, QString *process_err)
225 return executeBlocking(std::move(app), args, QString(), process_out,
235 m_process.setEnvironment(env);
245 if (running || m_execQueue.isEmpty()) {
248 return m_execQueue.dequeue().id;
256void Executor::finished(
int exitCode, QProcess::ExitStatus exitStatus) {
257 execQueueItem i = m_execQueue.dequeue();
259 if (exitStatus == QProcess::NormalExit) {
263 output = decodeAssumingUtf8(m_process.readAllStandardOutput());
265 if (i.readStderr || exitCode != 0) {
266 err = decodeAssumingUtf8(m_process.readAllStandardError());
269 dbg() << exitCode << err;
273 emit finished(i.id, exitCode, output, err);
Executes external commands for handleing password, git and other data.
Executor(QObject *parent=0)
Executor::Executor executes external applications.
static auto executeBlocking(QString app, const QStringList &args, const QString &input=QString(), QString *process_out=nullptr, QString *process_err=nullptr) -> int
Executor::executeBlocking blocking version of the executor, takes input and presents it as stdin.
void execute(int id, const QString &app, const QStringList &args, bool readStdout, bool readStderr=true)
Executor::execute execute an app.
void setEnvironment(const QStringList &env)
Executor::setEnvironment set environment variables for executor processes.
void starting()
starting signal that is emited when process starts
auto cancelNext() -> int
Executor::cancelNext cancels execution of first process in queue if it's not already running.