diff --git a/src/plugins/docker/dockerdevice.cpp b/src/plugins/docker/dockerdevice.cpp index 90c90d896cc..c4274da06f8 100644 --- a/src/plugins/docker/dockerdevice.cpp +++ b/src/plugins/docker/dockerdevice.cpp @@ -127,6 +127,7 @@ public: void updateContainerAccess(); void changeMounts(QStringList newMounts); + bool ensureReachable(const FilePath &other); void shutdown(); QString containerId() { return m_container; } @@ -150,11 +151,18 @@ private: void stopCurrentContainer(); void fetchSystemEnviroment(); + bool addTemporaryMount(const FilePath &path, const FilePath &containerPath); + DockerDevice *const q; DockerDeviceData m_data; DockerSettings *m_settings; - // For local file access + struct TemporaryMountInfo { + FilePath path; + FilePath containerPath; + }; + + QList m_temporaryMounts; std::unique_ptr m_shell; @@ -469,6 +477,12 @@ bool DockerDevicePrivate::createContainer() dockerCreate.addArgs({"-v", q->debugDumperPath().toUserOutput() + ':' + dumperPath.path()}); q->setDebugDumperPath(dumperPath); + for (const auto &[path, containerPath] : qAsConst(m_temporaryMounts)) { + if (path.isEmpty()) + continue; + dockerCreate.addArgs({"-v", path.nativePath() + ':' + containerPath.nativePath()}); + } + dockerCreate.addArgs({"--entrypoint", "/bin/sh"}); dockerCreate.addArg(m_data.repoAndTag()); @@ -846,6 +860,16 @@ bool DockerDevice::setPermissions(const FilePath &filePath, QFileDevice::Permiss return false; } +bool DockerDevice::ensureReachable(const FilePath &other) const +{ + if (other.needsDevice()) + return false; + + if (other.isDir()) + return d->ensureReachable(other); + return d->ensureReachable(other.parentDir()); +} + void DockerDevice::iterateWithFind(const FilePath &filePath, const std::function &callBack, const FileFilter &filter) const @@ -1256,6 +1280,21 @@ void DockerDeviceFactory::shutdownExistingDevices() } } +bool DockerDevicePrivate::addTemporaryMount(const FilePath &path, const FilePath &containerPath) +{ + bool alreadyAdded = anyOf(m_temporaryMounts, + [containerPath](const TemporaryMountInfo &info) { + return info.containerPath == containerPath; + }); + if (alreadyAdded) + return false; + + qCDebug(dockerDeviceLog) << "Adding temporary mount:" << path; + m_temporaryMounts.append({path, containerPath}); + stopCurrentContainer(); // Force re-start with new mounts. + return true; +} + Environment DockerDevicePrivate::environment() { if (!m_cachedEnviroment.isValid()) @@ -1281,6 +1320,26 @@ void DockerDevicePrivate::changeMounts(QStringList newMounts) } } +bool DockerDevicePrivate::ensureReachable(const FilePath &other) +{ + for (const QString &mount : m_data.mounts) { + const FilePath fMount = FilePath::fromString(mount); + if (other.isChildOf(fMount)) + return true; + } + + for (const auto &[path, containerPath] : m_temporaryMounts) { + if (path.path() != containerPath.path()) + continue; + + if (other.isChildOf(path)) + return true; + } + + addTemporaryMount(other, other); + return true; +} + void DockerDevicePrivate::setData(const DockerDeviceData &data) { if (m_data != data) { diff --git a/src/plugins/docker/dockerdevice.h b/src/plugins/docker/dockerdevice.h index a3d4e398936..b1ddb18b418 100644 --- a/src/plugins/docker/dockerdevice.h +++ b/src/plugins/docker/dockerdevice.h @@ -5,9 +5,10 @@ #include "dockersettings.h" +#include + #include #include -#include #include @@ -20,17 +21,11 @@ class DockerDeviceData public: bool operator==(const DockerDeviceData &other) const { - return imageId == other.imageId - && repo == other.repo - && tag == other.tag - && useLocalUidGid == other.useLocalUidGid - && mounts == other.mounts; + return imageId == other.imageId && repo == other.repo && tag == other.tag + && useLocalUidGid == other.useLocalUidGid && mounts == other.mounts; } - bool operator!=(const DockerDeviceData &other) const - { - return !(*this == other); - } + bool operator!=(const DockerDeviceData &other) const { return !(*this == other); } // Used for "docker run" QString repoAndTag() const @@ -49,7 +44,7 @@ public: QString tag; QString size; bool useLocalUidGid = true; - QStringList mounts = { Core::DocumentManager::projectsDirectory().toString() }; + QStringList mounts = {Core::DocumentManager::projectsDirectory().toString()}; }; class DockerDevice : public ProjectExplorer::IDevice @@ -63,7 +58,10 @@ public: void shutdown(); - static Ptr create(DockerSettings *settings, const DockerDeviceData &data) { return Ptr(new DockerDevice(settings, data)); } + static Ptr create(DockerSettings *settings, const DockerDeviceData &data) + { + return Ptr(new DockerDevice(settings, data)); + } ProjectExplorer::IDeviceWidget *createWidget() override; QList validate() const override; @@ -110,7 +108,9 @@ public: QDateTime lastModified(const Utils::FilePath &filePath) const override; qint64 fileSize(const Utils::FilePath &filePath) const override; QFileDevice::Permissions permissions(const Utils::FilePath &filePath) const override; - bool setPermissions(const Utils::FilePath &filePath, QFileDevice::Permissions permissions) const override; + bool setPermissions(const Utils::FilePath &filePath, + QFileDevice::Permissions permissions) const override; + bool ensureReachable(const Utils::FilePath &other) const override; Utils::Environment systemEnvironment() const override; @@ -148,9 +148,9 @@ public: private: QMutex m_deviceListMutex; - std::vector > m_existingDevices; + std::vector> m_existingDevices; }; -} // Docker::Internal +} // namespace Docker::Internal Q_DECLARE_METATYPE(Docker::Internal::DockerDeviceData)