forked from qt-creator/qt-creator
Docker: Make GoCmdBridge optional
Change-Id: I29dbaafca3878b8130ae00eefc57881e35fd31e4 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
add_qtc_library(CmdBridgeClient
|
add_qtc_library(CmdBridgeClient
|
||||||
CONDITION TARGET CmdBridge
|
|
||||||
PUBLIC_DEPENDS Utils
|
PUBLIC_DEPENDS Utils
|
||||||
DEFINES GOBRIDGE_MAGIC_PACKET_MARKER=\"${GOBRIDGE_MAGIC_PACKET_MARKER}\"
|
DEFINES GOBRIDGE_MAGIC_PACKET_MARKER=\"${GOBRIDGE_MAGIC_PACKET_MARKER}\"
|
||||||
SOURCES
|
SOURCES
|
||||||
|
|||||||
@@ -294,7 +294,10 @@ expected_str<QFuture<Environment>> Client::start()
|
|||||||
auto func = it.value();
|
auto func = it.value();
|
||||||
auto id = it.key();
|
auto id = it.key();
|
||||||
it = j->map.erase(it);
|
it = j->map.erase(it);
|
||||||
func(QVariantMap{{"Type", "error"}, {"Id", id}, {"Error", "Process exited"}});
|
func(QVariantMap{
|
||||||
|
{"Type", "error"},
|
||||||
|
{"Id", id},
|
||||||
|
{"Error", QString("Process exited: %1").arg(d->process->errorString())}});
|
||||||
}
|
}
|
||||||
|
|
||||||
emit done(d->process->resultData());
|
emit done(d->process->resultData());
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
add_qtc_plugin(Docker
|
add_qtc_plugin(Docker
|
||||||
CONDITION TARGET CmdBridgeClient
|
|
||||||
DEPENDS Utils CmdBridgeClient
|
DEPENDS Utils CmdBridgeClient
|
||||||
PLUGIN_DEPENDS Core ProjectExplorer QtSupport
|
PLUGIN_DEPENDS Core ProjectExplorer QtSupport
|
||||||
SOURCES
|
SOURCES
|
||||||
|
|||||||
@@ -78,7 +78,6 @@
|
|||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QToolButton>
|
#include <QToolButton>
|
||||||
|
|
||||||
#include <numeric>
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
#ifdef Q_OS_UNIX
|
#ifdef Q_OS_UNIX
|
||||||
@@ -116,6 +115,31 @@ public:
|
|||||||
DockerDevicePrivate *m_dev = nullptr;
|
DockerDevicePrivate *m_dev = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DockerFallbackFileAccess : public UnixDeviceFileAccess
|
||||||
|
{
|
||||||
|
const FilePath m_rootPath;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DockerFallbackFileAccess(const FilePath &rootPath)
|
||||||
|
: m_rootPath(rootPath)
|
||||||
|
{}
|
||||||
|
|
||||||
|
RunResult runInShell(const CommandLine &cmdLine, const QByteArray &stdInData) const override
|
||||||
|
{
|
||||||
|
Process proc;
|
||||||
|
proc.setWriteData(stdInData);
|
||||||
|
proc.setCommand(
|
||||||
|
{m_rootPath.withNewPath(cmdLine.executable().path()), cmdLine.splitArguments()});
|
||||||
|
proc.runBlocking();
|
||||||
|
|
||||||
|
return {
|
||||||
|
proc.resultData().m_exitCode,
|
||||||
|
proc.readAllRawStandardOutput(),
|
||||||
|
proc.readAllRawStandardError(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void DockerDeviceSettings::fromMap(const Store &map)
|
void DockerDeviceSettings::fromMap(const Store &map)
|
||||||
{
|
{
|
||||||
DeviceSettings::fromMap(map);
|
DeviceSettings::fromMap(map);
|
||||||
@@ -333,7 +357,7 @@ public:
|
|||||||
|
|
||||||
std::optional<Environment> m_cachedEnviroment;
|
std::optional<Environment> m_cachedEnviroment;
|
||||||
bool m_isShutdown = false;
|
bool m_isShutdown = false;
|
||||||
std::unique_ptr<DockerDeviceFileAccess> m_fileAccess;
|
std::unique_ptr<DeviceFileAccess> m_fileAccess;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DockerProcessImpl : public ProcessInterface
|
class DockerProcessImpl : public ProcessInterface
|
||||||
@@ -373,8 +397,10 @@ DockerProcessImpl::DockerProcessImpl(IDevice::ConstPtr device, DockerDevicePriva
|
|||||||
});
|
});
|
||||||
|
|
||||||
connect(&m_process, &Process::readyReadStandardOutput, this, [this] {
|
connect(&m_process, &Process::readyReadStandardOutput, this, [this] {
|
||||||
if (m_hasReceivedFirstOutput)
|
if (m_hasReceivedFirstOutput) {
|
||||||
emit readyRead(m_process.readAllRawStandardOutput(), {});
|
emit readyRead(m_process.readAllRawStandardOutput(), {});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray output = m_process.readAllRawStandardOutput();
|
QByteArray output = m_process.readAllRawStandardOutput();
|
||||||
qsizetype idx = output.indexOf('\n');
|
qsizetype idx = output.indexOf('\n');
|
||||||
@@ -383,14 +409,30 @@ DockerProcessImpl::DockerProcessImpl(IDevice::ConstPtr device, DockerDevicePriva
|
|||||||
qCDebug(dockerDeviceLog) << "Process first line received:" << m_process.commandLine()
|
qCDebug(dockerDeviceLog) << "Process first line received:" << m_process.commandLine()
|
||||||
<< firstLine;
|
<< firstLine;
|
||||||
|
|
||||||
if (!firstLine.startsWith("__qtc"))
|
if (!firstLine.startsWith("__qtc")) {
|
||||||
|
emit done(ProcessResultData{
|
||||||
|
-1,
|
||||||
|
QProcess::ExitStatus::CrashExit,
|
||||||
|
QProcess::ProcessError::FailedToStart,
|
||||||
|
QString::fromUtf8(firstLine),
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
m_remotePID = firstLine.mid(5, firstLine.size() - 5 - 5).toLongLong(&ok);
|
m_remotePID = firstLine.mid(5, firstLine.size() - 5 - 5).toLongLong(&ok);
|
||||||
|
|
||||||
if (ok)
|
if (ok)
|
||||||
emit started(m_remotePID);
|
emit started(m_remotePID);
|
||||||
|
else {
|
||||||
|
emit done(ProcessResultData{
|
||||||
|
-1,
|
||||||
|
QProcess::ExitStatus::CrashExit,
|
||||||
|
QProcess::ProcessError::FailedToStart,
|
||||||
|
QString::fromUtf8(firstLine),
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// In case we already received some error output, send it now.
|
// In case we already received some error output, send it now.
|
||||||
const QByteArray stdErr = m_process.readAllRawStandardError();
|
const QByteArray stdErr = m_process.readAllRawStandardError();
|
||||||
@@ -479,8 +521,18 @@ void DockerProcessImpl::sendControlSignal(ControlSignal controlSignal)
|
|||||||
m_process.closeWriteChannel();
|
m_process.closeWriteChannel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
auto dfa = dynamic_cast<DockerDeviceFileAccess *>(m_device->fileAccess());
|
||||||
|
if (dfa) {
|
||||||
static_cast<DockerDeviceFileAccess *>(m_device->fileAccess())
|
static_cast<DockerDeviceFileAccess *>(m_device->fileAccess())
|
||||||
->signalProcess(m_remotePID, controlSignal);
|
->signalProcess(m_remotePID, controlSignal);
|
||||||
|
} else {
|
||||||
|
const int signal = controlSignalToInt(controlSignal);
|
||||||
|
Process p;
|
||||||
|
p.setCommand(
|
||||||
|
{m_device->rootPath().withNewPath("kill"),
|
||||||
|
{QString("-%1").arg(signal), QString("%2").arg(m_remotePID)}});
|
||||||
|
p.runBlocking();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
switch (controlSignal) {
|
switch (controlSignal) {
|
||||||
@@ -544,9 +596,14 @@ DockerDevice::DockerDevice(std::unique_ptr<DockerDeviceSettings> deviceSettings)
|
|||||||
setFileAccess([this]() -> DeviceFileAccess * {
|
setFileAccess([this]() -> DeviceFileAccess * {
|
||||||
if (!d->m_fileAccess) {
|
if (!d->m_fileAccess) {
|
||||||
auto fileAccess = std::make_unique<DockerDeviceFileAccess>(d);
|
auto fileAccess = std::make_unique<DockerDeviceFileAccess>(d);
|
||||||
QTC_ASSERT_EXPECTED(
|
auto initResult = fileAccess->init(rootPath().withNewPath("/tmp/_qtc_cmdbridge"));
|
||||||
fileAccess->init(rootPath().withNewPath("/tmp/_qtc_cmdbridge")), return nullptr);
|
QTC_CHECK(initResult);
|
||||||
|
if (initResult) {
|
||||||
d->m_fileAccess = std::move(fileAccess);
|
d->m_fileAccess = std::move(fileAccess);
|
||||||
|
return d->m_fileAccess.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
d->m_fileAccess = std::make_unique<DockerFallbackFileAccess>(rootPath());
|
||||||
}
|
}
|
||||||
return d->m_fileAccess.get();
|
return d->m_fileAccess.get();
|
||||||
});
|
});
|
||||||
@@ -649,11 +706,20 @@ CommandLine DockerDevicePrivate::withDockerExecCmd(const CommandLine &cmd,
|
|||||||
exec.addCommandLineAsArgs(cmd, CommandLine::Raw);
|
exec.addCommandLineAsArgs(cmd, CommandLine::Raw);
|
||||||
|
|
||||||
if (withMarker) {
|
if (withMarker) {
|
||||||
|
// Check the executable for existence.
|
||||||
|
CommandLine testType({"type", {}});
|
||||||
|
testType.addArg(cmd.executable().path());
|
||||||
|
testType.addArgs(">/dev/null", CommandLine::Raw);
|
||||||
|
|
||||||
|
// Send PID only if existence was confirmed, so we can correctly notify
|
||||||
|
// a failed start.
|
||||||
CommandLine echo("echo");
|
CommandLine echo("echo");
|
||||||
echo.addArgs("__qtc$$qtc__", CommandLine::Raw);
|
echo.addArgs("__qtc$$qtc__", CommandLine::Raw);
|
||||||
echo.addCommandLineWithAnd(exec);
|
echo.addCommandLineWithAnd(exec);
|
||||||
|
|
||||||
dockerCmd.addCommandLineAsSingleArg(echo);
|
testType.addCommandLineWithAnd(echo);
|
||||||
|
|
||||||
|
dockerCmd.addCommandLineAsSingleArg(testType);
|
||||||
} else {
|
} else {
|
||||||
dockerCmd.addCommandLineAsSingleArg(exec);
|
dockerCmd.addCommandLineAsSingleArg(exec);
|
||||||
}
|
}
|
||||||
@@ -763,6 +829,8 @@ QStringList DockerDevicePrivate::createMountArgs() const
|
|||||||
const Utils::expected_str<Utils::FilePath> cmdBridgePath = CmdBridge::Client::getCmdBridgePath(
|
const Utils::expected_str<Utils::FilePath> cmdBridgePath = CmdBridge::Client::getCmdBridgePath(
|
||||||
osAndArch.first, osAndArch.second, Core::ICore::libexecPath());
|
osAndArch.first, osAndArch.second, Core::ICore::libexecPath());
|
||||||
|
|
||||||
|
QTC_CHECK_EXPECTED(cmdBridgePath);
|
||||||
|
|
||||||
QStringList cmds;
|
QStringList cmds;
|
||||||
QList<MountPair> mounts;
|
QList<MountPair> mounts;
|
||||||
for (const FilePath &m : deviceSettings->mounts())
|
for (const FilePath &m : deviceSettings->mounts())
|
||||||
|
|||||||
Reference in New Issue
Block a user