forked from qt-creator/qt-creator
Move FileTransfer into ProjectExplorer plugin
Make it ready for providing implementations for other devices. Change-Id: I14eaf167a7b2c1189f4d23f2e9f556204295b9b3 Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
@@ -60,6 +60,8 @@ add_qtc_plugin(ProjectExplorer
|
|||||||
devicesupport/devicesettingswidget.cpp devicesupport/devicesettingswidget.h devicesupport/devicesettingswidget.ui
|
devicesupport/devicesettingswidget.cpp devicesupport/devicesettingswidget.h devicesupport/devicesettingswidget.ui
|
||||||
devicesupport/devicetestdialog.cpp devicesupport/devicetestdialog.h devicesupport/devicetestdialog.ui
|
devicesupport/devicetestdialog.cpp devicesupport/devicetestdialog.h devicesupport/devicetestdialog.ui
|
||||||
devicesupport/deviceusedportsgatherer.cpp devicesupport/deviceusedportsgatherer.h
|
devicesupport/deviceusedportsgatherer.cpp devicesupport/deviceusedportsgatherer.h
|
||||||
|
devicesupport/filetransfer.cpp devicesupport/filetransfer.h
|
||||||
|
devicesupport/filetransferinterface.h
|
||||||
devicesupport/idevice.cpp devicesupport/idevice.h
|
devicesupport/idevice.cpp devicesupport/idevice.h
|
||||||
devicesupport/idevicefactory.cpp devicesupport/idevicefactory.h
|
devicesupport/idevicefactory.cpp devicesupport/idevicefactory.h
|
||||||
devicesupport/idevicefwd.h
|
devicesupport/idevicefwd.h
|
||||||
|
227
src/plugins/projectexplorer/devicesupport/filetransfer.cpp
Normal file
227
src/plugins/projectexplorer/devicesupport/filetransfer.cpp
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2022 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "filetransfer.h"
|
||||||
|
|
||||||
|
#include "devicemanager.h"
|
||||||
|
#include "idevice.h"
|
||||||
|
|
||||||
|
#include <utils/processinterface.h>
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
|
#include <QProcess>
|
||||||
|
|
||||||
|
using namespace Utils;
|
||||||
|
|
||||||
|
namespace ProjectExplorer {
|
||||||
|
|
||||||
|
FileTransferDirection FileToTransfer::direction() const
|
||||||
|
{
|
||||||
|
if (m_source.needsDevice() == m_target.needsDevice())
|
||||||
|
return FileTransferDirection::Invalid;
|
||||||
|
return m_source.needsDevice() ? FileTransferDirection::Download : FileTransferDirection::Upload;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FileTransferSetupData::defaultRsyncFlags()
|
||||||
|
{
|
||||||
|
return "-av";
|
||||||
|
}
|
||||||
|
|
||||||
|
static FileTransferDirection transferDirection(const FilesToTransfer &files)
|
||||||
|
{
|
||||||
|
if (files.isEmpty())
|
||||||
|
return FileTransferDirection::Invalid;
|
||||||
|
|
||||||
|
const FileTransferDirection direction = files.first().direction();
|
||||||
|
for (const FileToTransfer &file : files) {
|
||||||
|
if (file.direction() != direction)
|
||||||
|
return FileTransferDirection::Invalid;
|
||||||
|
}
|
||||||
|
return direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const FilePath &remoteFile(FileTransferDirection direction, const FileToTransfer &file)
|
||||||
|
{
|
||||||
|
return direction == FileTransferDirection::Upload ? file.m_target : file.m_source;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isSameDevice(const FilePath &first, const FilePath &second)
|
||||||
|
{
|
||||||
|
return (first.scheme() == second.scheme()) && (first.host() == second.host());
|
||||||
|
}
|
||||||
|
|
||||||
|
static IDeviceConstPtr matchedDevice(FileTransferDirection direction, const FilesToTransfer &files)
|
||||||
|
{
|
||||||
|
if (files.isEmpty())
|
||||||
|
return {};
|
||||||
|
const FilePath &filePath = remoteFile(direction, files.first());
|
||||||
|
for (const FileToTransfer &file : files) {
|
||||||
|
if (!isSameDevice(filePath, remoteFile(direction, file)))
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return DeviceManager::deviceForPath(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileTransferInterface::startFailed(const QString &errorString)
|
||||||
|
{
|
||||||
|
emit done({0, QProcess::NormalExit, QProcess::FailedToStart, errorString});
|
||||||
|
}
|
||||||
|
|
||||||
|
class FileTransferPrivate : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
void test(const ProjectExplorer::IDeviceConstPtr &onDevice);
|
||||||
|
void start();
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
FileTransferSetupData m_setup;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void progress(const QString &progressMessage);
|
||||||
|
void done(const ProcessResultData &resultData);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void startFailed(const QString &errorString);
|
||||||
|
void run(const FileTransferSetupData &setup, const IDeviceConstPtr &device);
|
||||||
|
|
||||||
|
std::unique_ptr<FileTransferInterface> m_transfer;
|
||||||
|
};
|
||||||
|
|
||||||
|
void FileTransferPrivate::test(const IDeviceConstPtr &onDevice)
|
||||||
|
{
|
||||||
|
if (!onDevice)
|
||||||
|
return startFailed(tr("No device set for test transfer."));
|
||||||
|
|
||||||
|
run({{}, m_setup.m_method, m_setup.m_rsyncFlags}, onDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileTransferPrivate::start()
|
||||||
|
{
|
||||||
|
if (m_setup.m_files.isEmpty())
|
||||||
|
return startFailed(tr("No files to transfer."));
|
||||||
|
|
||||||
|
const FileTransferDirection direction = transferDirection(m_setup.m_files);
|
||||||
|
if (direction == FileTransferDirection::Invalid)
|
||||||
|
return startFailed(tr("Mixing different types of transfer in one go."));
|
||||||
|
|
||||||
|
const IDeviceConstPtr device = matchedDevice(direction, m_setup.m_files);
|
||||||
|
if (!device)
|
||||||
|
return startFailed(tr("Trying to transfer into / from not matching device."));
|
||||||
|
|
||||||
|
run(m_setup, device);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileTransferPrivate::stop()
|
||||||
|
{
|
||||||
|
if (!m_transfer)
|
||||||
|
return;
|
||||||
|
m_transfer->disconnect();
|
||||||
|
m_transfer.release()->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileTransferPrivate::run(const FileTransferSetupData &setup, const IDeviceConstPtr &device)
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
|
||||||
|
m_transfer.reset(device->createFileTransferInterface(setup));
|
||||||
|
QTC_ASSERT(m_transfer, startFailed(tr("Missing transfer implementation.")); return);
|
||||||
|
|
||||||
|
m_transfer->setParent(this);
|
||||||
|
connect(m_transfer.get(), &FileTransferInterface::progress,
|
||||||
|
this, &FileTransferPrivate::progress);
|
||||||
|
connect(m_transfer.get(), &FileTransferInterface::done,
|
||||||
|
this, &FileTransferPrivate::done);
|
||||||
|
m_transfer->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileTransferPrivate::startFailed(const QString &errorString)
|
||||||
|
{
|
||||||
|
emit done({0, QProcess::NormalExit, QProcess::FailedToStart, errorString});
|
||||||
|
}
|
||||||
|
|
||||||
|
FileTransfer::FileTransfer()
|
||||||
|
: d(new FileTransferPrivate)
|
||||||
|
{
|
||||||
|
d->setParent(this);
|
||||||
|
connect(d, &FileTransferPrivate::progress, this, &FileTransfer::progress);
|
||||||
|
connect(d, &FileTransferPrivate::done, this, &FileTransfer::done);
|
||||||
|
}
|
||||||
|
|
||||||
|
FileTransfer::~FileTransfer()
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileTransfer::setFilesToTransfer(const FilesToTransfer &files)
|
||||||
|
{
|
||||||
|
d->m_setup.m_files = files;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileTransfer::setTransferMethod(FileTransferMethod method)
|
||||||
|
{
|
||||||
|
d->m_setup.m_method = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileTransfer::setRsyncFlags(const QString &flags)
|
||||||
|
{
|
||||||
|
d->m_setup.m_rsyncFlags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileTransfer::test(const ProjectExplorer::IDeviceConstPtr &onDevice)
|
||||||
|
{
|
||||||
|
d->test(onDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
FileTransferMethod FileTransfer::transferMethod() const
|
||||||
|
{
|
||||||
|
return d->m_setup.m_method;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileTransfer::start()
|
||||||
|
{
|
||||||
|
d->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileTransfer::stop()
|
||||||
|
{
|
||||||
|
d->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FileTransfer::transferMethodName(FileTransferMethod method)
|
||||||
|
{
|
||||||
|
switch (method) {
|
||||||
|
case FileTransferMethod::Sftp: return FileTransfer::tr("sftp");
|
||||||
|
case FileTransferMethod::Rsync: return FileTransfer::tr("rsync");
|
||||||
|
}
|
||||||
|
QTC_CHECK(false);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ProjectExplorer
|
||||||
|
|
||||||
|
#include "filetransfer.moc"
|
@@ -25,33 +25,17 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "remotelinux_export.h"
|
#include "../projectexplorer_export.h"
|
||||||
|
#include "filetransferinterface.h"
|
||||||
#include <projectexplorer/devicesupport/idevicefwd.h>
|
#include "idevicefwd.h"
|
||||||
|
|
||||||
#include <utils/filepath.h>
|
|
||||||
|
|
||||||
namespace Utils { class ProcessResultData; }
|
namespace Utils { class ProcessResultData; }
|
||||||
|
|
||||||
namespace RemoteLinux {
|
namespace ProjectExplorer {
|
||||||
|
|
||||||
class REMOTELINUX_EXPORT FileToTransfer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Utils::FilePath m_source;
|
|
||||||
Utils::FilePath m_target;
|
|
||||||
};
|
|
||||||
using FilesToTransfer = QList<FileToTransfer>;
|
|
||||||
|
|
||||||
enum class FileTransferMethod {
|
|
||||||
Sftp,
|
|
||||||
Rsync,
|
|
||||||
Default = Sftp
|
|
||||||
};
|
|
||||||
|
|
||||||
class FileTransferPrivate;
|
class FileTransferPrivate;
|
||||||
|
|
||||||
class REMOTELINUX_EXPORT FileTransfer : public QObject
|
class PROJECTEXPLORER_EXPORT FileTransfer : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@@ -59,19 +43,17 @@ public:
|
|||||||
FileTransfer();
|
FileTransfer();
|
||||||
~FileTransfer();
|
~FileTransfer();
|
||||||
|
|
||||||
void setDevice(const ProjectExplorer::IDeviceConstPtr &device);
|
|
||||||
void setTransferMethod(FileTransferMethod method);
|
|
||||||
void setFilesToTransfer(const FilesToTransfer &files);
|
void setFilesToTransfer(const FilesToTransfer &files);
|
||||||
|
void setTransferMethod(FileTransferMethod method);
|
||||||
void setRsyncFlags(const QString &flags);
|
void setRsyncFlags(const QString &flags);
|
||||||
|
|
||||||
FileTransferMethod transferMethod() const;
|
FileTransferMethod transferMethod() const;
|
||||||
|
|
||||||
void test();
|
void test(const ProjectExplorer::IDeviceConstPtr &onDevice);
|
||||||
void start();
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
static QString transferMethodName(FileTransferMethod method);
|
static QString transferMethodName(FileTransferMethod method);
|
||||||
static QString defaultRsyncFlags();
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void progress(const QString &progressMessage);
|
void progress(const QString &progressMessage);
|
||||||
@@ -81,6 +63,4 @@ private:
|
|||||||
FileTransferPrivate *d;
|
FileTransferPrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace RemoteLinux
|
} // namespace ProjectExplorer
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(RemoteLinux::FileTransferMethod)
|
|
@@ -0,0 +1,93 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2022 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../projectexplorer_export.h"
|
||||||
|
|
||||||
|
#include <utils/filepath.h>
|
||||||
|
|
||||||
|
namespace Utils { class ProcessResultData; }
|
||||||
|
|
||||||
|
namespace ProjectExplorer {
|
||||||
|
|
||||||
|
enum class FileTransferDirection {
|
||||||
|
Invalid,
|
||||||
|
Upload,
|
||||||
|
Download
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class FileTransferMethod {
|
||||||
|
Sftp,
|
||||||
|
Rsync,
|
||||||
|
Default = Sftp
|
||||||
|
};
|
||||||
|
|
||||||
|
class PROJECTEXPLORER_EXPORT FileToTransfer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Utils::FilePath m_source;
|
||||||
|
Utils::FilePath m_target;
|
||||||
|
|
||||||
|
FileTransferDirection direction() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
using FilesToTransfer = QList<FileToTransfer>;
|
||||||
|
|
||||||
|
class PROJECTEXPLORER_EXPORT FileTransferSetupData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FilesToTransfer m_files; // When empty, do test instead of a real transfer
|
||||||
|
FileTransferMethod m_method = FileTransferMethod::Default;
|
||||||
|
QString m_rsyncFlags = defaultRsyncFlags();
|
||||||
|
|
||||||
|
static QString defaultRsyncFlags();
|
||||||
|
};
|
||||||
|
|
||||||
|
class PROJECTEXPLORER_EXPORT FileTransferInterface : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void progress(const QString &progressMessage);
|
||||||
|
void done(const Utils::ProcessResultData &resultData);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
FileTransferInterface(const FileTransferSetupData &setupData)
|
||||||
|
: m_setup(setupData) {}
|
||||||
|
|
||||||
|
void startFailed(const QString &errorString);
|
||||||
|
|
||||||
|
const FileTransferSetupData m_setup;
|
||||||
|
|
||||||
|
private:
|
||||||
|
FileTransferInterface() = delete;
|
||||||
|
|
||||||
|
virtual void start() = 0;
|
||||||
|
|
||||||
|
friend class FileTransferPrivate;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ProjectExplorer
|
@@ -434,6 +434,14 @@ ProcessInterface *IDevice::createProcessInterface() const
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileTransferInterface *IDevice::createFileTransferInterface(
|
||||||
|
const FileTransferSetupData &setup) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(setup)
|
||||||
|
QTC_CHECK(false);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
Environment IDevice::systemEnvironment() const
|
Environment IDevice::systemEnvironment() const
|
||||||
{
|
{
|
||||||
QTC_CHECK(false);
|
QTC_CHECK(false);
|
||||||
|
@@ -60,6 +60,8 @@ class QtcProcess;
|
|||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
|
|
||||||
class DeviceProcessList;
|
class DeviceProcessList;
|
||||||
|
class FileTransferInterface;
|
||||||
|
class FileTransferSetupData;
|
||||||
class Kit;
|
class Kit;
|
||||||
class SshParameters;
|
class SshParameters;
|
||||||
class Task;
|
class Task;
|
||||||
@@ -265,6 +267,8 @@ public:
|
|||||||
virtual QFile::Permissions permissions(const Utils::FilePath &filePath) const;
|
virtual QFile::Permissions permissions(const Utils::FilePath &filePath) const;
|
||||||
virtual bool setPermissions(const Utils::FilePath &filePath, QFile::Permissions) const;
|
virtual bool setPermissions(const Utils::FilePath &filePath, QFile::Permissions) const;
|
||||||
virtual Utils::ProcessInterface *createProcessInterface() const;
|
virtual Utils::ProcessInterface *createProcessInterface() const;
|
||||||
|
virtual FileTransferInterface *createFileTransferInterface(
|
||||||
|
const FileTransferSetupData &setup) const;
|
||||||
virtual Utils::Environment systemEnvironment() const;
|
virtual Utils::Environment systemEnvironment() const;
|
||||||
virtual qint64 fileSize(const Utils::FilePath &filePath) const;
|
virtual qint64 fileSize(const Utils::FilePath &filePath) const;
|
||||||
virtual qint64 bytesAvailable(const Utils::FilePath &filePath) const;
|
virtual qint64 bytesAvailable(const Utils::FilePath &filePath) const;
|
||||||
|
@@ -219,6 +219,8 @@ Project {
|
|||||||
"devicesettingswidget.cpp", "devicesettingswidget.h", "devicesettingswidget.ui",
|
"devicesettingswidget.cpp", "devicesettingswidget.h", "devicesettingswidget.ui",
|
||||||
"devicetestdialog.cpp", "devicetestdialog.h", "devicetestdialog.ui",
|
"devicetestdialog.cpp", "devicetestdialog.h", "devicetestdialog.ui",
|
||||||
"deviceusedportsgatherer.cpp", "deviceusedportsgatherer.h",
|
"deviceusedportsgatherer.cpp", "deviceusedportsgatherer.h",
|
||||||
|
"filetransfer.cpp", "filetransfer.h",
|
||||||
|
"filetransferinterface.h",
|
||||||
"idevice.cpp", "idevice.h",
|
"idevice.cpp", "idevice.h",
|
||||||
"idevicefactory.cpp", "idevicefactory.h",
|
"idevicefactory.cpp", "idevicefactory.h",
|
||||||
"idevicefwd.h",
|
"idevicefwd.h",
|
||||||
|
@@ -6,7 +6,6 @@ add_qtc_plugin(RemoteLinux
|
|||||||
abstractremotelinuxdeployservice.cpp abstractremotelinuxdeployservice.h
|
abstractremotelinuxdeployservice.cpp abstractremotelinuxdeployservice.h
|
||||||
abstractremotelinuxdeploystep.cpp abstractremotelinuxdeploystep.h
|
abstractremotelinuxdeploystep.cpp abstractremotelinuxdeploystep.h
|
||||||
deploymenttimeinfo.cpp deploymenttimeinfo.h
|
deploymenttimeinfo.cpp deploymenttimeinfo.h
|
||||||
filetransfer.h
|
|
||||||
genericdirectuploadservice.cpp genericdirectuploadservice.h
|
genericdirectuploadservice.cpp genericdirectuploadservice.h
|
||||||
genericdirectuploadstep.cpp genericdirectuploadstep.h
|
genericdirectuploadstep.cpp genericdirectuploadstep.h
|
||||||
genericlinuxdeviceconfigurationwidget.cpp genericlinuxdeviceconfigurationwidget.h genericlinuxdeviceconfigurationwidget.ui
|
genericlinuxdeviceconfigurationwidget.cpp genericlinuxdeviceconfigurationwidget.h genericlinuxdeviceconfigurationwidget.ui
|
||||||
|
@@ -25,10 +25,10 @@
|
|||||||
|
|
||||||
#include "filesystemaccess_test.h"
|
#include "filesystemaccess_test.h"
|
||||||
|
|
||||||
#include "filetransfer.h"
|
|
||||||
#include "linuxdevice.h"
|
#include "linuxdevice.h"
|
||||||
|
|
||||||
#include <projectexplorer/devicesupport/devicemanager.h>
|
#include <projectexplorer/devicesupport/devicemanager.h>
|
||||||
|
#include <projectexplorer/devicesupport/filetransfer.h>
|
||||||
#include <projectexplorer/devicesupport/sshparameters.h>
|
#include <projectexplorer/devicesupport/sshparameters.h>
|
||||||
#include <utils/filepath.h>
|
#include <utils/filepath.h>
|
||||||
#include <utils/processinterface.h>
|
#include <utils/processinterface.h>
|
||||||
@@ -39,6 +39,8 @@
|
|||||||
#include <QTest>
|
#include <QTest>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(ProjectExplorer::FileTransferMethod)
|
||||||
|
|
||||||
using namespace ProjectExplorer;
|
using namespace ProjectExplorer;
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
|
||||||
@@ -230,7 +232,6 @@ void FileSystemAccessTest::testFileTransfer()
|
|||||||
|
|
||||||
FileTransfer fileTransfer;
|
FileTransfer fileTransfer;
|
||||||
fileTransfer.setTransferMethod(fileTransferMethod);
|
fileTransfer.setTransferMethod(fileTransferMethod);
|
||||||
fileTransfer.setDevice(m_device);
|
|
||||||
|
|
||||||
// Create and upload 1000 small files and one big file
|
// Create and upload 1000 small files and one big file
|
||||||
QTemporaryDir dirForFilesToUpload;
|
QTemporaryDir dirForFilesToUpload;
|
||||||
|
@@ -25,9 +25,8 @@
|
|||||||
|
|
||||||
#include "genericdirectuploadservice.h"
|
#include "genericdirectuploadservice.h"
|
||||||
|
|
||||||
#include "filetransfer.h"
|
|
||||||
|
|
||||||
#include <projectexplorer/deployablefile.h>
|
#include <projectexplorer/deployablefile.h>
|
||||||
|
#include <projectexplorer/devicesupport/filetransfer.h>
|
||||||
#include <projectexplorer/devicesupport/idevice.h>
|
#include <projectexplorer/devicesupport/idevice.h>
|
||||||
#include <utils/hostosinfo.h>
|
#include <utils/hostosinfo.h>
|
||||||
#include <utils/processinterface.h>
|
#include <utils/processinterface.h>
|
||||||
@@ -310,7 +309,6 @@ void GenericDirectUploadService::uploadFiles()
|
|||||||
deviceConfiguration()->filePath(file.remoteFilePath())});
|
deviceConfiguration()->filePath(file.remoteFilePath())});
|
||||||
}
|
}
|
||||||
|
|
||||||
d->uploader.setDevice(deviceConfiguration());
|
|
||||||
d->uploader.setFilesToTransfer(files);
|
d->uploader.setFilesToTransfer(files);
|
||||||
d->uploader.start();
|
d->uploader.start();
|
||||||
}
|
}
|
||||||
|
@@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
#include "linuxdevice.h"
|
#include "linuxdevice.h"
|
||||||
|
|
||||||
#include "filetransfer.h"
|
|
||||||
#include "genericlinuxdeviceconfigurationwidget.h"
|
#include "genericlinuxdeviceconfigurationwidget.h"
|
||||||
#include "genericlinuxdeviceconfigurationwizard.h"
|
#include "genericlinuxdeviceconfigurationwizard.h"
|
||||||
#include "linuxdevicetester.h"
|
#include "linuxdevicetester.h"
|
||||||
@@ -39,6 +38,8 @@
|
|||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <coreplugin/messagemanager.h>
|
#include <coreplugin/messagemanager.h>
|
||||||
|
|
||||||
|
#include <projectexplorer/devicesupport/filetransfer.h>
|
||||||
|
#include <projectexplorer/devicesupport/filetransferinterface.h>
|
||||||
#include <projectexplorer/devicesupport/sshdeviceprocesslist.h>
|
#include <projectexplorer/devicesupport/sshdeviceprocesslist.h>
|
||||||
#include <projectexplorer/devicesupport/sshparameters.h>
|
#include <projectexplorer/devicesupport/sshparameters.h>
|
||||||
#include <projectexplorer/devicesupport/sshsettings.h>
|
#include <projectexplorer/devicesupport/sshsettings.h>
|
||||||
@@ -1417,47 +1418,6 @@ bool LinuxDevice::writeFileContents(const FilePath &filePath, const QByteArray &
|
|||||||
return d->runInShell({"dd", {"of=" + filePath.path()}}, data);
|
return d->runInShell({"dd", {"of=" + filePath.path()}}, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class TransferDirection {
|
|
||||||
Upload,
|
|
||||||
Download,
|
|
||||||
Invalid
|
|
||||||
};
|
|
||||||
|
|
||||||
static TransferDirection transferDirection(const FileToTransfer &file)
|
|
||||||
{
|
|
||||||
if (file.m_source.needsDevice() == file.m_target.needsDevice())
|
|
||||||
return TransferDirection::Invalid;
|
|
||||||
return file.m_source.needsDevice() ? TransferDirection::Download : TransferDirection::Upload;
|
|
||||||
}
|
|
||||||
|
|
||||||
static TransferDirection transferDirection(const FilesToTransfer &files)
|
|
||||||
{
|
|
||||||
if (files.isEmpty())
|
|
||||||
return TransferDirection::Invalid;
|
|
||||||
const TransferDirection direction = transferDirection(files.first());
|
|
||||||
for (const FileToTransfer &file : files) {
|
|
||||||
if (transferDirection(file) != direction)
|
|
||||||
return TransferDirection::Invalid;
|
|
||||||
}
|
|
||||||
return direction;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isDeviceMatched(const FilePath &file, const QString &id)
|
|
||||||
{
|
|
||||||
return (file.scheme() == "device") && (file.host() == id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isDeviceMatched(const FilesToTransfer &files, const QString &id)
|
|
||||||
{
|
|
||||||
for (const FileToTransfer &file : files) {
|
|
||||||
if (transferDirection(file) == TransferDirection::Upload && !isDeviceMatched(file.m_target, id))
|
|
||||||
return false;
|
|
||||||
if (transferDirection(file) == TransferDirection::Download && !isDeviceMatched(file.m_source, id))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FilePaths dirsToCreate(const FilesToTransfer &files)
|
static FilePaths dirsToCreate(const FilesToTransfer &files)
|
||||||
{
|
{
|
||||||
FilePaths dirs;
|
FilePaths dirs;
|
||||||
@@ -1474,77 +1434,33 @@ static FilePaths dirsToCreate(const FilesToTransfer &files)
|
|||||||
return dirs;
|
return dirs;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QByteArray transferCommand(const TransferDirection transferDirection, bool link)
|
static QByteArray transferCommand(const FileTransferDirection direction, bool link)
|
||||||
{
|
{
|
||||||
if (transferDirection == TransferDirection::Upload)
|
if (direction == FileTransferDirection::Upload)
|
||||||
return link ? "ln -s" : "put";
|
return link ? "ln -s" : "put";
|
||||||
if (transferDirection == TransferDirection::Download)
|
if (direction == FileTransferDirection::Download)
|
||||||
return "get";
|
return "get";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
class FileTransferInterface : public QObject
|
class SshTransferInterface : public FileTransferInterface
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
|
||||||
void setDevice(const ProjectExplorer::IDeviceConstPtr &device)
|
|
||||||
{
|
|
||||||
m_device = device;
|
|
||||||
m_devicePrivate = nullptr;
|
|
||||||
if (m_device) {
|
|
||||||
const LinuxDevice *linuxDevice = m_device.dynamicCast<const LinuxDevice>().get();
|
|
||||||
QTC_ASSERT(linuxDevice, return);
|
|
||||||
m_devicePrivate = linuxDevice->d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void setFilesToTransfer(const FilesToTransfer &files, TransferDirection direction)
|
|
||||||
{
|
|
||||||
m_files = files;
|
|
||||||
m_direction = direction;
|
|
||||||
}
|
|
||||||
|
|
||||||
void start()
|
|
||||||
{
|
|
||||||
if (!m_devicePrivate) {
|
|
||||||
startFailed(tr("Transferring files to/from non-linux device "
|
|
||||||
"isn't supported currently."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_sshParameters = displayless(m_devicePrivate->q->sshParameters());
|
|
||||||
if (SshSettings::connectionSharingEnabled()) {
|
|
||||||
m_connecting = true;
|
|
||||||
m_connectionHandle.reset(new SshConnectionHandle(m_device->sharedFromThis()));
|
|
||||||
m_connectionHandle->setParent(this);
|
|
||||||
connect(m_connectionHandle.get(), &SshConnectionHandle::connected,
|
|
||||||
this, &FileTransferInterface::handleConnected);
|
|
||||||
connect(m_connectionHandle.get(), &SshConnectionHandle::disconnected,
|
|
||||||
this, &FileTransferInterface::handleDisconnected);
|
|
||||||
m_devicePrivate->attachToSharedConnection(m_connectionHandle.get(), m_sshParameters);
|
|
||||||
} else {
|
|
||||||
startImpl();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void progress(const QString &progressMessage);
|
|
||||||
void done(const Utils::ProcessResultData &resultData);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
FileTransferInterface(FileTransferMethod method)
|
SshTransferInterface(const FileTransferSetupData &setup, LinuxDevicePrivate *devicePrivate)
|
||||||
: m_method(method)
|
: FileTransferInterface(setup)
|
||||||
|
, m_device(devicePrivate->q->sharedFromThis())
|
||||||
|
, m_devicePrivate(devicePrivate)
|
||||||
, m_process(this)
|
, m_process(this)
|
||||||
{
|
{
|
||||||
|
m_direction = m_setup.m_files.isEmpty() ? FileTransferDirection::Invalid
|
||||||
|
: m_setup.m_files.first().direction();
|
||||||
SshParameters::setupSshEnvironment(&m_process);
|
SshParameters::setupSshEnvironment(&m_process);
|
||||||
connect(&m_process, &QtcProcess::readyReadStandardOutput, this, [this] {
|
connect(&m_process, &QtcProcess::readyReadStandardOutput, this, [this] {
|
||||||
emit progress(QString::fromLocal8Bit(m_process.readAllStandardOutput()));
|
emit progress(QString::fromLocal8Bit(m_process.readAllStandardOutput()));
|
||||||
});
|
});
|
||||||
connect(&m_process, &QtcProcess::done, this, &FileTransferInterface::doneImpl);
|
connect(&m_process, &QtcProcess::done, this, &SshTransferInterface::doneImpl);
|
||||||
}
|
|
||||||
|
|
||||||
void startFailed(const QString &errorString)
|
|
||||||
{
|
|
||||||
emit done({0, QProcess::NormalExit, QProcess::FailedToStart, errorString});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool handleError()
|
bool handleError()
|
||||||
@@ -1552,10 +1468,10 @@ protected:
|
|||||||
ProcessResultData resultData = m_process.resultData();
|
ProcessResultData resultData = m_process.resultData();
|
||||||
if (resultData.m_error == QProcess::FailedToStart) {
|
if (resultData.m_error == QProcess::FailedToStart) {
|
||||||
resultData.m_errorString = tr("\"%1\" failed to start: %2")
|
resultData.m_errorString = tr("\"%1\" failed to start: %2")
|
||||||
.arg(FileTransfer::transferMethodName(m_method), resultData.m_errorString);
|
.arg(FileTransfer::transferMethodName(m_setup.m_method), resultData.m_errorString);
|
||||||
} else if (resultData.m_exitStatus != QProcess::NormalExit) {
|
} else if (resultData.m_exitStatus != QProcess::NormalExit) {
|
||||||
resultData.m_errorString = tr("\"%1\" crashed.")
|
resultData.m_errorString = tr("\"%1\" crashed.")
|
||||||
.arg(FileTransfer::transferMethodName(m_method));
|
.arg(FileTransfer::transferMethodName(m_setup.m_method));
|
||||||
} else if (resultData.m_exitCode != 0) {
|
} else if (resultData.m_exitCode != 0) {
|
||||||
resultData.m_errorString = QString::fromLocal8Bit(m_process.readAllStandardError());
|
resultData.m_errorString = QString::fromLocal8Bit(m_process.readAllStandardError());
|
||||||
} else {
|
} else {
|
||||||
@@ -1583,14 +1499,29 @@ protected:
|
|||||||
QString userAtHost() const { return m_sshParameters.userName() + '@' + m_sshParameters.host(); }
|
QString userAtHost() const { return m_sshParameters.userName() + '@' + m_sshParameters.host(); }
|
||||||
|
|
||||||
QtcProcess &process() { return m_process; }
|
QtcProcess &process() { return m_process; }
|
||||||
|
FileTransferDirection direction() const { return m_direction; }
|
||||||
FilesToTransfer m_files;
|
|
||||||
TransferDirection m_direction = TransferDirection::Invalid;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void startImpl() = 0;
|
virtual void startImpl() = 0;
|
||||||
virtual void doneImpl() = 0;
|
virtual void doneImpl() = 0;
|
||||||
|
|
||||||
|
void start() final
|
||||||
|
{
|
||||||
|
m_sshParameters = displayless(m_device->sshParameters());
|
||||||
|
if (SshSettings::connectionSharingEnabled()) {
|
||||||
|
m_connecting = true;
|
||||||
|
m_connectionHandle.reset(new SshConnectionHandle(m_device));
|
||||||
|
m_connectionHandle->setParent(this);
|
||||||
|
connect(m_connectionHandle.get(), &SshConnectionHandle::connected,
|
||||||
|
this, &SshTransferInterface::handleConnected);
|
||||||
|
connect(m_connectionHandle.get(), &SshConnectionHandle::disconnected,
|
||||||
|
this, &SshTransferInterface::handleDisconnected);
|
||||||
|
m_devicePrivate->attachToSharedConnection(m_connectionHandle.get(), m_sshParameters);
|
||||||
|
} else {
|
||||||
|
startImpl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void handleConnected(const QString &socketFilePath)
|
void handleConnected(const QString &socketFilePath)
|
||||||
{
|
{
|
||||||
m_connecting = false;
|
m_connecting = false;
|
||||||
@@ -1612,20 +1543,24 @@ private:
|
|||||||
emit done(resultData); // TODO: don't emit done() on process finished afterwards
|
emit done(resultData); // TODO: don't emit done() on process finished afterwards
|
||||||
}
|
}
|
||||||
|
|
||||||
FileTransferMethod m_method = FileTransferMethod::Default;
|
|
||||||
IDevice::ConstPtr m_device;
|
IDevice::ConstPtr m_device;
|
||||||
LinuxDevicePrivate *m_devicePrivate = nullptr;
|
LinuxDevicePrivate *m_devicePrivate = nullptr;
|
||||||
std::unique_ptr<SshConnectionHandle> m_connectionHandle;
|
|
||||||
QtcProcess m_process;
|
|
||||||
QString m_socketFilePath;
|
|
||||||
SshParameters m_sshParameters;
|
SshParameters m_sshParameters;
|
||||||
|
FileTransferDirection m_direction = FileTransferDirection::Invalid; // helper
|
||||||
|
|
||||||
|
// ssh shared connection related
|
||||||
|
std::unique_ptr<SshConnectionHandle> m_connectionHandle;
|
||||||
|
QString m_socketFilePath;
|
||||||
bool m_connecting = false;
|
bool m_connecting = false;
|
||||||
|
|
||||||
|
QtcProcess m_process;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SftpTransferImpl : public FileTransferInterface
|
class SftpTransferImpl : public SshTransferInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SftpTransferImpl() : FileTransferInterface(FileTransferMethod::Sftp) { }
|
SftpTransferImpl(const FileTransferSetupData &setup, LinuxDevicePrivate *devicePrivate)
|
||||||
|
: SshTransferInterface(setup, devicePrivate) { }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void startImpl() final
|
void startImpl() final
|
||||||
@@ -1642,12 +1577,12 @@ private:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FilePaths dirs = dirsToCreate(m_files);
|
const FilePaths dirs = dirsToCreate(m_setup.m_files);
|
||||||
for (const FilePath &dir : dirs) {
|
for (const FilePath &dir : dirs) {
|
||||||
if (m_direction == TransferDirection::Upload) {
|
if (direction() == FileTransferDirection::Upload) {
|
||||||
m_batchFile->write("-mkdir " + ProcessArgs::quoteArgUnix(dir.path()).toLocal8Bit()
|
m_batchFile->write("-mkdir " + ProcessArgs::quoteArgUnix(dir.path()).toLocal8Bit()
|
||||||
+ '\n');
|
+ '\n');
|
||||||
} else if (m_direction == TransferDirection::Download) {
|
} else if (direction() == FileTransferDirection::Download) {
|
||||||
if (!QDir::root().mkpath(dir.path())) {
|
if (!QDir::root().mkpath(dir.path())) {
|
||||||
startFailed(tr("Failed to create local directory \"%1\".")
|
startFailed(tr("Failed to create local directory \"%1\".")
|
||||||
.arg(QDir::toNativeSeparators(dir.path())));
|
.arg(QDir::toNativeSeparators(dir.path())));
|
||||||
@@ -1656,10 +1591,10 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const FileToTransfer &file : m_files) {
|
for (const FileToTransfer &file : m_setup.m_files) {
|
||||||
FilePath sourceFileOrLinkTarget = file.m_source;
|
FilePath sourceFileOrLinkTarget = file.m_source;
|
||||||
bool link = false;
|
bool link = false;
|
||||||
if (m_direction == TransferDirection::Upload) {
|
if (direction() == FileTransferDirection::Upload) {
|
||||||
const QFileInfo fi(file.m_source.toFileInfo());
|
const QFileInfo fi(file.m_source.toFileInfo());
|
||||||
if (fi.isSymLink()) {
|
if (fi.isSymLink()) {
|
||||||
link = true;
|
link = true;
|
||||||
@@ -1669,7 +1604,7 @@ private:
|
|||||||
sourceFileOrLinkTarget.setPath(fi.dir().relativeFilePath(fi.symLinkTarget()));
|
sourceFileOrLinkTarget.setPath(fi.dir().relativeFilePath(fi.symLinkTarget()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_batchFile->write(transferCommand(m_direction, link) + ' '
|
m_batchFile->write(transferCommand(direction(), link) + ' '
|
||||||
+ ProcessArgs::quoteArgUnix(sourceFileOrLinkTarget.path()).toLocal8Bit() + ' '
|
+ ProcessArgs::quoteArgUnix(sourceFileOrLinkTarget.path()).toLocal8Bit() + ' '
|
||||||
+ ProcessArgs::quoteArgUnix(file.m_target.path()).toLocal8Bit() + '\n');
|
+ ProcessArgs::quoteArgUnix(file.m_target.path()).toLocal8Bit() + '\n');
|
||||||
}
|
}
|
||||||
@@ -1684,12 +1619,11 @@ private:
|
|||||||
std::unique_ptr<QTemporaryFile> m_batchFile;
|
std::unique_ptr<QTemporaryFile> m_batchFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RsyncTransferImpl : public FileTransferInterface
|
class RsyncTransferImpl : public SshTransferInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RsyncTransferImpl(const QString &flags)
|
RsyncTransferImpl(const FileTransferSetupData &setup, LinuxDevicePrivate *devicePrivate)
|
||||||
: FileTransferInterface(FileTransferMethod::Rsync)
|
: SshTransferInterface(setup, devicePrivate)
|
||||||
, m_flags(flags)
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -1701,7 +1635,7 @@ private:
|
|||||||
|
|
||||||
void doneImpl() final
|
void doneImpl() final
|
||||||
{
|
{
|
||||||
if (m_files.size() == 0 || m_currentIndex == m_files.size() - 1)
|
if (m_setup.m_files.size() == 0 || m_currentIndex == m_setup.m_files.size() - 1)
|
||||||
return handleDone();
|
return handleDone();
|
||||||
|
|
||||||
if (handleError())
|
if (handleError())
|
||||||
@@ -1718,10 +1652,10 @@ private:
|
|||||||
const QString sshCmdLine = ProcessArgs::joinArgs(
|
const QString sshCmdLine = ProcessArgs::joinArgs(
|
||||||
QStringList{SshSettings::sshFilePath().toUserOutput()}
|
QStringList{SshSettings::sshFilePath().toUserOutput()}
|
||||||
<< fullConnectionOptions(), OsTypeLinux);
|
<< fullConnectionOptions(), OsTypeLinux);
|
||||||
QStringList options{"-e", sshCmdLine, m_flags};
|
QStringList options{"-e", sshCmdLine, m_setup.m_rsyncFlags};
|
||||||
|
|
||||||
if (!m_files.isEmpty()) { // NormalRun
|
if (!m_setup.m_files.isEmpty()) { // NormalRun
|
||||||
const FileToTransfer file = m_files.at(m_currentIndex);
|
const FileToTransfer file = m_setup.m_files.at(m_currentIndex);
|
||||||
const FileToTransfer fixedFile = fixLocalFileOnWindows(file, options);
|
const FileToTransfer fixedFile = fixLocalFileOnWindows(file, options);
|
||||||
const auto fixedPaths = fixPaths(fixedFile, userAtHost());
|
const auto fixedPaths = fixPaths(fixedFile, userAtHost());
|
||||||
|
|
||||||
@@ -1740,7 +1674,7 @@ private:
|
|||||||
if (!HostOsInfo::isWindowsHost())
|
if (!HostOsInfo::isWindowsHost())
|
||||||
return file;
|
return file;
|
||||||
|
|
||||||
QString localFilePath = m_direction == TransferDirection::Upload
|
QString localFilePath = direction() == FileTransferDirection::Upload
|
||||||
? file.m_source.path() : file.m_target.path();
|
? file.m_source.path() : file.m_target.path();
|
||||||
localFilePath = '/' + localFilePath.at(0) + localFilePath.mid(2);
|
localFilePath = '/' + localFilePath.at(0) + localFilePath.mid(2);
|
||||||
if (anyOf(options, [](const QString &opt) {
|
if (anyOf(options, [](const QString &opt) {
|
||||||
@@ -1749,8 +1683,8 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
FileToTransfer fixedFile = file;
|
FileToTransfer fixedFile = file;
|
||||||
(m_direction == TransferDirection::Upload) ? fixedFile.m_source.setPath(localFilePath)
|
(direction() == FileTransferDirection::Upload) ? fixedFile.m_source.setPath(localFilePath)
|
||||||
: fixedFile.m_target.setPath(localFilePath);
|
: fixedFile.m_target.setPath(localFilePath);
|
||||||
return fixedFile;
|
return fixedFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1758,7 +1692,7 @@ private:
|
|||||||
{
|
{
|
||||||
FilePath localPath;
|
FilePath localPath;
|
||||||
FilePath remotePath;
|
FilePath remotePath;
|
||||||
if (m_direction == TransferDirection::Upload) {
|
if (direction() == FileTransferDirection::Upload) {
|
||||||
localPath = file.m_source;
|
localPath = file.m_source;
|
||||||
remotePath = file.m_target;
|
remotePath = file.m_target;
|
||||||
} else {
|
} else {
|
||||||
@@ -1769,166 +1703,24 @@ private:
|
|||||||
? localPath.path() + '/' : localPath.path();
|
? localPath.path() + '/' : localPath.path();
|
||||||
const QString remote = remoteHost + ':' + remotePath.path();
|
const QString remote = remoteHost + ':' + remotePath.path();
|
||||||
|
|
||||||
return m_direction == TransferDirection::Upload ? qMakePair(local, remote)
|
return direction() == FileTransferDirection::Upload ? qMakePair(local, remote)
|
||||||
: qMakePair(remote, local);
|
: qMakePair(remote, local);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString m_flags;
|
|
||||||
int m_currentIndex = 0;
|
int m_currentIndex = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FileTransferPrivate : public QObject
|
FileTransferInterface *LinuxDevice::createFileTransferInterface(
|
||||||
|
const FileTransferSetupData &setup) const
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
switch (setup.m_method) {
|
||||||
|
case FileTransferMethod::Sftp: return new SftpTransferImpl(setup, d);
|
||||||
public:
|
case FileTransferMethod::Rsync: return new RsyncTransferImpl(setup, d);
|
||||||
void test() { run(TestRun); }
|
|
||||||
void start() { run(NormalRun); }
|
|
||||||
void stop();
|
|
||||||
|
|
||||||
FileTransferMethod m_method = FileTransferMethod::Default;
|
|
||||||
IDevice::ConstPtr m_device;
|
|
||||||
FilesToTransfer m_files;
|
|
||||||
QString m_rsyncFlags = FileTransfer::defaultRsyncFlags();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void progress(const QString &progressMessage);
|
|
||||||
void done(const Utils::ProcessResultData &resultData);
|
|
||||||
|
|
||||||
private:
|
|
||||||
enum RunMode {
|
|
||||||
NormalRun,
|
|
||||||
TestRun
|
|
||||||
};
|
|
||||||
|
|
||||||
void startFailed(const QString &errorString);
|
|
||||||
void run(RunMode mode);
|
|
||||||
|
|
||||||
std::unique_ptr<FileTransferInterface> m_transfer;
|
|
||||||
};
|
|
||||||
|
|
||||||
void FileTransferPrivate::stop()
|
|
||||||
{
|
|
||||||
if (!m_transfer)
|
|
||||||
return;
|
|
||||||
m_transfer->disconnect();
|
|
||||||
m_transfer.release()->deleteLater();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileTransferPrivate::startFailed(const QString &errorString)
|
|
||||||
{
|
|
||||||
emit done({0, QProcess::NormalExit, QProcess::FailedToStart, errorString});
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileTransferPrivate::run(RunMode mode)
|
|
||||||
{
|
|
||||||
stop();
|
|
||||||
|
|
||||||
TransferDirection direction = TransferDirection::Invalid;
|
|
||||||
if (mode == NormalRun) {
|
|
||||||
if (m_files.isEmpty())
|
|
||||||
return startFailed(tr("No files to transfer."));
|
|
||||||
|
|
||||||
if (!m_device)
|
|
||||||
return startFailed(tr("No device set for transfer."));
|
|
||||||
|
|
||||||
direction = transferDirection(m_files);
|
|
||||||
if (direction == TransferDirection::Invalid)
|
|
||||||
return startFailed(tr("Mixing different types of transfer in one go."));
|
|
||||||
|
|
||||||
if (!isDeviceMatched(m_files, m_device->id().toString()))
|
|
||||||
return startFailed(tr("Trying to transfer into / from not matching device."));
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (m_method) {
|
|
||||||
case FileTransferMethod::Sftp:
|
|
||||||
m_transfer.reset(new SftpTransferImpl());
|
|
||||||
break;
|
|
||||||
case FileTransferMethod::Rsync:
|
|
||||||
m_transfer.reset(new RsyncTransferImpl(m_rsyncFlags));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
QTC_ASSERT(m_transfer, startFailed(tr("Missing transfer implementation.")); return);
|
|
||||||
m_transfer->setParent(this);
|
|
||||||
m_transfer->setDevice(m_device);
|
|
||||||
if (mode == NormalRun)
|
|
||||||
m_transfer->setFilesToTransfer(m_files, direction);
|
|
||||||
connect(m_transfer.get(), &FileTransferInterface::progress,
|
|
||||||
this, &FileTransferPrivate::progress);
|
|
||||||
connect(m_transfer.get(), &FileTransferInterface::done,
|
|
||||||
this, &FileTransferPrivate::done);
|
|
||||||
m_transfer->start();
|
|
||||||
}
|
|
||||||
|
|
||||||
FileTransfer::FileTransfer()
|
|
||||||
: d(new FileTransferPrivate)
|
|
||||||
{
|
|
||||||
d->setParent(this);
|
|
||||||
connect(d, &FileTransferPrivate::progress, this, &FileTransfer::progress);
|
|
||||||
connect(d, &FileTransferPrivate::done, this, &FileTransfer::done);
|
|
||||||
}
|
|
||||||
|
|
||||||
FileTransfer::~FileTransfer()
|
|
||||||
{
|
|
||||||
stop();
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileTransfer::setDevice(const ProjectExplorer::IDeviceConstPtr &device)
|
|
||||||
{
|
|
||||||
d->m_device = device;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileTransfer::setTransferMethod(FileTransferMethod method)
|
|
||||||
{
|
|
||||||
d->m_method = method;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileTransfer::setFilesToTransfer(const FilesToTransfer &files)
|
|
||||||
{
|
|
||||||
d->m_files = files;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileTransfer::setRsyncFlags(const QString &flags)
|
|
||||||
{
|
|
||||||
d->m_rsyncFlags = flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileTransfer::test()
|
|
||||||
{
|
|
||||||
d->test();
|
|
||||||
}
|
|
||||||
|
|
||||||
FileTransferMethod FileTransfer::transferMethod() const
|
|
||||||
{
|
|
||||||
return d->m_method;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileTransfer::start()
|
|
||||||
{
|
|
||||||
d->start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileTransfer::stop()
|
|
||||||
{
|
|
||||||
d->stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString FileTransfer::transferMethodName(FileTransferMethod method)
|
|
||||||
{
|
|
||||||
switch (method) {
|
|
||||||
case FileTransferMethod::Sftp: return FileTransfer::tr("sftp");
|
|
||||||
case FileTransferMethod::Rsync: return FileTransfer::tr("rsync");
|
|
||||||
}
|
}
|
||||||
QTC_CHECK(false);
|
QTC_CHECK(false);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FileTransfer::defaultRsyncFlags()
|
|
||||||
{
|
|
||||||
return "-av";
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
// Factory
|
// Factory
|
||||||
|
@@ -81,6 +81,8 @@ public:
|
|||||||
bool writeFileContents(const Utils::FilePath &filePath, const QByteArray &data) const override;
|
bool writeFileContents(const Utils::FilePath &filePath, const QByteArray &data) const override;
|
||||||
QDateTime lastModified(const Utils::FilePath &filePath) const override;
|
QDateTime lastModified(const Utils::FilePath &filePath) const override;
|
||||||
Utils::ProcessInterface *createProcessInterface() const override;
|
Utils::ProcessInterface *createProcessInterface() const override;
|
||||||
|
ProjectExplorer::FileTransferInterface *createFileTransferInterface(
|
||||||
|
const ProjectExplorer::FileTransferSetupData &setup) const override;
|
||||||
Utils::Environment systemEnvironment() const override;
|
Utils::Environment systemEnvironment() const override;
|
||||||
qint64 fileSize(const Utils::FilePath &filePath) const override;
|
qint64 fileSize(const Utils::FilePath &filePath) const override;
|
||||||
qint64 bytesAvailable(const Utils::FilePath &filePath) const override;
|
qint64 bytesAvailable(const Utils::FilePath &filePath) const override;
|
||||||
@@ -92,7 +94,7 @@ protected:
|
|||||||
|
|
||||||
class LinuxDevicePrivate *d;
|
class LinuxDevicePrivate *d;
|
||||||
friend class SshProcessInterface;
|
friend class SshProcessInterface;
|
||||||
friend class FileTransferInterface;
|
friend class SshTransferInterface;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
@@ -25,10 +25,10 @@
|
|||||||
|
|
||||||
#include "linuxdevicetester.h"
|
#include "linuxdevicetester.h"
|
||||||
|
|
||||||
#include "filetransfer.h"
|
|
||||||
#include "remotelinux_constants.h"
|
#include "remotelinux_constants.h"
|
||||||
|
|
||||||
#include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
|
#include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
|
||||||
|
#include <projectexplorer/devicesupport/filetransfer.h>
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/port.h>
|
#include <utils/port.h>
|
||||||
#include <utils/processinterface.h>
|
#include <utils/processinterface.h>
|
||||||
@@ -84,7 +84,6 @@ void GenericLinuxDeviceTester::testDevice(const IDevice::Ptr &deviceConfiguratio
|
|||||||
QTC_ASSERT(d->state == Inactive, return);
|
QTC_ASSERT(d->state == Inactive, return);
|
||||||
|
|
||||||
d->device = deviceConfiguration;
|
d->device = deviceConfiguration;
|
||||||
d->fileTransfer.setDevice(d->device);
|
|
||||||
|
|
||||||
testEcho();
|
testEcho();
|
||||||
}
|
}
|
||||||
@@ -215,7 +214,7 @@ void GenericLinuxDeviceTester::testFileTransfer(FileTransferMethod method)
|
|||||||
.arg(FileTransfer::transferMethodName(method)));
|
.arg(FileTransfer::transferMethodName(method)));
|
||||||
|
|
||||||
d->fileTransfer.setTransferMethod(method);
|
d->fileTransfer.setTransferMethod(method);
|
||||||
d->fileTransfer.test();
|
d->fileTransfer.test(d->device);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericLinuxDeviceTester::handleFileTransferDone(const ProcessResultData &resultData)
|
void GenericLinuxDeviceTester::handleFileTransferDone(const ProcessResultData &resultData)
|
||||||
|
@@ -27,8 +27,7 @@
|
|||||||
|
|
||||||
#include "remotelinux_export.h"
|
#include "remotelinux_export.h"
|
||||||
|
|
||||||
#include "filetransfer.h"
|
#include <projectexplorer/devicesupport/filetransferinterface.h>
|
||||||
|
|
||||||
#include <projectexplorer/devicesupport/idevice.h>
|
#include <projectexplorer/devicesupport/idevice.h>
|
||||||
|
|
||||||
namespace Utils { class ProcessResultData; }
|
namespace Utils { class ProcessResultData; }
|
||||||
@@ -59,7 +58,7 @@ private:
|
|||||||
void handlePortsGathererError(const QString &message);
|
void handlePortsGathererError(const QString &message);
|
||||||
void handlePortsGathererDone();
|
void handlePortsGathererDone();
|
||||||
|
|
||||||
void testFileTransfer(FileTransferMethod method);
|
void testFileTransfer(ProjectExplorer::FileTransferMethod method);
|
||||||
void handleFileTransferDone(const Utils::ProcessResultData &resultData);
|
void handleFileTransferDone(const Utils::ProcessResultData &resultData);
|
||||||
|
|
||||||
void setFinished(ProjectExplorer::DeviceTester::TestResult result);
|
void setFinished(ProjectExplorer::DeviceTester::TestResult result);
|
||||||
|
@@ -21,7 +21,6 @@ Project {
|
|||||||
"abstractremotelinuxdeploystep.h",
|
"abstractremotelinuxdeploystep.h",
|
||||||
"deploymenttimeinfo.cpp",
|
"deploymenttimeinfo.cpp",
|
||||||
"deploymenttimeinfo.h",
|
"deploymenttimeinfo.h",
|
||||||
"filetransfer.h",
|
|
||||||
"genericdirectuploadservice.cpp",
|
"genericdirectuploadservice.cpp",
|
||||||
"genericdirectuploadservice.h",
|
"genericdirectuploadservice.h",
|
||||||
"genericdirectuploadstep.cpp",
|
"genericdirectuploadstep.cpp",
|
||||||
|
@@ -26,10 +26,10 @@
|
|||||||
#include "rsyncdeploystep.h"
|
#include "rsyncdeploystep.h"
|
||||||
|
|
||||||
#include "abstractremotelinuxdeployservice.h"
|
#include "abstractremotelinuxdeployservice.h"
|
||||||
#include "filetransfer.h"
|
|
||||||
#include "remotelinux_constants.h"
|
#include "remotelinux_constants.h"
|
||||||
|
|
||||||
#include <projectexplorer/deploymentdata.h>
|
#include <projectexplorer/deploymentdata.h>
|
||||||
|
#include <projectexplorer/devicesupport/filetransfer.h>
|
||||||
#include <projectexplorer/devicesupport/idevice.h>
|
#include <projectexplorer/devicesupport/idevice.h>
|
||||||
#include <projectexplorer/runconfigurationaspects.h>
|
#include <projectexplorer/runconfigurationaspects.h>
|
||||||
#include <projectexplorer/target.h>
|
#include <projectexplorer/target.h>
|
||||||
@@ -136,7 +136,6 @@ void RsyncDeployService::createRemoteDirectories()
|
|||||||
|
|
||||||
void RsyncDeployService::deployFiles()
|
void RsyncDeployService::deployFiles()
|
||||||
{
|
{
|
||||||
m_fileTransfer.setDevice(deviceConfiguration());
|
|
||||||
m_fileTransfer.setTransferMethod(FileTransferMethod::Rsync);
|
m_fileTransfer.setTransferMethod(FileTransferMethod::Rsync);
|
||||||
m_fileTransfer.setRsyncFlags(m_flags);
|
m_fileTransfer.setRsyncFlags(m_flags);
|
||||||
m_fileTransfer.setFilesToTransfer(m_files);
|
m_fileTransfer.setFilesToTransfer(m_files);
|
||||||
@@ -161,7 +160,7 @@ RsyncDeployStep::RsyncDeployStep(BuildStepList *bsl, Utils::Id id)
|
|||||||
flags->setDisplayStyle(StringAspect::LineEditDisplay);
|
flags->setDisplayStyle(StringAspect::LineEditDisplay);
|
||||||
flags->setSettingsKey("RemoteLinux.RsyncDeployStep.Flags");
|
flags->setSettingsKey("RemoteLinux.RsyncDeployStep.Flags");
|
||||||
flags->setLabelText(tr("Flags:"));
|
flags->setLabelText(tr("Flags:"));
|
||||||
flags->setValue(FileTransfer::defaultRsyncFlags());
|
flags->setValue(FileTransferSetupData::defaultRsyncFlags());
|
||||||
|
|
||||||
auto ignoreMissingFiles = addAspect<BoolAspect>();
|
auto ignoreMissingFiles = addAspect<BoolAspect>();
|
||||||
ignoreMissingFiles->setSettingsKey("RemoteLinux.RsyncDeployStep.IgnoreMissingFiles");
|
ignoreMissingFiles->setSettingsKey("RemoteLinux.RsyncDeployStep.IgnoreMissingFiles");
|
||||||
|
@@ -25,12 +25,12 @@
|
|||||||
|
|
||||||
#include "uploadandinstalltarpackagestep.h"
|
#include "uploadandinstalltarpackagestep.h"
|
||||||
|
|
||||||
#include "filetransfer.h"
|
|
||||||
#include "remotelinux_constants.h"
|
#include "remotelinux_constants.h"
|
||||||
#include "remotelinuxpackageinstaller.h"
|
#include "remotelinuxpackageinstaller.h"
|
||||||
#include "tarpackagecreationstep.h"
|
#include "tarpackagecreationstep.h"
|
||||||
|
|
||||||
#include <projectexplorer/deployconfiguration.h>
|
#include <projectexplorer/deployconfiguration.h>
|
||||||
|
#include <projectexplorer/devicesupport/filetransfer.h>
|
||||||
#include <projectexplorer/devicesupport/idevice.h>
|
#include <projectexplorer/devicesupport/idevice.h>
|
||||||
|
|
||||||
#include <utils/processinterface.h>
|
#include <utils/processinterface.h>
|
||||||
@@ -103,7 +103,6 @@ void UploadAndInstallTarPackageService::doDeploy()
|
|||||||
const QString remoteFilePath = uploadDir() + QLatin1Char('/') + m_packageFilePath.fileName();
|
const QString remoteFilePath = uploadDir() + QLatin1Char('/') + m_packageFilePath.fileName();
|
||||||
const FilesToTransfer files {{m_packageFilePath,
|
const FilesToTransfer files {{m_packageFilePath,
|
||||||
deviceConfiguration()->filePath(remoteFilePath)}};
|
deviceConfiguration()->filePath(remoteFilePath)}};
|
||||||
m_uploader.setDevice(deviceConfiguration());
|
|
||||||
m_uploader.setFilesToTransfer(files);
|
m_uploader.setFilesToTransfer(files);
|
||||||
m_uploader.start();
|
m_uploader.start();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user