Utils: Move QtcProcess constructor setup data to shared setup data

This includes replacing DeviceProcess terminal handling with base
member.

Change-Id: Id1541bfce33c71dddc71b4816ad0b174dce3879c
Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
This commit is contained in:
hjk
2022-02-10 19:25:03 +01:00
parent 825c89987c
commit e2cb64471a
23 changed files with 119 additions and 87 deletions

View File

@@ -32,8 +32,9 @@
namespace QSsh {
SshProcess::SshProcess(Utils::ProcessMode processMode)
: Utils::QtcProcess(processMode)
{
setProcessMode(processMode);
Utils::Environment env = Utils::Environment::systemEnvironment();
if (SshSettings::askpassFilePath().exists()) {
env.set("SSH_ASKPASS", SshSettings::askpassFilePath().toUserOutput());

View File

@@ -215,6 +215,10 @@ public:
class ProcessSetupData
{
public:
QtcProcess::ProcessImpl m_processImpl = QtcProcess::DefaultImpl;
ProcessMode m_processMode = ProcessMode::Reader;
QtcProcess::TerminalMode m_terminalMode = QtcProcess::TerminalOff;
QString m_nativeArguments;
QString m_standardInputFile;
QString m_initialErrorString;
@@ -532,17 +536,6 @@ static QtcProcess::ProcessImpl defaultProcessImpl()
return QtcProcess::ProcessLauncherImpl;
}
static ProcessInterface *newProcessInstance(QObject *parent, const QtcProcess::Setup &setup)
{
if (setup.terminalMode != QtcProcess::TerminalOff)
return new TerminalImpl(parent, setup.processImpl, setup.terminalMode);
const QtcProcess::ProcessImpl impl = setup.processImpl == QtcProcess::DefaultImpl
? defaultProcessImpl() : setup.processImpl;
if (impl == QtcProcess::QProcessImpl)
return new QProcessImpl(parent, setup.processMode);
return new ProcessLauncherImpl(parent, setup.processMode);
}
class QtcProcessPrivate : public QObject
{
public:
@@ -552,19 +545,34 @@ public:
OtherFailure
};
explicit QtcProcessPrivate(QtcProcess *parent, const QtcProcess::Setup &processSetup)
explicit QtcProcessPrivate(QtcProcess *parent)
: QObject(parent)
, q(parent)
, m_processSetup(processSetup)
{}
void setupNewProcessInstance()
{
const QtcProcess::ProcessImpl impl =
m_setup.m_processImpl == QtcProcess::DefaultImpl
? defaultProcessImpl()
: m_setup.m_processImpl;
if (m_setup.m_terminalMode != QtcProcess::TerminalOff)
m_process = new TerminalImpl(parent(), impl, m_setup.m_terminalMode);
else if (impl == QtcProcess::QProcessImpl)
m_process = new QProcessImpl(parent(), m_setup.m_processMode);
else
m_process = new ProcessLauncherImpl(parent(), m_setup.m_processMode);
m_process->m_setup = &m_setup;
}
void ensureProcessInstanceExists()
{
if (m_process)
return;
m_process = newProcessInstance(parent(), m_processSetup);
m_process->m_setup = &m_setup;
setupNewProcessInstance();
connect(m_process, &ProcessInterface::started,
q, &QtcProcess::started);
@@ -691,7 +699,6 @@ public:
QtcProcess *q;
ProcessInterface *m_process = nullptr;
const QtcProcess::Setup m_processSetup;
CommandLine m_commandLine;
FilePath m_workingDirectory;
Environment m_environment;
@@ -752,9 +759,9 @@ QtcProcess::Result QtcProcessPrivate::interpretExitCode(int exitCode)
\sa Utils::ProcessArgs
*/
QtcProcess::QtcProcess(const Setup &setup, QObject *parent)
QtcProcess::QtcProcess(QObject *parent)
: QObject(parent),
d(new QtcProcessPrivate(this, setup))
d(new QtcProcessPrivate(this))
{
static int qProcessExitStatusMeta = qRegisterMetaType<QProcess::ExitStatus>();
static int qProcessProcessErrorMeta = qRegisterMetaType<QProcess::ProcessError>();
@@ -762,23 +769,34 @@ QtcProcess::QtcProcess(const Setup &setup, QObject *parent)
Q_UNUSED(qProcessProcessErrorMeta)
}
QtcProcess::QtcProcess(QObject *parent)
: QtcProcess({}, parent)
{}
QtcProcess::~QtcProcess()
{
delete d;
}
void QtcProcess::setProcessImpl(ProcessImpl processImpl)
{
d->m_setup.m_processImpl = processImpl;
}
ProcessMode QtcProcess::processMode() const
{
return d->m_processSetup.processMode;
return d->m_setup.m_processMode;
}
void QtcProcess::setTerminalMode(TerminalMode mode)
{
d->m_setup.m_terminalMode = mode;
}
QtcProcess::TerminalMode QtcProcess::terminalMode() const
{
return d->m_processSetup.terminalMode;
return d->m_setup.m_terminalMode;
}
void QtcProcess::setProcessMode(ProcessMode processMode)
{
d->m_setup.m_processMode = processMode;
}
void QtcProcess::setEnvironment(const Environment &env)

View File

@@ -60,6 +60,9 @@ class QTCREATOR_UTILS_EXPORT QtcProcess : public QObject
Q_OBJECT
public:
QtcProcess(QObject *parent = nullptr);
~QtcProcess();
enum ProcessImpl {
QProcessImpl,
ProcessLauncherImpl,
@@ -74,24 +77,6 @@ public:
TerminalOn = TerminalRun // default mode for ON
};
struct Setup {
Setup() {}
Setup(ProcessImpl processImpl) : processImpl(processImpl) {}
Setup(ProcessMode processMode) : processMode(processMode) {}
Setup(TerminalMode terminalMode) : terminalMode(terminalMode) {}
ProcessImpl processImpl = DefaultImpl;
ProcessMode processMode = ProcessMode::Reader;
TerminalMode terminalMode = TerminalOff;
};
QtcProcess(const Setup &setup = {}, QObject *parent = nullptr);
QtcProcess(QObject *parent);
~QtcProcess();
ProcessMode processMode() const;
TerminalMode terminalMode() const;
enum Result {
// Finished successfully. Unless an ExitCodeInterpreter is set
// this corresponds to a return code 0.
@@ -109,6 +94,15 @@ public:
Hang
};
void setProcessImpl(ProcessImpl processImpl);
void setTerminalMode(TerminalMode mode);
bool usesTerminal() const { return terminalMode() != TerminalOff; }
TerminalMode terminalMode() const;
void setProcessMode(ProcessMode processMode);
ProcessMode processMode() const;
void setEnvironment(const Environment &env);
void unsetEnvironment();
const Environment &environment() const;

View File

@@ -126,8 +126,10 @@ public:
TerminalProcessPrivate(QObject *parent, QtcProcess::ProcessImpl processImpl,
QtcProcess::TerminalMode terminalMode)
: m_terminalMode(terminalMode)
, m_process(processImpl, parent)
{}
, m_process(parent)
{
m_process.setProcessImpl(processImpl);
}
const QtcProcess::TerminalMode m_terminalMode;
FilePath m_workingDir;

View File

@@ -118,7 +118,8 @@ static CreateAvdInfo createAvdCommand(const AndroidConfig &config, const CreateA
const FilePath avdManagerTool = config.avdManagerToolPath();
qCDebug(avdManagerLog)
<< "Running AVD Manager command:" << CommandLine(avdManagerTool, arguments).toUserOutput();
QtcProcess proc(ProcessMode::Writer);
QtcProcess proc;
proc.setProcessMode(ProcessMode::Writer);
proc.setEnvironment(AndroidConfigurations::toolsEnvironment(config));
proc.setCommand({avdManagerTool, arguments});
proc.start();

View File

@@ -1017,9 +1017,12 @@ void AndroidSdkManagerPrivate::getPendingLicense(SdkCmdFutureInterface &fi)
{
fi.setProgressRange(0, 100);
fi.setProgressValue(0);
AndroidSdkManager::OperationOutput result;
result.type = AndroidSdkManager::LicenseWorkflow;
QtcProcess licenseCommand(ProcessMode::Writer);
QtcProcess licenseCommand;
licenseCommand.setProcessMode(ProcessMode::Writer);
licenseCommand.setEnvironment(AndroidConfigurations::toolsEnvironment(m_config));
bool reviewingLicenses = false;
licenseCommand.setCommand(CommandLine(m_config.sdkManagerToolPath(), {"--licenses", sdkRootArg(m_config)}));

View File

@@ -182,9 +182,10 @@ void addCdbOptionPages(QList<Core::IOptionsPage *> *opts)
CdbEngine::CdbEngine() :
m_tokenPrefix("<token>"),
m_process(ProcessMode::Writer),
m_extensionCommandPrefix("!" QT_CREATOR_CDB_EXT ".")
{
m_process.setProcessMode(ProcessMode::Writer);
setObjectName("CdbEngine");
setDebuggerName("CDB");

View File

@@ -145,8 +145,9 @@ const char tracepointCapturePropertyName[] = "GDB.TracepointCapture";
///////////////////////////////////////////////////////////////////////
GdbEngine::GdbEngine()
: m_gdbProc(ProcessMode::Writer)
{
m_gdbProc.setProcessMode(ProcessMode::Writer);
setObjectName("GdbEngine");
setDebuggerName("GDB");

View File

@@ -82,8 +82,9 @@ static int &currentToken()
///////////////////////////////////////////////////////////////////////
LldbEngine::LldbEngine()
: m_lldbProc(ProcessMode::Writer)
{
m_lldbProc.setProcessMode(ProcessMode::Writer);
setObjectName("LldbEngine");
setDebuggerName("LLDB");

View File

@@ -63,8 +63,10 @@ using namespace Utils;
namespace Debugger {
namespace Internal {
PdbEngine::PdbEngine() : m_proc(ProcessMode::Writer)
PdbEngine::PdbEngine()
{
m_proc.setProcessMode(ProcessMode::Writer);
setObjectName("PdbEngine");
setDebuggerName("PDB");
}

View File

@@ -194,9 +194,10 @@ void TerminalRunner::start()
QTC_ASSERT(!m_stubProc, reportFailure({}); return);
Runnable stub = m_stubRunnable();
const QtcProcess::TerminalMode terminalMode = HostOsInfo::isWindowsHost()
? QtcProcess::TerminalSuspend : QtcProcess::TerminalDebug;
m_stubProc = new QtcProcess(terminalMode, this);
m_stubProc = new QtcProcess(this);
m_stubProc->setTerminalMode(HostOsInfo::isWindowsHost()
? QtcProcess::TerminalSuspend : QtcProcess::TerminalDebug);
connect(m_stubProc, &QtcProcess::errorOccurred,
this, &TerminalRunner::stubError);
connect(m_stubProc, &QtcProcess::started,

View File

@@ -112,8 +112,9 @@ public:
DockerDeviceProcess::DockerDeviceProcess(const QSharedPointer<const IDevice> &device,
QObject *parent)
: DeviceProcess(device, ProcessMode::Writer, parent)
: DeviceProcess(device, parent)
{
setProcessMode(ProcessMode::Writer);
}
void DockerDeviceProcess::start(const Runnable &runnable)
@@ -537,7 +538,9 @@ DockerDevice::DockerDevice(const DockerDeviceData &data)
return;
}
QtcProcess *proc = new QtcProcess(QtcProcess::TerminalOn);
QtcProcess *proc = new QtcProcess;
proc->setTerminalMode(QtcProcess::TerminalOn);
QObject::connect(proc, &QtcProcess::finished, proc, &QObject::deleteLater);
QObject::connect(proc, &DeviceProcess::errorOccurred, [proc] {
@@ -897,7 +900,8 @@ void DockerDevicePrivate::startContainer()
CommandLine dockerRun{"docker", {"container" , "start", "-i", "-a", m_container}};
LOG("RUNNING: " << dockerRun.toUserOutput());
QPointer<QtcProcess> shell = new QtcProcess(ProcessMode::Writer);
QPointer<QtcProcess> shell = new QtcProcess;
shell->setProcessMode(ProcessMode::Writer);
connect(shell, &QtcProcess::finished, this, [this, shell] {
LOG("\nSHELL FINISHED\n");
QTC_ASSERT(shell, return);

View File

@@ -58,7 +58,8 @@ bool MergeTool::start(const FilePath &workingDirectory, const QStringList &files
Environment env = Environment::systemEnvironment();
env.set("LANG", "C");
env.set("LANGUAGE", "C");
m_process = new QtcProcess(ProcessMode::Writer);
m_process = new QtcProcess;
m_process->setProcessMode(ProcessMode::Writer);
m_process->setWorkingDirectory(workingDirectory);
m_process->setEnvironment(env);
m_process->setProcessChannelMode(QProcess::MergedChannels);

View File

@@ -88,8 +88,9 @@ void BaseClientInterface::parseData(const QByteArray &data)
}
StdIOClientInterface::StdIOClientInterface()
: m_process(ProcessMode::Writer)
{
m_process.setProcessMode(ProcessMode::Writer);
connect(&m_process, &QtcProcess::readyReadStandardError,
this, &StdIOClientInterface::readError);
connect(&m_process, &QtcProcess::readyReadStandardOutput,

View File

@@ -334,9 +334,9 @@ void ApplicationLauncherPrivate::start(const Runnable &runnable, const IDevice::
m_isLocal = local;
if (m_isLocal) {
const QtcProcess::TerminalMode terminalMode = m_useTerminal
? QtcProcess::TerminalOn : QtcProcess::TerminalOff;
m_localProcess.reset(new QtcProcess(terminalMode, this));
m_localProcess.reset(new QtcProcess(this));
m_localProcess->setTerminalMode(
m_useTerminal ? QtcProcess::TerminalOn : QtcProcess::TerminalOff);
m_localProcess->setProcessChannelMode(m_processChannelMode);
if (m_processChannelMode == QProcess::SeparateChannels) {
@@ -410,7 +410,8 @@ void ApplicationLauncherPrivate::start(const Runnable &runnable, const IDevice::
m_remoteExitStatus = QProcess::NormalExit;
m_deviceProcess = device->createProcess(this);
m_deviceProcess->setRunInTerminal(m_useTerminal);
m_deviceProcess->setTerminalMode(m_useTerminal ? QtcProcess::TerminalOn
: QtcProcess::TerminalOff);
connect(m_deviceProcess, &DeviceProcess::started,
q, &ApplicationLauncher::processStarted);
connect(m_deviceProcess, &DeviceProcess::readyReadStandardOutput,

View File

@@ -39,8 +39,9 @@ namespace Internal {
DesktopDeviceProcess::DesktopDeviceProcess(const QSharedPointer<const IDevice> &device,
QObject *parent)
: DeviceProcess(device, ProcessMode::Writer, parent)
: DeviceProcess(device, parent)
{
setProcessMode(ProcessMode::Writer);
}
void DesktopDeviceProcess::start(const Runnable &runnable)

View File

@@ -34,10 +34,8 @@ using namespace Utils;
namespace ProjectExplorer {
DeviceProcess::DeviceProcess(const IDevice::ConstPtr &device,
const QtcProcess::Setup &setup,
QObject *parent)
: QtcProcess(setup, parent), m_device(device)
DeviceProcess::DeviceProcess(const IDevice::ConstPtr &device, QObject *parent)
: QtcProcess(parent), m_device(device)
{
}

View File

@@ -44,19 +44,14 @@ public:
using Utils::QtcProcess::start;
virtual void start(const Runnable &runnable) = 0;
void setRunInTerminal(bool term) { m_runInTerminal = term; }
bool runInTerminal() const { return m_runInTerminal; }
protected:
explicit DeviceProcess(const QSharedPointer<const IDevice> &device,
const Utils::QtcProcess::Setup &setup,
QObject *parent = nullptr);
QSharedPointer<const IDevice> device() const;
private:
const QSharedPointer<const IDevice> m_device;
bool m_runInTerminal = false;
};
} // namespace ProjectExplorer

View File

@@ -71,9 +71,11 @@ public:
};
SshDeviceProcess::SshDeviceProcess(const IDevice::ConstPtr &device, QObject *parent)
: DeviceProcess(device, QtcProcess::TerminalOn, parent),
: DeviceProcess(device, parent),
d(std::make_unique<SshDeviceProcessPrivate>(this))
{
setTerminalMode(QtcProcess::TerminalOn);
// Hack: we rely on fact that below slots were called before any other external slots connected
// to this instance signals. That's why we don't re-emit them from inside our handlers since
// these signal will reach all other external slots anyway after our handlers are done.
@@ -96,7 +98,7 @@ SshDeviceProcess::~SshDeviceProcess()
void SshDeviceProcess::start(const Runnable &runnable)
{
QTC_ASSERT(d->state == SshDeviceProcessPrivate::Inactive, return);
QTC_ASSERT(runInTerminal() || !runnable.command.isEmpty(), return);
QTC_ASSERT(usesTerminal() || !runnable.command.isEmpty(), return);
d->setState(SshDeviceProcessPrivate::Connecting);
d->errorMessage.clear();
@@ -161,7 +163,7 @@ QProcess::ExitStatus SshDeviceProcess::exitStatus() const
int SshDeviceProcess::exitCode() const
{
return runInTerminal() ? QtcProcess::exitCode() : d->remoteProcess->exitCode();
return usesTerminal() ? QtcProcess::exitCode() : d->remoteProcess->exitCode();
}
QString SshDeviceProcess::errorString() const
@@ -189,14 +191,14 @@ void SshDeviceProcess::handleConnected()
QTC_ASSERT(d->state == SshDeviceProcessPrivate::Connecting, return);
d->setState(SshDeviceProcessPrivate::Connected);
d->remoteProcess = runInTerminal() && d->runnable.command.isEmpty()
d->remoteProcess = usesTerminal() && d->runnable.command.isEmpty()
? d->connection->createRemoteShell()
: d->connection->createRemoteProcess(fullCommandLine(d->runnable));
const QString display = d->displayName();
if (!display.isEmpty())
d->remoteProcess->requestX11Forwarding(display);
d->ignoreSelfSignals = !runInTerminal();
if (runInTerminal()) {
d->ignoreSelfSignals = !usesTerminal();
if (usesTerminal()) {
setAbortOnMetaChars(false);
setCommand(d->remoteProcess->fullLocalCommandLine(true));
QtcProcess::start();
@@ -337,7 +339,7 @@ void SshDeviceProcess::SshDeviceProcessPrivate::setState(SshDeviceProcess::SshDe
if (killOperation) {
killOperation->disconnect(q);
killOperation.clear();
if (q->runInTerminal())
if (q->usesTerminal())
QMetaObject::invokeMethod(q, &QtcProcess::stopProcess, Qt::QueuedConnection);
}
killTimer.stop();
@@ -352,7 +354,7 @@ void SshDeviceProcess::SshDeviceProcessPrivate::setState(SshDeviceProcess::SshDe
qint64 SshDeviceProcess::write(const QByteArray &data)
{
QTC_ASSERT(!runInTerminal(), return -1);
QTC_ASSERT(!usesTerminal(), return -1);
return d->remoteProcess->write(data);
}

View File

@@ -107,7 +107,8 @@ void openPythonRepl(QObject *parent, const FilePath &file, ReplType type)
};
const auto args = QStringList{"-i"} + replImportArgs(file, type);
auto process = new QtcProcess(QtcProcess::TerminalOn, parent);
auto process = new QtcProcess(parent);
process->setTerminalMode(QtcProcess::TerminalOn);
const FilePath pythonCommand = detectPython(file);
process->setCommand({pythonCommand, args});
process->setWorkingDirectory(workingDir(file));

View File

@@ -169,8 +169,11 @@ void QbsSession::initialize()
{
Environment env = Environment::systemEnvironment();
env.set("QT_FORCE_STDERR_LOGGING", "1");
d->packetReader = new PacketReader(this);
d->qbsProcess = new QtcProcess(ProcessMode::Writer, this);
d->qbsProcess = new QtcProcess(this);
d->qbsProcess->setProcessMode(ProcessMode::Writer);
d->qbsProcess->setEnvironment(env);
connect(d->qbsProcess, &QtcProcess::readyReadStandardOutput, this, [this] {
d->packetReader->handleData(d->qbsProcess->readAllStandardOutput());

View File

@@ -339,7 +339,7 @@ LinuxDevice::LinuxDevice()
if (env.size() > 0)
runnable.command.setExecutable("/bin/sh");
proc->setRunInTerminal(true);
proc->setTerminalMode(QtcProcess::TerminalOn);
proc->start(runnable);
});

View File

@@ -52,7 +52,7 @@ LinuxDeviceProcess::LinuxDeviceProcess(const QSharedPointer<const ProjectExplore
QByteArray LinuxDeviceProcess::readAllStandardOutput()
{
QByteArray output = SshDeviceProcess::readAllStandardOutput();
if (m_pidParsed || runInTerminal())
if (m_pidParsed || usesTerminal())
return output;
m_output.append(output);
@@ -96,14 +96,14 @@ QString LinuxDeviceProcess::fullCommandLine(const Runnable &runnable) const
cmd.addArgs("&&", CommandLine::Raw);
}
if (!runInTerminal())
if (!usesTerminal())
cmd.addArgs(QString("echo ") + pidMarker + "$$" + pidMarker + " && ", CommandLine::Raw);
const Environment &env = runnable.environment;
for (auto it = env.constBegin(); it != env.constEnd(); ++it)
cmd.addArgs(env.key(it) + "='" + env.expandedValueForKey(env.key(it)) + '\'', CommandLine::Raw);
if (!runInTerminal())
if (!usesTerminal())
cmd.addArg("exec");
cmd.addArg(runnable.command.executable().toString());