RemoteLinux: Fix deployment when building remotely

By using a generic file transfer method based of FilePath::copyFile()
that doesn't require either of the transfer end point to be the
local host.

Change-Id: Ia2e4273df52f5ce6533046d96be3f6b521b7f0a5
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
hjk
2022-10-14 10:06:21 +02:00
parent 508dd23de4
commit b323303518
5 changed files with 82 additions and 7 deletions

View File

@@ -98,12 +98,17 @@ void FileTransferPrivate::start()
return startFailed(tr("No files to transfer.")); return startFailed(tr("No files to transfer."));
const FileTransferDirection direction = transferDirection(m_setup.m_files); 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); IDeviceConstPtr device;
if (!device) if (direction != FileTransferDirection::Invalid)
return startFailed(tr("Trying to transfer into / from not matching device.")); device = matchedDevice(direction, m_setup.m_files);
if (!device) {
// Fall back to generic copy.
const FilePath &filePath = m_setup.m_files.first().m_target;
device = DeviceManager::deviceForPath(filePath);
m_setup.m_method = FileTransferMethod::GenericCopy;
}
run(m_setup, device); run(m_setup, device);
} }
@@ -190,6 +195,7 @@ QString FileTransfer::transferMethodName(FileTransferMethod method)
switch (method) { switch (method) {
case FileTransferMethod::Sftp: return FileTransfer::tr("sftp"); case FileTransferMethod::Sftp: return FileTransfer::tr("sftp");
case FileTransferMethod::Rsync: return FileTransfer::tr("rsync"); case FileTransferMethod::Rsync: return FileTransfer::tr("rsync");
case FileTransferMethod::GenericCopy: return FileTransfer::tr("generic file copy");
} }
QTC_CHECK(false); QTC_CHECK(false);
return {}; return {};

View File

@@ -20,6 +20,7 @@ enum class FileTransferDirection {
enum class FileTransferMethod { enum class FileTransferMethod {
Sftp, Sftp,
Rsync, Rsync,
GenericCopy,
Default = Sftp Default = Sftp
}; };

View File

@@ -1428,12 +1428,73 @@ private:
int m_currentIndex = 0; int m_currentIndex = 0;
}; };
class GenericTransferImpl : public FileTransferInterface
{
public:
GenericTransferImpl(const FileTransferSetupData &setup, LinuxDevicePrivate *)
: FileTransferInterface(setup)
{}
private:
void start() final
{
m_fileCount = m_setup.m_files.size();
m_currentIndex = 0;
m_checkedDirectories.clear();
nextFile();
}
void nextFile()
{
ProcessResultData result;
if (m_currentIndex >= m_fileCount) {
emit done(result);
return;
}
const FileToTransfer &file = m_setup.m_files.at(m_currentIndex);
const FilePath &source = file.m_source;
const FilePath &target = file.m_target;
++m_currentIndex;
const FilePath targetDir = target.parentDir();
if (!m_checkedDirectories.contains(targetDir)) {
emit progress(tr("Creating directory: %1")
.arg(targetDir.toUserOutput()));
if (!targetDir.ensureWritableDir()) {
result.m_errorString = tr("Failed.");
result.m_exitCode = -1; // Random pick
emit done(result);
return;
}
m_checkedDirectories.insert(targetDir);
}
emit progress(tr("Copying %1/%2: %3 -> %4")
.arg(m_currentIndex).arg(m_fileCount).arg(source.toUserOutput(), target.toUserOutput()));
if (!source.copyFile(target)) {
result.m_errorString = tr("Failed.");
result.m_exitCode = -1; // Random pick
emit done(result);
return;
}
// FIXME: Use asyncCopyFile instead
nextFile();
}
int m_currentIndex = 0;
int m_fileCount = 0;
QSet<FilePath> m_checkedDirectories;
};
FileTransferInterface *LinuxDevice::createFileTransferInterface( FileTransferInterface *LinuxDevice::createFileTransferInterface(
const FileTransferSetupData &setup) const const FileTransferSetupData &setup) const
{ {
switch (setup.m_method) { switch (setup.m_method) {
case FileTransferMethod::Sftp: return new SftpTransferImpl(setup, d); case FileTransferMethod::Sftp: return new SftpTransferImpl(setup, d);
case FileTransferMethod::Rsync: return new RsyncTransferImpl(setup, d); case FileTransferMethod::Rsync: return new RsyncTransferImpl(setup, d);
case FileTransferMethod::GenericCopy: return new GenericTransferImpl(setup, d);
} }
QTC_CHECK(false); QTC_CHECK(false);
return {}; return {};

View File

@@ -236,6 +236,7 @@ void GenericLinuxDeviceTester::testFileTransfer(FileTransferMethod method)
switch (method) { switch (method) {
case FileTransferMethod::Sftp: d->state = TestingSftp; break; case FileTransferMethod::Sftp: d->state = TestingSftp; break;
case FileTransferMethod::Rsync: d->state = TestingRsync; break; case FileTransferMethod::Rsync: d->state = TestingRsync; break;
case FileTransferMethod::GenericCopy: QTC_CHECK(false) /* not tested */; break;
} }
emit progressMessage(Tr::tr("Checking whether \"%1\" works...") emit progressMessage(Tr::tr("Checking whether \"%1\" works...")
.arg(FileTransfer::transferMethodName(method))); .arg(FileTransfer::transferMethodName(method)));

View File

@@ -39,6 +39,9 @@ RemoteLinuxDeployConfigurationFactory::RemoteLinuxDeployConfigurationFactory()
addInitialStep(Constants::MakeInstallStepId, needsMakeInstall); addInitialStep(Constants::MakeInstallStepId, needsMakeInstall);
addInitialStep(Constants::KillAppStepId); addInitialStep(Constants::KillAppStepId);
// Todo: Check: Instead of having two different steps here, have one
// and shift the logic into the implementation there?
addInitialStep(Constants::RsyncDeployStepId, [](Target *target) { addInitialStep(Constants::RsyncDeployStepId, [](Target *target) {
auto runDevice = DeviceKitAspect::device(target->kit()); auto runDevice = DeviceKitAspect::device(target->kit());
auto buildDevice = BuildDeviceKitAspect::device(target->kit()); auto buildDevice = BuildDeviceKitAspect::device(target->kit());
@@ -49,8 +52,11 @@ RemoteLinuxDeployConfigurationFactory::RemoteLinuxDeployConfigurationFactory()
return runDevice && runDevice->extraData(Constants::SupportsRSync).toBool(); return runDevice && runDevice->extraData(Constants::SupportsRSync).toBool();
}); });
addInitialStep(Constants::DirectUploadStepId, [](Target *target) { addInitialStep(Constants::DirectUploadStepId, [](Target *target) {
auto device = DeviceKitAspect::device(target->kit()); auto runDevice = DeviceKitAspect::device(target->kit());
return device && !device->extraData(Constants::SupportsRSync).toBool(); auto buildDevice = BuildDeviceKitAspect::device(target->kit());
if (runDevice == buildDevice)
return true;
return runDevice && !runDevice->extraData(Constants::SupportsRSync).toBool();
}); });
} }