Base QtcProcess on ProcessInterface

Change-Id: I51bc6b7aea8e2d3aa0ef9fbba3b5fc796058c8cb
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Jarek Kobus
2022-02-18 01:53:33 +01:00
parent 537100f803
commit 357c39f2d7
2 changed files with 108 additions and 115 deletions

View File

@@ -447,9 +447,10 @@ public:
OtherFailure OtherFailure
}; };
explicit QtcProcessPrivate(QtcProcess *parent) explicit QtcProcessPrivate(QtcProcess *parent, ProcessSetupData &setup)
: QObject(parent) : QObject(parent)
, q(parent) , q(parent)
, m_setup(setup)
{} {}
ProcessInterface *createProcessInterface() ProcessInterface *createProcessInterface()
@@ -525,7 +526,7 @@ public:
QtcProcess *q; QtcProcess *q;
std::unique_ptr<ProcessInterface> m_process; std::unique_ptr<ProcessInterface> m_process;
ProcessSetupData m_setup; ProcessSetupData &m_setup;
void slotTimeout(); void slotTimeout();
void slotFinished(); void slotFinished();
@@ -670,8 +671,8 @@ bool ProcessInterface::ensureProgramExists(const QString &program)
*/ */
QtcProcess::QtcProcess(QObject *parent) QtcProcess::QtcProcess(QObject *parent)
: QObject(parent), : ProcessInterface(parent),
d(new QtcProcessPrivate(this)) d(new QtcProcessPrivate(this, m_setup))
{ {
static int qProcessExitStatusMeta = qRegisterMetaType<QProcess::ExitStatus>(); static int qProcessExitStatusMeta = qRegisterMetaType<QProcess::ExitStatus>();
static int qProcessProcessErrorMeta = qRegisterMetaType<QProcess::ProcessError>(); static int qProcessProcessErrorMeta = qRegisterMetaType<QProcess::ProcessError>();

View File

@@ -43,19 +43,91 @@ class tst_QtcProcess;
namespace Utils { namespace Utils {
class ProcessInterface;
class QtcProcess;
namespace Internal { class QtcProcessPrivate; } namespace Internal { class QtcProcessPrivate; }
class DeviceProcessHooks class QTCREATOR_UTILS_EXPORT ProcessSetupData
{ {
public: public:
std::function<void(QtcProcess &)> startProcessHook; ProcessImpl m_processImpl = ProcessImpl::Default;
std::function<Environment(const FilePath &)> systemEnvironmentForBinary; ProcessMode m_processMode = ProcessMode::Reader;
TerminalMode m_terminalMode = TerminalMode::Off;
CommandLine m_commandLine;
FilePath m_workingDirectory;
Environment m_environment;
QByteArray m_writeData;
QProcess::ProcessChannelMode m_processChannelMode = QProcess::SeparateChannels;
QVariantHash m_extraData;
QString m_standardInputFile;
QString m_errorString; // partial internal
QString m_nativeArguments; // internal, dependent on specific code path
// TODO: Make below bools a one common flag enum?
bool m_abortOnMetaChars = true;
bool m_runAsRoot = false;
bool m_haveEnv = false;
bool m_lowPriority = false;
bool m_unixTerminalDisabled = false;
bool m_useCtrlCStub = false; // debug only
bool m_belowNormalPriority = false; // internal, dependent on other fields and specific code path
}; };
class QTCREATOR_UTILS_EXPORT QtcProcess : public QObject class QTCREATOR_UTILS_EXPORT ProcessInterface : public QObject
{
Q_OBJECT
public:
ProcessInterface(QObject *parent) : QObject(parent) {}
virtual void start() { defaultStart(); }
virtual void terminate() = 0;
virtual void kill() = 0;
virtual void close() = 0;
virtual QByteArray readAllStandardOutput() = 0;
virtual QByteArray readAllStandardError() = 0;
virtual qint64 write(const QByteArray &data) = 0;
virtual qint64 processId() const = 0;
virtual QProcess::ProcessState state() const = 0;
virtual int exitCode() const = 0;
virtual QProcess::ExitStatus exitStatus() const = 0;
virtual QProcess::ProcessError error() const = 0;
virtual QString errorString() const = 0;
virtual void setErrorString(const QString &str) = 0;
virtual bool waitForStarted(int msecs) = 0;
virtual bool waitForReadyRead(int msecs) = 0;
virtual bool waitForFinished(int msecs) = 0;
virtual void kickoffProcess() { QTC_CHECK(false); }
virtual void interruptProcess() { QTC_CHECK(false); }
virtual qint64 applicationMainThreadID() const { QTC_CHECK(false); return -1; }
signals:
void started();
void finished();
void errorOccurred(QProcess::ProcessError error);
void readyReadStandardOutput();
void readyReadStandardError();
protected:
void defaultStart();
ProcessSetupData m_setup;
private:
virtual void doDefaultStart(const QString &program, const QStringList &arguments)
{ Q_UNUSED(program) Q_UNUSED(arguments) QTC_CHECK(false); }
bool dissolveCommand(QString *program, QStringList *arguments);
bool ensureProgramExists(const QString &program);
friend class QtcProcess;
};
class DeviceProcessHooks;
class QTCREATOR_UTILS_EXPORT QtcProcess : public ProcessInterface
{ {
Q_OBJECT Q_OBJECT
@@ -67,31 +139,31 @@ public:
// ProcessInterface related // ProcessInterface related
virtual void start(); void start() override;
virtual void terminate(); void terminate() override;
virtual void kill(); void kill() override;
void close(); void close() final;
virtual QByteArray readAllStandardOutput(); QByteArray readAllStandardOutput() override;
virtual QByteArray readAllStandardError(); QByteArray readAllStandardError() override;
virtual qint64 write(const QByteArray &input); qint64 write(const QByteArray &input) override;
virtual qint64 processId() const; qint64 processId() const override;
virtual QProcess::ProcessState state() const; QProcess::ProcessState state() const override;
virtual int exitCode() const; int exitCode() const override;
virtual QProcess::ExitStatus exitStatus() const; QProcess::ExitStatus exitStatus() const override;
QProcess::ProcessError error() const; QProcess::ProcessError error() const final;
virtual QString errorString() const; QString errorString() const override;
void setErrorString(const QString &str); void setErrorString(const QString &str) final;
bool waitForStarted(int msecs = 30000); bool waitForStarted(int msecs = 30000) final;
bool waitForReadyRead(int msecs = 30000); bool waitForReadyRead(int msecs = 30000) final;
bool waitForFinished(int msecs = 30000); bool waitForFinished(int msecs = 30000) final;
void kickoffProcess(); void kickoffProcess() final;
void interruptProcess(); void interruptProcess() final;
qint64 applicationMainThreadID() const; qint64 applicationMainThreadID() const final;
// ProcessSetupData related // ProcessSetupData related
@@ -218,16 +290,10 @@ public:
QString toStandaloneCommandLine() const; QString toStandaloneCommandLine() const;
signals:
void started();
void finished();
void errorOccurred(QProcess::ProcessError error);
void readyReadStandardOutput();
void readyReadStandardError();
private: private:
friend QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const QtcProcess &r); friend QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const QtcProcess &r);
friend class Internal::QtcProcessPrivate;
Internal::QtcProcessPrivate *d = nullptr; Internal::QtcProcessPrivate *d = nullptr;
friend tst_QtcProcess; friend tst_QtcProcess;
@@ -236,87 +302,13 @@ private:
void endFeed(); void endFeed();
}; };
class QTCREATOR_UTILS_EXPORT ProcessSetupData class DeviceProcessHooks
{ {
public: public:
ProcessImpl m_processImpl = ProcessImpl::Default; std::function<void(QtcProcess &)> startProcessHook;
ProcessMode m_processMode = ProcessMode::Reader; std::function<Environment(const FilePath &)> systemEnvironmentForBinary;
TerminalMode m_terminalMode = TerminalMode::Off;
CommandLine m_commandLine;
FilePath m_workingDirectory;
Environment m_environment;
QByteArray m_writeData;
QProcess::ProcessChannelMode m_processChannelMode = QProcess::SeparateChannels;
QVariantHash m_extraData;
QString m_standardInputFile;
QString m_errorString; // partial internal
QString m_nativeArguments; // internal, dependent on specific code path
// TODO: Make below bools a one common flag enum?
bool m_abortOnMetaChars = true;
bool m_runAsRoot = false;
bool m_haveEnv = false;
bool m_lowPriority = false;
bool m_unixTerminalDisabled = false;
bool m_useCtrlCStub = false; // debug only
bool m_belowNormalPriority = false; // internal, dependent on other fields and specific code path
}; };
class QTCREATOR_UTILS_EXPORT ProcessInterface : public QObject
{
Q_OBJECT
public:
ProcessInterface(QObject *parent) : QObject(parent) {}
virtual void start() { defaultStart(); }
virtual void terminate() = 0;
virtual void kill() = 0;
virtual void close() = 0;
virtual QByteArray readAllStandardOutput() = 0;
virtual QByteArray readAllStandardError() = 0;
virtual qint64 write(const QByteArray &data) = 0;
virtual qint64 processId() const = 0;
virtual QProcess::ProcessState state() const = 0;
virtual int exitCode() const = 0;
virtual QProcess::ExitStatus exitStatus() const = 0;
virtual QProcess::ProcessError error() const = 0;
virtual QString errorString() const = 0;
virtual void setErrorString(const QString &str) = 0;
virtual bool waitForStarted(int msecs) = 0;
virtual bool waitForReadyRead(int msecs) = 0;
virtual bool waitForFinished(int msecs) = 0;
virtual void kickoffProcess() { QTC_CHECK(false); }
virtual void interruptProcess() { QTC_CHECK(false); }
virtual qint64 applicationMainThreadID() const { QTC_CHECK(false); return -1; }
signals:
void started();
void finished();
void errorOccurred(QProcess::ProcessError error);
void readyReadStandardOutput();
void readyReadStandardError();
protected:
void defaultStart();
ProcessSetupData m_setup;
private:
virtual void doDefaultStart(const QString &program, const QStringList &arguments)
{ Q_UNUSED(program) Q_UNUSED(arguments) QTC_CHECK(false); }
bool dissolveCommand(QString *program, QStringList *arguments);
bool ensureProgramExists(const QString &program);
friend class QtcProcess;
};
using ExitCodeInterpreter = std::function<QtcProcess::Result(int /*exitCode*/)>; using ExitCodeInterpreter = std::function<QtcProcess::Result(int /*exitCode*/)>;
} // namespace Utils } // namespace Utils