aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/docker/dockerdevice.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/docker/dockerdevice.cpp')
-rw-r--r--src/plugins/docker/dockerdevice.cpp371
1 files changed, 215 insertions, 156 deletions
diff --git a/src/plugins/docker/dockerdevice.cpp b/src/plugins/docker/dockerdevice.cpp
index 2a955f131fe..2dd2a589f72 100644
--- a/src/plugins/docker/dockerdevice.cpp
+++ b/src/plugins/docker/dockerdevice.cpp
@@ -17,6 +17,7 @@
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/devicesupport/devicemanager.h>
#include <projectexplorer/devicesupport/idevicewidget.h>
+#include <projectexplorer/devicesupport/processlist.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/kitmanager.h>
#include <projectexplorer/project.h>
@@ -43,11 +44,12 @@
#include <utils/overridecursor.h>
#include <utils/pathlisteditor.h>
#include <utils/port.h>
+#include <utils/process.h>
#include <utils/processinterface.h>
#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
#include <utils/sortfiltermodel.h>
#include <utils/temporaryfile.h>
+#include <utils/terminalhooks.h>
#include <utils/treemodel.h>
#include <utils/utilsicons.h>
@@ -95,16 +97,16 @@ public:
{}
private:
- void setupShellProcess(QtcProcess *shellProcess) final
+ void setupShellProcess(Process *shellProcess) final
{
- shellProcess->setCommand({m_settings->dockerBinaryPath.filePath(),
+ shellProcess->setCommand({m_settings->dockerBinaryPath(),
{"container", "start", "-i", "-a", m_containerId}});
}
CommandLine createFallbackCommand(const CommandLine &cmdLine)
{
CommandLine result = cmdLine;
- result.setExecutable(cmdLine.executable().onDevice(m_devicePath));
+ result.setExecutable(m_devicePath.withNewPath(cmdLine.executable().path()));
return result;
}
@@ -124,7 +126,6 @@ public:
RunResult runInShell(const CommandLine &cmdLine,
const QByteArray &stdInData) const override;
QString mapToDevicePath(const QString &hostPath) const override;
- OsType osType(const FilePath &filePath) const override;
DockerDevicePrivate *m_dev = nullptr;
};
@@ -142,7 +143,7 @@ public:
RunResult runInShell(const CommandLine &cmd, const QByteArray &stdInData = {});
- void updateContainerAccess();
+ bool updateContainerAccess();
void changeMounts(QStringList newMounts);
bool ensureReachable(const FilePath &other);
void shutdown();
@@ -160,15 +161,17 @@ public:
Environment environment();
CommandLine withDockerExecCmd(const CommandLine &cmd,
- Environment *env = nullptr,
- FilePath *workDir = nullptr,
- bool interactive = false);
+ const std::optional<Environment> &env = std::nullopt,
+ const std::optional<FilePath> &workDir = std::nullopt,
+ bool interactive = false,
+ bool withPty = false,
+ bool withMarker = true);
bool prepareForBuild(const Target *target);
Tasks validateMounts() const;
bool createContainer();
- void startContainer();
+ bool startContainer();
void stopCurrentContainer();
void fetchSystemEnviroment();
@@ -183,6 +186,8 @@ public:
QStringList createMountArgs() const;
+ bool isImageAvailable() const;
+
DockerDevice *const q;
DockerDeviceData m_data;
DockerSettings *m_settings;
@@ -221,7 +226,7 @@ private:
// as this object is alive.
IDevice::ConstPtr m_device;
- QtcProcess m_process;
+ Process m_process;
qint64 m_remotePID = 0;
bool m_hasReceivedFirstOutput = false;
};
@@ -231,43 +236,66 @@ DockerProcessImpl::DockerProcessImpl(IDevice::ConstPtr device, DockerDevicePriva
, m_device(std::move(device))
, m_process(this)
{
- connect(&m_process, &QtcProcess::started, this, [this] {
+ connect(&m_process, &Process::started, this, [this] {
qCDebug(dockerDeviceLog) << "Process started:" << m_process.commandLine();
- });
- connect(&m_process, &QtcProcess::readyReadStandardOutput, this, [this] {
- if (!m_hasReceivedFirstOutput) {
- QByteArray output = m_process.readAllRawStandardOutput();
- qsizetype idx = output.indexOf('\n');
- QByteArray firstLine = output.left(idx);
- QByteArray rest = output.mid(idx + 1);
- qCDebug(dockerDeviceLog)
- << "Process first line received:" << m_process.commandLine() << firstLine;
- if (firstLine.startsWith("__qtc")) {
- bool ok = false;
- m_remotePID = firstLine.mid(5, firstLine.size() - 5 - 5).toLongLong(&ok);
-
- if (ok)
- emit started(m_remotePID);
-
- if (rest.size() > 0)
- emit readyRead(rest, {});
-
- m_hasReceivedFirstOutput = true;
- return;
- }
+ if (m_setup.m_ptyData.has_value()) {
+ m_hasReceivedFirstOutput = true;
+ emit started(m_process.processId(), m_process.applicationMainThreadId());
}
- emit readyRead(m_process.readAllRawStandardOutput(), {});
});
- connect(&m_process, &QtcProcess::readyReadStandardError, this, [this] {
- emit readyRead({}, m_process.readAllRawStandardError());
+ connect(&m_process, &Process::readyReadStandardOutput, this, [this] {
+ if (m_hasReceivedFirstOutput)
+ emit readyRead(m_process.readAllRawStandardOutput(), {});
+
+ QByteArray output = m_process.readAllRawStandardOutput();
+ qsizetype idx = output.indexOf('\n');
+ QByteArray firstLine = output.left(idx).trimmed();
+ QByteArray rest = output.mid(idx + 1);
+ qCDebug(dockerDeviceLog) << "Process first line received:" << m_process.commandLine()
+ << firstLine;
+
+ if (!firstLine.startsWith("__qtc"))
+ return;
+
+ bool ok = false;
+ m_remotePID = firstLine.mid(5, firstLine.size() - 5 - 5).toLongLong(&ok);
+
+ if (ok)
+ emit started(m_remotePID);
+
+ // In case we already received some error output, send it now.
+ const QByteArray stdErr = m_process.readAllRawStandardError();
+ if (rest.size() > 0 || stdErr.size() > 0)
+ emit readyRead(rest, stdErr);
+
+ m_hasReceivedFirstOutput = true;
});
- connect(&m_process, &QtcProcess::done, this, [this] {
+ connect(&m_process, &Process::readyReadStandardError, this, [this] {
+ if (m_remotePID)
+ emit readyRead({}, m_process.readAllRawStandardError());
+ });
+
+ connect(&m_process, &Process::done, this, [this] {
qCDebug(dockerDeviceLog) << "Process exited:" << m_process.commandLine()
<< "with code:" << m_process.resultData().m_exitCode;
- emit done(m_process.resultData());
+
+ Utils::ProcessResultData resultData = m_process.resultData();
+
+ if (m_remotePID == 0 && !m_hasReceivedFirstOutput) {
+ resultData.m_error = QProcess::FailedToStart;
+ qCWarning(dockerDeviceLog) << "Process failed to start:" << m_process.commandLine();
+ QByteArray stdOut = m_process.readAllRawStandardOutput();
+ QByteArray stdErr = m_process.readAllRawStandardError();
+ if (!stdOut.isEmpty())
+ qCWarning(dockerDeviceLog) << "stdout:" << stdOut;
+ if (!stdErr.isEmpty())
+ qCWarning(dockerDeviceLog) << "stderr:" << stdErr;
+ }
+
+ emit done(resultData);
});
}
@@ -282,23 +310,30 @@ void DockerProcessImpl::start()
m_process.setProcessImpl(m_setup.m_processImpl);
m_process.setProcessMode(m_setup.m_processMode);
m_process.setTerminalMode(m_setup.m_terminalMode);
+ m_process.setPtyData(m_setup.m_ptyData);
m_process.setReaperTimeout(m_setup.m_reaperTimeout);
m_process.setWriteData(m_setup.m_writeData);
m_process.setProcessChannelMode(m_setup.m_processChannelMode);
m_process.setExtraData(m_setup.m_extraData);
m_process.setStandardInputFile(m_setup.m_standardInputFile);
m_process.setAbortOnMetaChars(m_setup.m_abortOnMetaChars);
+ m_process.setCreateConsoleOnWindows(m_setup.m_createConsoleOnWindows);
if (m_setup.m_lowPriority)
m_process.setLowPriority();
+ const bool inTerminal = m_setup.m_terminalMode != TerminalMode::Off
+ || m_setup.m_ptyData.has_value();
+
const bool interactive = m_setup.m_processMode == ProcessMode::Writer
- || !m_setup.m_writeData.isEmpty();
+ || !m_setup.m_writeData.isEmpty() || inTerminal;
- const CommandLine fullCommandLine = m_devicePrivate
- ->withDockerExecCmd(m_setup.m_commandLine,
- &m_setup.m_environment,
- &m_setup.m_workingDirectory,
- interactive);
+ const CommandLine fullCommandLine
+ = m_devicePrivate->withDockerExecCmd(m_setup.m_commandLine,
+ m_setup.m_environment,
+ m_setup.m_workingDirectory,
+ interactive,
+ inTerminal,
+ !m_process.ptyData().has_value());
m_process.setCommand(fullCommandLine);
m_process.start();
@@ -311,14 +346,26 @@ qint64 DockerProcessImpl::write(const QByteArray &data)
void DockerProcessImpl::sendControlSignal(ControlSignal controlSignal)
{
- QTC_ASSERT(m_remotePID, return);
- if (controlSignal == ControlSignal::CloseWriteChannel) {
- m_process.closeWriteChannel();
- return;
+ if (!m_setup.m_ptyData.has_value()) {
+ QTC_ASSERT(m_remotePID, return);
+ if (controlSignal == ControlSignal::CloseWriteChannel) {
+ m_process.closeWriteChannel();
+ return;
+ }
+ const int signal = controlSignalToInt(controlSignal);
+ m_devicePrivate->runInShell(
+ {"kill", {QString("-%1").arg(signal), QString("%2").arg(m_remotePID)}});
+ } else {
+ // clang-format off
+ switch (controlSignal) {
+ case ControlSignal::Terminate: m_process.terminate(); break;
+ case ControlSignal::Kill: m_process.kill(); break;
+ case ControlSignal::Interrupt: m_process.interrupt(); break;
+ case ControlSignal::KickOff: m_process.kickoffProcess(); break;
+ case ControlSignal::CloseWriteChannel: break;
+ }
+ // clang-format on
}
- const int signal = controlSignalToInt(controlSignal);
- m_devicePrivate->runInShell(
- {"kill", {QString("-%1").arg(signal), QString("%2").arg(m_remotePID)}});
}
IDeviceWidget *DockerDevice::createWidget()
@@ -367,47 +414,40 @@ QString DockerDeviceFileAccess::mapToDevicePath(const QString &hostPath) const
return newPath;
}
-OsType DockerDeviceFileAccess::osType(const FilePath &filePath) const
-{
- QTC_ASSERT(m_dev, return UnixDeviceFileAccess::osType(filePath));
- return m_dev->q->osType();
-}
-
DockerDevice::DockerDevice(DockerSettings *settings, const DockerDeviceData &data)
: d(new DockerDevicePrivate(this, settings, data))
{
setFileAccess(&d->m_fileAccess);
setDisplayType(Tr::tr("Docker"));
- setOsType(OsTypeOtherUnix);
+ setOsType(OsTypeLinux);
setDefaultDisplayName(Tr::tr("Docker Image"));
-
+ setupId(IDevice::ManuallyAdded);
+ setType(Constants::DOCKER_DEVICE_TYPE);
+ setMachineType(IDevice::Hardware);
setDisplayName(Tr::tr("Docker Image \"%1\" (%2)").arg(data.repoAndTag()).arg(data.imageId));
setAllowEmptyCommand(true);
- setOpenTerminal([this, settings](const Environment &env, const FilePath &workingDir) {
+ setOpenTerminal([this](const Environment &env, const FilePath &workingDir) {
Q_UNUSED(env); // TODO: That's the runnable's environment in general. Use it via -e below.
- updateContainerAccess();
+ if (!updateContainerAccess())
+ return;
+
if (d->containerId().isEmpty()) {
MessageManager::writeDisrupting(Tr::tr("Error starting remote shell. No container."));
return;
}
- QtcProcess *proc = new QtcProcess(d);
- proc->setTerminalMode(TerminalMode::On);
+ Process proc;
+ proc.setTerminalMode(TerminalMode::Detached);
+ proc.setEnvironment(env);
+ proc.setWorkingDirectory(workingDir);
+ proc.setCommand({Terminal::defaultShellForDevice(rootPath()), {}});
+ proc.start();
- QObject::connect(proc, &QtcProcess::done, [proc] {
- if (proc->error() != QProcess::UnknownError && MessageManager::instance()) {
- MessageManager::writeDisrupting(
- Tr::tr("Error starting remote shell: %1").arg(proc->errorString()));
- }
- proc->deleteLater();
- });
-
- const QString wd = workingDir.isEmpty() ? "/" : workingDir.path();
- proc->setCommand({settings->dockerBinaryPath.filePath(),
- {"exec", "-it", "-w", wd, d->containerId(), "/bin/sh"}});
- proc->setEnvironment(Environment::systemEnvironment()); // The host system env. Intentional.
- proc->start();
+ if (proc.error() != QProcess::UnknownError && MessageManager::instance()) {
+ MessageManager::writeDisrupting(
+ Tr::tr("Error starting remote shell: %1").arg(proc.errorString()));
+ }
});
addDeviceAction({Tr::tr("Open Shell in Container"), [](const IDevice::Ptr &device, QWidget *) {
@@ -440,47 +480,58 @@ void DockerDevice::setData(const DockerDeviceData &data)
d->setData(data);
}
-void DockerDevice::updateContainerAccess() const
+bool DockerDevice::updateContainerAccess() const
{
- d->updateContainerAccess();
+ return d->updateContainerAccess();
}
CommandLine DockerDevicePrivate::withDockerExecCmd(const CommandLine &cmd,
- Environment *env,
- FilePath *workDir,
- bool interactive)
+ const std::optional<Environment> &env,
+ const std::optional<FilePath> &workDir,
+ bool interactive,
+ bool withPty,
+ bool withMarker)
{
if (!m_settings)
return {};
- updateContainerAccess();
+ if (!updateContainerAccess())
+ return {};
- CommandLine dockerCmd{m_settings->dockerBinaryPath.filePath(), {"exec"}};
+ CommandLine dockerCmd{m_settings->dockerBinaryPath(), {"exec"}};
if (interactive)
dockerCmd.addArg("-i");
+ if (withPty)
+ dockerCmd.addArg("-t");
+
if (env) {
- for (auto it = env->constBegin(); it != env->constEnd(); ++it) {
+ env->forEachEntry([&](const QString &key, const QString &value, bool) {
dockerCmd.addArg("-e");
- dockerCmd.addArg(env->key(it) + "=" + env->expandedValueForKey(env->key(it)));
- }
+ dockerCmd.addArg(key + "=" + env->expandVariables(value));
+ });
}
if (workDir && !workDir->isEmpty())
- dockerCmd.addArgs({"-w", workDir->path()});
+ dockerCmd.addArgs({"-w", q->rootPath().withNewMappedPath(*workDir).nativePath()});
dockerCmd.addArg(m_container);
+
dockerCmd.addArgs({"/bin/sh", "-c"});
CommandLine exec("exec");
- exec.addCommandLineAsArgs(cmd);
+ exec.addCommandLineAsArgs(cmd, CommandLine::Raw);
- CommandLine echo("echo");
- echo.addArgs("__qtc$$qtc__", CommandLine::Raw);
- echo.addCommandLineWithAnd(exec);
+ if (withMarker) {
+ CommandLine echo("echo");
+ echo.addArgs("__qtc$$qtc__", CommandLine::Raw);
+ echo.addCommandLineWithAnd(exec);
- dockerCmd.addCommandLineAsSingleArg(echo);
+ dockerCmd.addCommandLineAsSingleArg(echo);
+ } else {
+ dockerCmd.addCommandLineAsSingleArg(exec);
+ }
return dockerCmd;
}
@@ -494,10 +545,17 @@ void DockerDevicePrivate::stopCurrentContainer()
if (!DockerApi::isDockerDaemonAvailable(false).value_or(false))
return;
- m_shell.reset();
+ if (m_shell) {
+ // We have to disconnect the shell from the device, otherwise it will try to
+ // tell us about the container being stopped. Since that signal is emitted in a different
+ // thread, it would be delayed received by us when we might already have started
+ // a new shell.
+ m_shell->disconnect(this);
+ m_shell.reset();
+ }
- QtcProcess proc;
- proc.setCommand({m_settings->dockerBinaryPath.filePath(), {"container", "stop", m_container}});
+ Process proc;
+ proc.setCommand({m_settings->dockerBinaryPath(), {"container", "stop", m_container}});
m_container.clear();
@@ -598,14 +656,33 @@ QStringList DockerDevicePrivate::createMountArgs() const
return cmds;
}
+bool DockerDevicePrivate::isImageAvailable() const
+{
+ Process proc;
+ proc.setCommand(
+ {m_settings->dockerBinaryPath(),
+ {"image", "list", m_data.repoAndTag(), "--format", "{{.Repository}}:{{.Tag}}"}});
+ proc.runBlocking();
+ if (proc.result() != ProcessResult::FinishedWithSuccess)
+ return false;
+
+ if (proc.stdOut().trimmed() == m_data.repoAndTag())
+ return true;
+
+ return false;
+}
+
bool DockerDevicePrivate::createContainer()
{
if (!m_settings)
return false;
+ if (!isImageAvailable())
+ return false;
+
const QString display = HostOsInfo::isLinuxHost() ? QString(":0")
: QString("host.docker.internal:0");
- CommandLine dockerCreate{m_settings->dockerBinaryPath.filePath(),
+ CommandLine dockerCreate{m_settings->dockerBinaryPath(),
{"create",
"-i",
"--rm",
@@ -621,9 +698,6 @@ bool DockerDevicePrivate::createContainer()
if (m_data.useLocalUidGid)
dockerCreate.addArgs({"-u", QString("%1:%2").arg(getuid()).arg(getgid())});
#endif
- FilePath dumperPath = FilePath::fromString("/tmp/qtcreator/debugger");
- addTemporaryMount(Core::ICore::resourcePath("debugger/"), dumperPath);
- q->setDebugDumperPath(dumperPath);
dockerCreate.addArgs(createMountArgs());
@@ -636,7 +710,7 @@ bool DockerDevicePrivate::createContainer()
dockerCreate.addArg(m_data.repoAndTag());
qCDebug(dockerDeviceLog).noquote() << "RUNNING: " << dockerCreate.toUserOutput();
- QtcProcess createProcess;
+ Process createProcess;
createProcess.setCommand(dockerCreate);
createProcess.runBlocking();
@@ -655,20 +729,22 @@ bool DockerDevicePrivate::createContainer()
return true;
}
-void DockerDevicePrivate::startContainer()
+bool DockerDevicePrivate::startContainer()
{
if (!createContainer())
- return;
+ return false;
m_shell = std::make_unique<ContainerShell>(m_settings, m_container, q->rootPath());
connect(m_shell.get(), &DeviceShell::done, this, [this](const ProcessResultData &resultData) {
+ if (m_shell)
+ m_shell.release()->deleteLater();
+
if (resultData.m_error != QProcess::UnknownError
|| resultData.m_exitStatus == QProcess::NormalExit)
return;
qCWarning(dockerDeviceLog) << "Container shell encountered error:" << resultData.m_error;
- m_shell.release()->deleteLater();
DockerApi::recheckDockerDaemon();
MessageManager::writeFlashing(Tr::tr("Docker daemon appears to be not running. "
@@ -677,23 +753,25 @@ void DockerDevicePrivate::startContainer()
"or restart Qt Creator."));
});
- if (!m_shell->start()) {
- qCWarning(dockerDeviceLog) << "Container shell failed to start";
- }
+ if (m_shell->start())
+ return true;
+
+ qCWarning(dockerDeviceLog) << "Container shell failed to start";
+ return false;
}
-void DockerDevicePrivate::updateContainerAccess()
+bool DockerDevicePrivate::updateContainerAccess()
{
if (m_isShutdown)
- return;
+ return false;
if (DockerApi::isDockerDaemonAvailable(false).value_or(false) == false)
- return;
+ return false;
if (m_shell)
- return;
+ return true;
- startContainer();
+ return startContainer();
}
void DockerDevice::setMounts(const QStringList &mounts) const
@@ -750,36 +828,9 @@ ProcessInterface *DockerDevice::createProcessInterface() const
return new DockerProcessImpl(this->sharedFromThis(), d);
}
-bool DockerDevice::canAutoDetectPorts() const
+DeviceProcessList *DockerDevice::createProcessListModel(QObject *parent) const
{
- return true;
-}
-
-PortsGatheringMethod DockerDevice::portsGatheringMethod() const
-{
- return {[this](QAbstractSocket::NetworkLayerProtocol protocol) -> CommandLine {
- // We might encounter the situation that protocol is given IPv6
- // but the consumer of the free port information decides to open
- // an IPv4(only) port. As a result the next IPv6 scan will
- // report the port again as open (in IPv6 namespace), while the
- // same port in IPv4 namespace might still be blocked, and
- // re-use of this port fails.
- // GDBserver behaves exactly like this.
-
- Q_UNUSED(protocol)
-
- // /proc/net/tcp* covers /proc/net/tcp and /proc/net/tcp6
- return {filePath("sed"),
- "-e 's/.*: [[:xdigit:]]*:\\([[:xdigit:]]\\{4\\}\\).*/\\1/g' /proc/net/tcp*",
- CommandLine::Raw};
- },
-
- &Port::parseFromSedOutput};
-};
-
-DeviceProcessList *DockerDevice::createProcessListModel(QObject *) const
-{
- return nullptr;
+ return new ProcessList(sharedFromThis(), parent);
}
DeviceTester *DockerDevice::createDeviceTester() const
@@ -865,7 +916,8 @@ void DockerDevice::aboutToBeRemoved() const
void DockerDevicePrivate::fetchSystemEnviroment()
{
- updateContainerAccess();
+ if (!updateContainerAccess())
+ return;
if (m_shell && m_shell->state() == DeviceShell::State::Succeeded) {
const RunResult result = runInShell({"env", {}});
@@ -874,7 +926,7 @@ void DockerDevicePrivate::fetchSystemEnviroment()
return;
}
- QtcProcess proc;
+ Process proc;
proc.setCommand(withDockerExecCmd({"env", {}}));
proc.start();
proc.waitForFinished();
@@ -889,7 +941,8 @@ void DockerDevicePrivate::fetchSystemEnviroment()
RunResult DockerDevicePrivate::runInShell(const CommandLine &cmd, const QByteArray &stdInData)
{
- updateContainerAccess();
+ if (!updateContainerAccess())
+ return {};
QTC_ASSERT(m_shell, return {});
return m_shell->runInShell(cmd, stdInData);
}
@@ -985,6 +1038,7 @@ public:
using namespace Layouting;
+ // clang-format off
Column {
Stack {
statusLabel,
@@ -993,21 +1047,20 @@ public:
m_log,
errorLabel,
Row{showUnnamedContainers, m_buttons},
- }
- .attachTo(this);
-
+ }.attachTo(this);
+ // clang-format on
connect(m_buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(m_buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
m_buttons->button(QDialogButtonBox::Ok)->setEnabled(false);
- CommandLine cmd{m_settings->dockerBinaryPath.filePath(),
+ CommandLine cmd{m_settings->dockerBinaryPath(),
{"images", "--format", "{{.ID}}\\t{{.Repository}}\\t{{.Tag}}\\t{{.Size}}"}};
m_log->append(Tr::tr("Running \"%1\"\n").arg(cmd.toUserOutput()));
- m_process = new QtcProcess(this);
+ m_process = new Process(this);
m_process->setCommand(cmd);
- connect(m_process, &QtcProcess::readyReadStandardOutput, this, [this] {
+ connect(m_process, &Process::readyReadStandardOutput, this, [this] {
const QString out = m_process->readAllStandardOutput().trimmed();
m_log->append(out);
for (const QString &line : out.split('\n')) {
@@ -1026,12 +1079,12 @@ public:
m_log->append(Tr::tr("Done."));
});
- connect(m_process, &Utils::QtcProcess::readyReadStandardError, this, [this] {
+ connect(m_process, &Utils::Process::readyReadStandardError, this, [this] {
const QString out = Tr::tr("Error: %1").arg(m_process->cleanedStdErr());
m_log->append(Tr::tr("Error: %1").arg(out));
});
- connect(m_process, &QtcProcess::done, errorLabel, [errorLabel, this, statusLabel] {
+ connect(m_process, &Process::done, errorLabel, [errorLabel, this, statusLabel] {
delete statusLabel;
if (m_process->result() == ProcessResult::FinishedWithSuccess)
m_view->setEnabled(true);
@@ -1057,9 +1110,6 @@ public:
QTC_ASSERT(item, return {});
auto device = DockerDevice::create(m_settings, *item);
- device->setupId(IDevice::ManuallyAdded);
- device->setType(Constants::DOCKER_DEVICE_TYPE);
- device->setMachineType(IDevice::Hardware);
return device;
}
@@ -1072,7 +1122,7 @@ public:
QDialogButtonBox *m_buttons;
DockerSettings *m_settings;
- QtcProcess *m_process = nullptr;
+ Process *m_process = nullptr;
QString m_selectedId;
};
@@ -1186,16 +1236,25 @@ bool DockerDevicePrivate::ensureReachable(const FilePath &other)
const FilePath fMount = FilePath::fromString(mount);
if (other.isChildOf(fMount))
return true;
+
+ if (fMount == other)
+ return true;
}
for (const auto &[path, containerPath] : m_temporaryMounts) {
if (path.path() != containerPath.path())
continue;
+ if (path == other)
+ return true;
+
if (other.isChildOf(path))
return true;
}
+ if (q->filePath(other.path()).exists())
+ return false;
+
addTemporaryMount(other, other);
return true;
}