From eb9416b35fd10cb0e20f66177bc36a10e2aebe8c Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 27 Jan 2023 16:16:46 +0100 Subject: [PATCH] RemoteLinux: Move GenericDirectUploadService implementation ... to genericdirectuploadstep.cpp and inline its pimpl. Change-Id: I50550ee4bbf4266fa191008c9db1696bae3f7f43 Reviewed-by: Qt CI Bot Reviewed-by: Christian Kandeler --- src/plugins/remotelinux/CMakeLists.txt | 1 - .../genericdirectuploadservice.cpp | 314 ------------------ .../remotelinux/genericdirectuploadservice.h | 38 --- .../remotelinux/genericdirectuploadstep.cpp | 303 ++++++++++++++++- src/plugins/remotelinux/remotelinux.qbs | 2 - 5 files changed, 301 insertions(+), 357 deletions(-) delete mode 100644 src/plugins/remotelinux/genericdirectuploadservice.cpp delete mode 100644 src/plugins/remotelinux/genericdirectuploadservice.h diff --git a/src/plugins/remotelinux/CMakeLists.txt b/src/plugins/remotelinux/CMakeLists.txt index c37c31d24af..dbb2b8e143d 100644 --- a/src/plugins/remotelinux/CMakeLists.txt +++ b/src/plugins/remotelinux/CMakeLists.txt @@ -5,7 +5,6 @@ add_qtc_plugin(RemoteLinux abstractremotelinuxdeploystep.cpp abstractremotelinuxdeploystep.h customcommanddeploystep.cpp customcommanddeploystep.h deploymenttimeinfo.cpp deploymenttimeinfo.h - genericdirectuploadservice.cpp genericdirectuploadservice.h genericdirectuploadstep.cpp genericdirectuploadstep.h genericlinuxdeviceconfigurationwidget.cpp genericlinuxdeviceconfigurationwidget.h genericlinuxdeviceconfigurationwizard.cpp genericlinuxdeviceconfigurationwizard.h diff --git a/src/plugins/remotelinux/genericdirectuploadservice.cpp b/src/plugins/remotelinux/genericdirectuploadservice.cpp deleted file mode 100644 index 6cd3c799376..00000000000 --- a/src/plugins/remotelinux/genericdirectuploadservice.cpp +++ /dev/null @@ -1,314 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "genericdirectuploadservice.h" - -#include "remotelinuxtr.h" - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -using namespace ProjectExplorer; -using namespace Utils; -using namespace Utils::Tasking; - -namespace RemoteLinux { -namespace Internal { - -const int MaxConcurrentStatCalls = 10; - -struct UploadStorage -{ - QList filesToUpload; -}; - -class GenericDirectUploadServicePrivate -{ -public: - GenericDirectUploadServicePrivate(GenericDirectUploadService *service) : q(service) {} - - QDateTime timestampFromStat(const DeployableFile &file, QtcProcess *statProc); - - using FilesToStat = std::function(UploadStorage *)>; - using StatEndHandler - = std::function; - TaskItem statTask(UploadStorage *storage, const DeployableFile &file, - StatEndHandler statEndHandler); - TaskItem statTree(const TreeStorage &storage, FilesToStat filesToStat, - StatEndHandler statEndHandler); - TaskItem uploadTask(const TreeStorage &storage); - TaskItem chmodTask(const DeployableFile &file); - TaskItem chmodTree(const TreeStorage &storage); - - GenericDirectUploadService *q = nullptr; - IncrementalDeployment incremental = IncrementalDeployment::NotSupported; - bool ignoreMissingFiles = false; - QList deployableFiles; -}; - -QList collectFilesToUpload(const DeployableFile &deployable) -{ - QList collected; - FilePath localFile = deployable.localFilePath(); - if (localFile.isDir()) { - const FilePaths files = localFile.dirEntries(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); - const QString remoteDir = deployable.remoteDirectory() + '/' + localFile.fileName(); - for (const FilePath &localFilePath : files) - collected.append(collectFilesToUpload(DeployableFile(localFilePath, remoteDir))); - } else { - collected << deployable; - } - return collected; -} - -} // namespace Internal - -using namespace Internal; - -GenericDirectUploadService::GenericDirectUploadService(QObject *parent) - : AbstractRemoteLinuxDeployService(parent), d(new GenericDirectUploadServicePrivate(this)) -{ -} - -GenericDirectUploadService::~GenericDirectUploadService() -{ - delete d; -} - -void GenericDirectUploadService::setDeployableFiles(const QList &deployableFiles) -{ - d->deployableFiles = deployableFiles; -} - -void GenericDirectUploadService::setIncrementalDeployment(IncrementalDeployment incremental) -{ - d->incremental = incremental; -} - -void GenericDirectUploadService::setIgnoreMissingFiles(bool ignoreMissingFiles) -{ - d->ignoreMissingFiles = ignoreMissingFiles; -} - -bool GenericDirectUploadService::isDeploymentNecessary() const -{ - QList collected; - for (int i = 0; i < d->deployableFiles.count(); ++i) - collected.append(collectFilesToUpload(d->deployableFiles.at(i))); - - QTC_CHECK(collected.size() >= d->deployableFiles.size()); - d->deployableFiles = collected; - return !d->deployableFiles.isEmpty(); -} - -QDateTime GenericDirectUploadServicePrivate::timestampFromStat(const DeployableFile &file, - QtcProcess *statProc) -{ - bool succeeded = false; - QString error; - if (statProc->error() == QProcess::FailedToStart) { - error = Tr::tr("Failed to start \"stat\": %1").arg(statProc->errorString()); - } else if (statProc->exitStatus() == QProcess::CrashExit) { - error = Tr::tr("\"stat\" crashed."); - } else if (statProc->exitCode() != 0) { - error = Tr::tr("\"stat\" failed with exit code %1: %2") - .arg(statProc->exitCode()).arg(statProc->cleanedStdErr()); - } else { - succeeded = true; - } - if (!succeeded) { - emit q->warningMessage(Tr::tr("Failed to retrieve remote timestamp for file \"%1\". " - "Incremental deployment will not work. Error message was: %2") - .arg(file.remoteFilePath(), error)); - return {}; - } - const QByteArray output = statProc->readAllRawStandardOutput().trimmed(); - const QString warningString(Tr::tr("Unexpected stat output for remote file \"%1\": %2") - .arg(file.remoteFilePath()).arg(QString::fromUtf8(output))); - if (!output.startsWith(file.remoteFilePath().toUtf8())) { - emit q->warningMessage(warningString); - return {}; - } - const QByteArrayList columns = output.mid(file.remoteFilePath().toUtf8().size() + 1).split(' '); - if (columns.size() < 14) { // Normal Linux stat: 16 columns in total, busybox stat: 15 columns - emit q->warningMessage(warningString); - return {}; - } - bool isNumber; - const qint64 secsSinceEpoch = columns.at(11).toLongLong(&isNumber); - if (!isNumber) { - emit q->warningMessage(warningString); - return {}; - } - return QDateTime::fromSecsSinceEpoch(secsSinceEpoch); -} - -TaskItem GenericDirectUploadServicePrivate::statTask(UploadStorage *storage, - const DeployableFile &file, - StatEndHandler statEndHandler) -{ - const auto setupHandler = [=](QtcProcess &process) { - // We'd like to use --format=%Y, but it's not supported by busybox. - process.setCommand({q->deviceConfiguration()->filePath("stat"), - {"-t", Utils::ProcessArgs::quoteArgUnix(file.remoteFilePath())}}); - }; - const auto endHandler = [=](const QtcProcess &process) { - QtcProcess *proc = const_cast(&process); - const QDateTime timestamp = timestampFromStat(file, proc); - statEndHandler(storage, file, timestamp); - }; - return Process(setupHandler, endHandler, endHandler); -} - -TaskItem GenericDirectUploadServicePrivate::statTree(const TreeStorage &storage, - FilesToStat filesToStat, StatEndHandler statEndHandler) -{ - const auto setupHandler = [=](TaskTree &tree) { - UploadStorage *storagePtr = storage.activeStorage(); - const QList files = filesToStat(storagePtr); - QList statList{optional, ParallelLimit(MaxConcurrentStatCalls)}; - for (const DeployableFile &file : std::as_const(files)) { - QTC_ASSERT(file.isValid(), continue); - statList.append(statTask(storagePtr, file, statEndHandler)); - } - tree.setupRoot({statList}); - }; - return Tree(setupHandler); -} - -TaskItem GenericDirectUploadServicePrivate::uploadTask(const TreeStorage &storage) -{ - const auto setupHandler = [this, storage](FileTransfer &transfer) { - if (storage->filesToUpload.isEmpty()) { - emit q->progressMessage(Tr::tr("No files need to be uploaded.")); - return TaskAction::StopWithDone; - } - emit q->progressMessage(Tr::tr("%n file(s) need to be uploaded.", "", - storage->filesToUpload.size())); - FilesToTransfer files; - for (const DeployableFile &file : std::as_const(storage->filesToUpload)) { - if (!file.localFilePath().exists()) { - const QString message = Tr::tr("Local file \"%1\" does not exist.") - .arg(file.localFilePath().toUserOutput()); - if (ignoreMissingFiles) { - emit q->warningMessage(message); - continue; - } - emit q->errorMessage(message); - return TaskAction::StopWithError; - } - files.append({file.localFilePath(), - q->deviceConfiguration()->filePath(file.remoteFilePath())}); - } - if (files.isEmpty()) { - emit q->progressMessage(Tr::tr("No files need to be uploaded.")); - return TaskAction::StopWithDone; - } - transfer.setFilesToTransfer(files); - QObject::connect(&transfer, &FileTransfer::progress, - q, &GenericDirectUploadService::progressMessage); - return TaskAction::Continue; - }; - const auto errorHandler = [this](const FileTransfer &transfer) { - emit q->errorMessage(transfer.resultData().m_errorString); - }; - - return Transfer(setupHandler, {}, errorHandler); -} - -TaskItem GenericDirectUploadServicePrivate::chmodTask(const DeployableFile &file) -{ - const auto setupHandler = [=](QtcProcess &process) { - process.setCommand({q->deviceConfiguration()->filePath("chmod"), - {"a+x", Utils::ProcessArgs::quoteArgUnix(file.remoteFilePath())}}); - }; - const auto errorHandler = [=](const QtcProcess &process) { - const QString error = process.errorString(); - if (!error.isEmpty()) { - emit q->warningMessage(Tr::tr("Remote chmod failed for file \"%1\": %2") - .arg(file.remoteFilePath(), error)); - } else if (process.exitCode() != 0) { - emit q->warningMessage(Tr::tr("Remote chmod failed for file \"%1\": %2") - .arg(file.remoteFilePath(), process.cleanedStdErr())); - } - }; - return Process(setupHandler, {}, errorHandler); -} - -TaskItem GenericDirectUploadServicePrivate::chmodTree(const TreeStorage &storage) -{ - const auto setupChmodHandler = [=](TaskTree &tree) { - QList filesToChmod; - for (const DeployableFile &file : std::as_const(storage->filesToUpload)) { - if (file.isExecutable()) - filesToChmod << file; - } - QList chmodList{optional, ParallelLimit(MaxConcurrentStatCalls)}; - for (const DeployableFile &file : std::as_const(filesToChmod)) { - QTC_ASSERT(file.isValid(), continue); - chmodList.append(chmodTask(file)); - } - tree.setupRoot({chmodList}); - }; - return Tree(setupChmodHandler); -} - -Group GenericDirectUploadService::deployRecipe() -{ - const auto preFilesToStat = [this](UploadStorage *storage) { - QList filesToStat; - for (const DeployableFile &file : std::as_const(d->deployableFiles)) { - if (d->incremental != IncrementalDeployment::Enabled || hasLocalFileChanged(file)) { - storage->filesToUpload.append(file); - continue; - } - if (d->incremental == IncrementalDeployment::NotSupported) - continue; - filesToStat << file; - } - return filesToStat; - }; - const auto preStatEndHandler = [this](UploadStorage *storage, const DeployableFile &file, - const QDateTime ×tamp) { - if (!timestamp.isValid() || hasRemoteFileChanged(file, timestamp)) - storage->filesToUpload.append(file); - }; - - const auto postFilesToStat = [this](UploadStorage *storage) { - return d->incremental == IncrementalDeployment::NotSupported - ? QList() : storage->filesToUpload; - }; - const auto postStatEndHandler = [this](UploadStorage *storage, const DeployableFile &file, - const QDateTime ×tamp) { - Q_UNUSED(storage) - if (timestamp.isValid()) - saveDeploymentTimeStamp(file, timestamp); - }; - const auto doneHandler = [this] { - emit progressMessage(Tr::tr("All files successfully deployed.")); - }; - - const TreeStorage storage; - const Group root { - Storage(storage), - d->statTree(storage, preFilesToStat, preStatEndHandler), - d->uploadTask(storage), - Group { - d->chmodTree(storage), - d->statTree(storage, postFilesToStat, postStatEndHandler) - }, - OnGroupDone(doneHandler) - }; - return root; -} - -} //namespace RemoteLinux diff --git a/src/plugins/remotelinux/genericdirectuploadservice.h b/src/plugins/remotelinux/genericdirectuploadservice.h deleted file mode 100644 index 31799f063ad..00000000000 --- a/src/plugins/remotelinux/genericdirectuploadservice.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#pragma once - -#include "remotelinux_export.h" - -#include "abstractremotelinuxdeploystep.h" - -#include - -namespace ProjectExplorer { class DeployableFile; } - -namespace RemoteLinux { -namespace Internal { class GenericDirectUploadServicePrivate; } - -enum class IncrementalDeployment { Enabled, Disabled, NotSupported }; - -class REMOTELINUX_EXPORT GenericDirectUploadService : public AbstractRemoteLinuxDeployService -{ - Q_OBJECT -public: - GenericDirectUploadService(QObject *parent = nullptr); - ~GenericDirectUploadService(); - - void setDeployableFiles(const QList &deployableFiles); - void setIncrementalDeployment(IncrementalDeployment incremental); - void setIgnoreMissingFiles(bool ignoreMissingFiles); - -private: - bool isDeploymentNecessary() const final; - Utils::Tasking::Group deployRecipe() final; - - friend class Internal::GenericDirectUploadServicePrivate; - Internal::GenericDirectUploadServicePrivate * const d; -}; - -} //namespace RemoteLinux diff --git a/src/plugins/remotelinux/genericdirectuploadstep.cpp b/src/plugins/remotelinux/genericdirectuploadstep.cpp index 2b778e2b9c8..46a431861d1 100644 --- a/src/plugins/remotelinux/genericdirectuploadstep.cpp +++ b/src/plugins/remotelinux/genericdirectuploadstep.cpp @@ -3,18 +3,317 @@ #include "genericdirectuploadstep.h" -#include "genericdirectuploadservice.h" #include "remotelinux_constants.h" #include "remotelinuxtr.h" +#include #include -#include +#include +#include #include +#include + +#include +#include +#include +#include + +#include using namespace ProjectExplorer; using namespace Utils; +using namespace Utils::Tasking; namespace RemoteLinux { +namespace Internal { + +const int MaxConcurrentStatCalls = 10; + +struct UploadStorage +{ + QList filesToUpload; +}; + +enum class IncrementalDeployment { Enabled, Disabled, NotSupported }; + +class GenericDirectUploadService : public AbstractRemoteLinuxDeployService +{ +public: + GenericDirectUploadService(QObject *parent = nullptr) + : AbstractRemoteLinuxDeployService(parent) + {} + + void setDeployableFiles(const QList &deployableFiles); + void setIncrementalDeployment(IncrementalDeployment incremental); + void setIgnoreMissingFiles(bool ignoreMissingFiles); + +private: + bool isDeploymentNecessary() const final; + Utils::Tasking::Group deployRecipe() final; + + QDateTime timestampFromStat(const DeployableFile &file, QtcProcess *statProc); + + using FilesToStat = std::function(UploadStorage *)>; + using StatEndHandler + = std::function; + TaskItem statTask(UploadStorage *storage, const DeployableFile &file, + StatEndHandler statEndHandler); + TaskItem statTree(const TreeStorage &storage, FilesToStat filesToStat, + StatEndHandler statEndHandler); + TaskItem uploadTask(const TreeStorage &storage); + TaskItem chmodTask(const DeployableFile &file); + TaskItem chmodTree(const TreeStorage &storage); + + IncrementalDeployment m_incremental = IncrementalDeployment::NotSupported; + bool m_ignoreMissingFiles = false; + mutable QList m_deployableFiles; +}; + +QList collectFilesToUpload(const DeployableFile &deployable) +{ + QList collected; + FilePath localFile = deployable.localFilePath(); + if (localFile.isDir()) { + const FilePaths files = localFile.dirEntries(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); + const QString remoteDir = deployable.remoteDirectory() + '/' + localFile.fileName(); + for (const FilePath &localFilePath : files) + collected.append(collectFilesToUpload(DeployableFile(localFilePath, remoteDir))); + } else { + collected << deployable; + } + return collected; +} + +} // namespace Internal + +using namespace Internal; + +void GenericDirectUploadService::setDeployableFiles(const QList &deployableFiles) +{ + m_deployableFiles = deployableFiles; +} + +void GenericDirectUploadService::setIncrementalDeployment(IncrementalDeployment incremental) +{ + m_incremental = incremental; +} + +void GenericDirectUploadService::setIgnoreMissingFiles(bool ignoreMissingFiles) +{ + m_ignoreMissingFiles = ignoreMissingFiles; +} + +bool GenericDirectUploadService::isDeploymentNecessary() const +{ + QList collected; + for (int i = 0; i < m_deployableFiles.count(); ++i) + collected.append(collectFilesToUpload(m_deployableFiles.at(i))); + + QTC_CHECK(collected.size() >= m_deployableFiles.size()); + m_deployableFiles = collected; + return !m_deployableFiles.isEmpty(); +} + +QDateTime GenericDirectUploadService::timestampFromStat(const DeployableFile &file, + QtcProcess *statProc) +{ + bool succeeded = false; + QString error; + if (statProc->error() == QProcess::FailedToStart) { + error = Tr::tr("Failed to start \"stat\": %1").arg(statProc->errorString()); + } else if (statProc->exitStatus() == QProcess::CrashExit) { + error = Tr::tr("\"stat\" crashed."); + } else if (statProc->exitCode() != 0) { + error = Tr::tr("\"stat\" failed with exit code %1: %2") + .arg(statProc->exitCode()).arg(statProc->cleanedStdErr()); + } else { + succeeded = true; + } + if (!succeeded) { + emit warningMessage(Tr::tr("Failed to retrieve remote timestamp for file \"%1\". " + "Incremental deployment will not work. Error message was: %2") + .arg(file.remoteFilePath(), error)); + return {}; + } + const QByteArray output = statProc->readAllRawStandardOutput().trimmed(); + const QString warningString(Tr::tr("Unexpected stat output for remote file \"%1\": %2") + .arg(file.remoteFilePath()).arg(QString::fromUtf8(output))); + if (!output.startsWith(file.remoteFilePath().toUtf8())) { + emit warningMessage(warningString); + return {}; + } + const QByteArrayList columns = output.mid(file.remoteFilePath().toUtf8().size() + 1).split(' '); + if (columns.size() < 14) { // Normal Linux stat: 16 columns in total, busybox stat: 15 columns + emit warningMessage(warningString); + return {}; + } + bool isNumber; + const qint64 secsSinceEpoch = columns.at(11).toLongLong(&isNumber); + if (!isNumber) { + emit warningMessage(warningString); + return {}; + } + return QDateTime::fromSecsSinceEpoch(secsSinceEpoch); +} + +TaskItem GenericDirectUploadService::statTask(UploadStorage *storage, + const DeployableFile &file, + StatEndHandler statEndHandler) +{ + const auto setupHandler = [=](QtcProcess &process) { + // We'd like to use --format=%Y, but it's not supported by busybox. + process.setCommand({deviceConfiguration()->filePath("stat"), + {"-t", Utils::ProcessArgs::quoteArgUnix(file.remoteFilePath())}}); + }; + const auto endHandler = [=](const QtcProcess &process) { + QtcProcess *proc = const_cast(&process); + const QDateTime timestamp = timestampFromStat(file, proc); + statEndHandler(storage, file, timestamp); + }; + return Process(setupHandler, endHandler, endHandler); +} + +TaskItem GenericDirectUploadService::statTree(const TreeStorage &storage, + FilesToStat filesToStat, StatEndHandler statEndHandler) +{ + const auto setupHandler = [=](TaskTree &tree) { + UploadStorage *storagePtr = storage.activeStorage(); + const QList files = filesToStat(storagePtr); + QList statList{optional, ParallelLimit(MaxConcurrentStatCalls)}; + for (const DeployableFile &file : std::as_const(files)) { + QTC_ASSERT(file.isValid(), continue); + statList.append(statTask(storagePtr, file, statEndHandler)); + } + tree.setupRoot({statList}); + }; + return Tree(setupHandler); +} + +TaskItem GenericDirectUploadService::uploadTask(const TreeStorage &storage) +{ + const auto setupHandler = [this, storage](FileTransfer &transfer) { + if (storage->filesToUpload.isEmpty()) { + emit progressMessage(Tr::tr("No files need to be uploaded.")); + return TaskAction::StopWithDone; + } + emit progressMessage(Tr::tr("%n file(s) need to be uploaded.", "", + storage->filesToUpload.size())); + FilesToTransfer files; + for (const DeployableFile &file : std::as_const(storage->filesToUpload)) { + if (!file.localFilePath().exists()) { + const QString message = Tr::tr("Local file \"%1\" does not exist.") + .arg(file.localFilePath().toUserOutput()); + if (m_ignoreMissingFiles) { + emit warningMessage(message); + continue; + } + emit errorMessage(message); + return TaskAction::StopWithError; + } + files.append({file.localFilePath(), + deviceConfiguration()->filePath(file.remoteFilePath())}); + } + if (files.isEmpty()) { + emit progressMessage(Tr::tr("No files need to be uploaded.")); + return TaskAction::StopWithDone; + } + transfer.setFilesToTransfer(files); + QObject::connect(&transfer, &FileTransfer::progress, + this, &GenericDirectUploadService::progressMessage); + return TaskAction::Continue; + }; + const auto errorHandler = [this](const FileTransfer &transfer) { + emit errorMessage(transfer.resultData().m_errorString); + }; + + return Transfer(setupHandler, {}, errorHandler); +} + +TaskItem GenericDirectUploadService::chmodTask(const DeployableFile &file) +{ + const auto setupHandler = [=](QtcProcess &process) { + process.setCommand({deviceConfiguration()->filePath("chmod"), + {"a+x", Utils::ProcessArgs::quoteArgUnix(file.remoteFilePath())}}); + }; + const auto errorHandler = [=](const QtcProcess &process) { + const QString error = process.errorString(); + if (!error.isEmpty()) { + emit warningMessage(Tr::tr("Remote chmod failed for file \"%1\": %2") + .arg(file.remoteFilePath(), error)); + } else if (process.exitCode() != 0) { + emit warningMessage(Tr::tr("Remote chmod failed for file \"%1\": %2") + .arg(file.remoteFilePath(), process.cleanedStdErr())); + } + }; + return Process(setupHandler, {}, errorHandler); +} + +TaskItem GenericDirectUploadService::chmodTree(const TreeStorage &storage) +{ + const auto setupChmodHandler = [=](TaskTree &tree) { + QList filesToChmod; + for (const DeployableFile &file : std::as_const(storage->filesToUpload)) { + if (file.isExecutable()) + filesToChmod << file; + } + QList chmodList{optional, ParallelLimit(MaxConcurrentStatCalls)}; + for (const DeployableFile &file : std::as_const(filesToChmod)) { + QTC_ASSERT(file.isValid(), continue); + chmodList.append(chmodTask(file)); + } + tree.setupRoot({chmodList}); + }; + return Tree(setupChmodHandler); +} + +Group GenericDirectUploadService::deployRecipe() +{ + const auto preFilesToStat = [this](UploadStorage *storage) { + QList filesToStat; + for (const DeployableFile &file : std::as_const(m_deployableFiles)) { + if (m_incremental != IncrementalDeployment::Enabled || hasLocalFileChanged(file)) { + storage->filesToUpload.append(file); + continue; + } + if (m_incremental == IncrementalDeployment::NotSupported) + continue; + filesToStat << file; + } + return filesToStat; + }; + const auto preStatEndHandler = [this](UploadStorage *storage, const DeployableFile &file, + const QDateTime ×tamp) { + if (!timestamp.isValid() || hasRemoteFileChanged(file, timestamp)) + storage->filesToUpload.append(file); + }; + + const auto postFilesToStat = [this](UploadStorage *storage) { + return m_incremental == IncrementalDeployment::NotSupported + ? QList() : storage->filesToUpload; + }; + const auto postStatEndHandler = [this](UploadStorage *storage, const DeployableFile &file, + const QDateTime ×tamp) { + Q_UNUSED(storage) + if (timestamp.isValid()) + saveDeploymentTimeStamp(file, timestamp); + }; + const auto doneHandler = [this] { + emit progressMessage(Tr::tr("All files successfully deployed.")); + }; + + const TreeStorage storage; + const Group root { + Storage(storage), + statTree(storage, preFilesToStat, preStatEndHandler), + uploadTask(storage), + Group { + chmodTree(storage), + statTree(storage, postFilesToStat, postStatEndHandler) + }, + OnGroupDone(doneHandler) + }; + return root; +} GenericDirectUploadStep::GenericDirectUploadStep(BuildStepList *bsl, Utils::Id id, bool offerIncrementalDeployment) diff --git a/src/plugins/remotelinux/remotelinux.qbs b/src/plugins/remotelinux/remotelinux.qbs index 5235dbaef5e..94a3878fe04 100644 --- a/src/plugins/remotelinux/remotelinux.qbs +++ b/src/plugins/remotelinux/remotelinux.qbs @@ -19,8 +19,6 @@ Project { "deploymenttimeinfo.h", "customcommanddeploystep.cpp", "customcommanddeploystep.h", - "genericdirectuploadservice.cpp", - "genericdirectuploadservice.h", "genericdirectuploadstep.cpp", "genericdirectuploadstep.h", "genericlinuxdeviceconfigurationwidget.cpp",