From a5b16f8137a8b14e849d08a7f90d323301773942 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 14 Jun 2021 08:33:44 +0200 Subject: [PATCH] Utils: Support remote FilePath::{lastModified,{remove,copy}File} And implement the Docker variant. Change-Id: Iee7cd0aaaf3d5c7dbb4ff995ac6889f31cb2f505 Reviewed-by: David Schulz --- src/libs/utils/fileutils.cpp | 23 ++++++++- src/libs/utils/fileutils.h | 7 ++- src/plugins/docker/dockerdevice.cpp | 47 +++++++++++++++++++ src/plugins/docker/dockerdevice.h | 3 ++ .../devicesupport/devicemanager.cpp | 19 ++++++++ .../projectexplorer/devicesupport/idevice.cpp | 26 +++++++++- .../projectexplorer/devicesupport/idevice.h | 3 ++ 7 files changed, 124 insertions(+), 4 deletions(-) diff --git a/src/libs/utils/fileutils.cpp b/src/libs/utils/fileutils.cpp index a5965590a7d..92c3ac819f7 100644 --- a/src/libs/utils/fileutils.cpp +++ b/src/libs/utils/fileutils.cpp @@ -1346,10 +1346,31 @@ uint FilePath::hash(uint seed) const QDateTime FilePath::lastModified() const { - QTC_CHECK(!needsDevice()); + if (needsDevice()) { + QTC_ASSERT(s_deviceHooks.lastModified, return {}); + return s_deviceHooks.lastModified(*this); + } return toFileInfo().lastModified(); } +bool FilePath::removeFile() const +{ + if (needsDevice()) { + QTC_ASSERT(s_deviceHooks.removeFile, return false); + return s_deviceHooks.removeFile(*this); + } + return QFile::remove(path()); +} + +bool FilePath::copyFile(const FilePath &target) const +{ + if (needsDevice()) { + QTC_ASSERT(s_deviceHooks.copyFile, return false); + return s_deviceHooks.copyFile(*this, target); + } + return QFile::copy(path(), target.path()); +} + QTextStream &operator<<(QTextStream &s, const FilePath &fn) { return s << fn.toString(); diff --git a/src/libs/utils/fileutils.h b/src/libs/utils/fileutils.h index 2c496bc46e6..0f5bcc72e9c 100644 --- a/src/libs/utils/fileutils.h +++ b/src/libs/utils/fileutils.h @@ -76,9 +76,12 @@ public: std::function ensureWritableDir; std::function createDir; std::function exists; + std::function removeFile; + std::function copyFile; std::function searchInPath; std::function(const FilePath &, const QStringList &, QDir::Filters)> dirEntries; std::function fileContents; + std::function lastModified; }; class QTCREATOR_UTILS_EXPORT FilePath @@ -155,6 +158,9 @@ public: bool isDir() const; bool isNewerThan(const QDateTime &timeStamp) const; + QDateTime lastModified() const; + bool removeFile() const; + bool copyFile(const FilePath &target) const; Qt::CaseSensitivity caseSensitivity() const; @@ -174,7 +180,6 @@ public: bool isEmpty() const; uint hash(uint seed) const; - QDateTime lastModified() const; // NOTE: Most FilePath operations on FilePath created from URL currently // do not work. Among the working are .toVariant() and .toUrl(). diff --git a/src/plugins/docker/dockerdevice.cpp b/src/plugins/docker/dockerdevice.cpp index ae14ccc8763..10603f1cd14 100644 --- a/src/plugins/docker/dockerdevice.cpp +++ b/src/plugins/docker/dockerdevice.cpp @@ -59,6 +59,7 @@ #include #include +#include #include #include #include @@ -788,6 +789,52 @@ bool DockerDevice::exists(const FilePath &filePath) const return exitCode == 0; } +bool DockerDevice::removeFile(const FilePath &filePath) const +{ + QTC_ASSERT(handlesFile(filePath), return false); + tryCreateLocalFileAccess(); + if (hasLocalFileAccess()) { + const FilePath localAccess = mapToLocalAccess(filePath); + const bool res = localAccess.removeFile(); + LOG("Remove? " << filePath.toUserOutput() << localAccess.toUserOutput() << res); + return res; + } + const CommandLine cmd("rm", {filePath.path()}); + const int exitCode = d->runSynchronously(cmd); + return exitCode == 0; +} + +bool DockerDevice::copyFile(const FilePath &filePath, const FilePath &target) const +{ + QTC_ASSERT(handlesFile(filePath), return false); + QTC_ASSERT(handlesFile(target), return false); + tryCreateLocalFileAccess(); + if (hasLocalFileAccess()) { + const FilePath localAccess = mapToLocalAccess(filePath); + const FilePath localTarget = mapToLocalAccess(target); + const bool res = localAccess.copyFile(localTarget); + LOG("Copy " << filePath.toUserOutput() << localAccess.toUserOutput() << localTarget << res); + return res; + } + const CommandLine cmd("cp", {filePath.path(), target.path()}); + const int exitCode = d->runSynchronously(cmd); + return exitCode == 0; +} + +QDateTime DockerDevice::lastModified(const FilePath &filePath) const +{ + QTC_ASSERT(handlesFile(filePath), return {}); + tryCreateLocalFileAccess(); + if (hasLocalFileAccess()) { + const FilePath localAccess = mapToLocalAccess(filePath); + const QDateTime res = localAccess.lastModified(); + LOG("Last modified? " << filePath.toUserOutput() << localAccess.toUserOutput() << res); + return res; + } + QTC_CHECK(false); + return {}; +} + FilePath DockerDevice::searchInPath(const FilePath &filePath) const { const QString path = filePath.path(); diff --git a/src/plugins/docker/dockerdevice.h b/src/plugins/docker/dockerdevice.h index f06217558d4..4b8a9fc6035 100644 --- a/src/plugins/docker/dockerdevice.h +++ b/src/plugins/docker/dockerdevice.h @@ -80,11 +80,14 @@ public: bool isWritableDirectory(const Utils::FilePath &filePath) const override; bool createDirectory(const Utils::FilePath &filePath) const override; bool exists(const Utils::FilePath &filePath) const override; + bool removeFile(const Utils::FilePath &filePath) const override; + bool copyFile(const Utils::FilePath &filePath, const Utils::FilePath &target) const override; Utils::FilePath searchInPath(const Utils::FilePath &filePath) const override; QList directoryEntries(const Utils::FilePath &filePath, const QStringList &nameFilters, QDir::Filters filters) const override; QByteArray fileContents(const Utils::FilePath &filePath, int limit) const override; + QDateTime lastModified(const Utils::FilePath &filePath) const override; void runProcess(Utils::QtcProcess &process) const override; Utils::Environment systemEnvironment() const override; diff --git a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp index cf5f27ece75..12c45f6ff83 100644 --- a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp +++ b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp @@ -39,6 +39,7 @@ #include #include +#include #include #include #include @@ -416,6 +417,18 @@ DeviceManager::DeviceManager(bool isInstance) : d(std::make_uniqueexists(filePath); }; + deviceHooks.removeFile = [](const FilePath &filePath) { + auto device = DeviceManager::deviceForPath(filePath); + QTC_ASSERT(device, return false); + return device->removeFile(filePath); + }; + + deviceHooks.copyFile = [](const FilePath &filePath, const FilePath &target) { + auto device = DeviceManager::deviceForPath(filePath); + QTC_ASSERT(device, return false); + return device->copyFile(filePath, target); + }; + deviceHooks.searchInPath = [](const FilePath &filePath) { auto device = DeviceManager::deviceForPath(filePath); QTC_ASSERT(device, return FilePath{}); @@ -435,6 +448,12 @@ DeviceManager::DeviceManager(bool isInstance) : d(std::make_uniquefileContents(filePath, maxSize); }; + deviceHooks.lastModified = [](const FilePath &filePath) { + auto device = DeviceManager::deviceForPath(filePath); + QTC_ASSERT(device, return QDateTime()); + return device->lastModified(filePath); + }; + FilePath::setDeviceFileHooks(deviceHooks); DeviceProcessHooks processHooks; diff --git a/src/plugins/projectexplorer/devicesupport/idevice.cpp b/src/plugins/projectexplorer/devicesupport/idevice.cpp index 90a144767c1..36af2cb2abe 100644 --- a/src/plugins/projectexplorer/devicesupport/idevice.cpp +++ b/src/plugins/projectexplorer/devicesupport/idevice.cpp @@ -43,6 +43,7 @@ #include #include +#include #include #include @@ -252,20 +253,35 @@ bool IDevice::ensureWritableDirectory(const FilePath &filePath) const return createDirectory(filePath); } -bool IDevice::createDirectory(const Utils::FilePath &filePath) const +bool IDevice::createDirectory(const FilePath &filePath) const { Q_UNUSED(filePath); QTC_CHECK(false); return false; } -bool IDevice::exists(const Utils::FilePath &filePath) const +bool IDevice::exists(const FilePath &filePath) const { Q_UNUSED(filePath); QTC_CHECK(false); return false; } +bool IDevice::removeFile(const FilePath &filePath) const +{ + Q_UNUSED(filePath); + QTC_CHECK(false); + return false; +} + +bool IDevice::copyFile(const FilePath &filePath, const FilePath &target) const +{ + Q_UNUSED(filePath); + Q_UNUSED(target); + QTC_CHECK(false); + return false; +} + FilePath IDevice::searchInPath(const FilePath &filePath) const { return Environment::systemEnvironment().searchInPath(filePath.path()); @@ -290,6 +306,12 @@ QByteArray IDevice::fileContents(const FilePath &filePath, int limit) const return {}; } +QDateTime IDevice::lastModified(const FilePath &filePath) const +{ + Q_UNUSED(filePath); + return {}; +} + void IDevice::runProcess(QtcProcess &process) const { Q_UNUSED(process); diff --git a/src/plugins/projectexplorer/devicesupport/idevice.h b/src/plugins/projectexplorer/devicesupport/idevice.h index 0fe627726eb..797540e0041 100644 --- a/src/plugins/projectexplorer/devicesupport/idevice.h +++ b/src/plugins/projectexplorer/devicesupport/idevice.h @@ -243,11 +243,14 @@ public: virtual bool ensureWritableDirectory(const Utils::FilePath &filePath) const; virtual bool createDirectory(const Utils::FilePath &filePath) const; virtual bool exists(const Utils::FilePath &filePath) const; + virtual bool removeFile(const Utils::FilePath &filePath) const; + virtual bool copyFile(const Utils::FilePath &filePath, const Utils::FilePath &target) const; virtual Utils::FilePath searchInPath(const Utils::FilePath &filePath) const; virtual QList directoryEntries(const Utils::FilePath &filePath, const QStringList &nameFilters, QDir::Filters filters) const; virtual QByteArray fileContents(const Utils::FilePath &filePath, int limit) const; + virtual QDateTime lastModified(const Utils::FilePath &filePath) const; virtual void runProcess(Utils::QtcProcess &process) const; virtual Utils::Environment systemEnvironment() const;