GenericLinuxDeviceTester: Use FileTransfer for sftp and rsync

Make ProcessArgs::prepareCommand() return false in case
when executable is a relative path and it can't be found.

Amends 13067a7d9c

Change-Id: I0c4cf1580be34894df01245eb2411cdd7a122651
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
Jarek Kobus
2022-05-16 20:31:55 +02:00
parent 79cacd354d
commit c31285d317
3 changed files with 56 additions and 79 deletions

View File

@@ -658,6 +658,8 @@ bool ProcessArgs::prepareCommand(const CommandLine &cmdLine, QString *outCmd, Pr
const QString arguments = cmdLine.arguments(); const QString arguments = cmdLine.arguments();
if (env && executable.isRelativePath()) if (env && executable.isRelativePath())
executable = env->searchInPath(executable.toString()); executable = env->searchInPath(executable.toString());
if (executable.isEmpty())
return false;
ProcessArgs::SplitError err; ProcessArgs::SplitError err;
*outArgs = ProcessArgs::prepareArgs(arguments, &err, executable.osType(), env, pwd); *outArgs = ProcessArgs::prepareArgs(arguments, &err, executable.osType(), env, pwd);
if (err == ProcessArgs::SplitOk) { if (err == ProcessArgs::SplitOk) {

View File

@@ -25,15 +25,15 @@
#include "linuxdevicetester.h" #include "linuxdevicetester.h"
#include "filetransfer.h"
#include "remotelinux_constants.h" #include "remotelinux_constants.h"
#include "rsyncdeploystep.h"
#include <projectexplorer/devicesupport/deviceusedportsgatherer.h> #include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
#include <ssh/sftptransfer.h>
#include <ssh/sshconnection.h> #include <ssh/sshconnection.h>
#include <ssh/sshconnectionmanager.h> #include <ssh/sshconnectionmanager.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/port.h> #include <utils/port.h>
#include <utils/processinterface.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/qtcprocess.h> #include <utils/qtcprocess.h>
@@ -56,8 +56,7 @@ public:
SshConnection *connection = nullptr; SshConnection *connection = nullptr;
QtcProcess unameProcess; QtcProcess unameProcess;
DeviceUsedPortsGatherer portsGatherer; DeviceUsedPortsGatherer portsGatherer;
SftpTransferPtr sftpTransfer; FileTransfer fileTransfer;
QtcProcess rsyncProcess;
State state = Inactive; State state = Inactive;
bool sftpWorks = false; bool sftpWorks = false;
}; };
@@ -75,9 +74,8 @@ GenericLinuxDeviceTester::GenericLinuxDeviceTester(QObject *parent)
this, &GenericLinuxDeviceTester::handlePortsGathererError); this, &GenericLinuxDeviceTester::handlePortsGathererError);
connect(&d->portsGatherer, &DeviceUsedPortsGatherer::portListReady, connect(&d->portsGatherer, &DeviceUsedPortsGatherer::portListReady,
this, &GenericLinuxDeviceTester::handlePortsGathererDone); this, &GenericLinuxDeviceTester::handlePortsGathererDone);
connect(&d->rsyncProcess, &QtcProcess::done, this, connect(&d->fileTransfer, &FileTransfer::done,
&GenericLinuxDeviceTester::handleRsyncDone); this, &GenericLinuxDeviceTester::handleFileTransferDone);
SshConnectionParameters::setupSshEnvironment(&d->rsyncProcess);
} }
GenericLinuxDeviceTester::~GenericLinuxDeviceTester() GenericLinuxDeviceTester::~GenericLinuxDeviceTester()
@@ -91,6 +89,7 @@ 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);
SshConnectionManager::forceNewConnection(deviceConfiguration->sshParameters()); SshConnectionManager::forceNewConnection(deviceConfiguration->sshParameters());
d->connection = SshConnectionManager::acquireConnection(deviceConfiguration->sshParameters()); d->connection = SshConnectionManager::acquireConnection(deviceConfiguration->sshParameters());
connect(d->connection, &SshConnection::connected, connect(d->connection, &SshConnection::connected,
@@ -118,10 +117,8 @@ void GenericLinuxDeviceTester::stopTest()
d->unameProcess.close(); d->unameProcess.close();
break; break;
case TestingSftp: case TestingSftp:
d->sftpTransfer->stop();
break;
case TestingRsync: case TestingRsync:
d->rsyncProcess.close(); d->fileTransfer.stop();
break; break;
case Inactive: case Inactive:
break; break;
@@ -203,88 +200,65 @@ void GenericLinuxDeviceTester::handlePortsGathererDone()
.arg(portList) + QLatin1Char('\n')); .arg(portList) + QLatin1Char('\n'));
} }
testSftp(); testFileTransfer(FileTransferMethod::Sftp);
} }
void GenericLinuxDeviceTester::testSftp() void GenericLinuxDeviceTester::testFileTransfer(FileTransferMethod method)
{ {
d->state = TestingSftp; switch (method) {
emit progressMessage(tr("Checking whether an SFTP connection can be set up...")); case FileTransferMethod::Sftp: d->state = TestingSftp; break;
case FileTransferMethod::Rsync: d->state = TestingRsync; break;
d->sftpTransfer = d->connection->createDownload(FilesToTransfer());
connect(d->sftpTransfer.get(), &SftpTransfer::done,
this, &GenericLinuxDeviceTester::handleSftpDone);
d->sftpTransfer->start();
}
void GenericLinuxDeviceTester::handleSftpDone(const QString &error)
{
QTC_ASSERT(d->state == TestingSftp, return);
if (error.isEmpty()) {
d->sftpWorks = true;
emit progressMessage(tr("SFTP service available.\n"));
} else {
d->sftpWorks = false;
emit errorMessage(tr("Error setting up SFTP connection: %1\n").arg(error));
} }
disconnect(d->sftpTransfer.get(), nullptr, this, nullptr); emit progressMessage(tr("Checking whether \"%1\" works...")
.arg(FileTransfer::transferMethodName(method)));
testRsync(); d->fileTransfer.setTransferMethod(method);
d->fileTransfer.test();
} }
void GenericLinuxDeviceTester::testRsync() void GenericLinuxDeviceTester::handleFileTransferDone(const ProcessResultData &resultData)
{ {
d->state = TestingRsync; QTC_ASSERT(d->state == TestingSftp || d->state == TestingRsync, return);
emit progressMessage(tr("Checking whether rsync works..."));
const RsyncCommandLine cmdLine = RsyncDeployStep::rsyncCommand(*d->connection,
RsyncDeployStep::defaultFlags());
const QStringList args = QStringList(cmdLine.options)
<< "-n" << "--exclude=*" << (cmdLine.remoteHostSpec + ":/tmp");
d->rsyncProcess.setCommand(CommandLine("rsync", args));
d->rsyncProcess.start();
}
void GenericLinuxDeviceTester::handleRsyncDone()
{
QTC_ASSERT(d->state == TestingRsync, return);
bool succeeded = false;
QString error; QString error;
if (d->rsyncProcess.error() == QProcess::FailedToStart) { const QString methodName = FileTransfer::transferMethodName(d->fileTransfer.transferMethod());
error = tr("Failed to start rsync: %1\n").arg(d->rsyncProcess.errorString()); if (resultData.m_error == QProcess::FailedToStart) {
} else if (d->rsyncProcess.exitStatus() == QProcess::CrashExit) { error = tr("Failed to start \"%1\": %2\n").arg(methodName, resultData.m_errorString);
error = tr("rsync crashed.\n"); } else if (resultData.m_exitStatus == QProcess::CrashExit) {
} else if (d->rsyncProcess.exitCode() != 0) { error = tr("\"%1\" crashed.\n").arg(methodName);
error = tr("rsync failed with exit code %1: %2\n") } else if (resultData.m_exitCode != 0) {
.arg(d->rsyncProcess.exitCode()) error = tr("\"%1\" failed with exit code %2: %3\n")
.arg(QString::fromLocal8Bit(d->rsyncProcess.readAllStandardError())); .arg(methodName).arg(resultData.m_exitCode).arg(resultData.m_errorString);
}
TestResult result = TestSuccess;
if (!error.isEmpty()) {
emit errorMessage(error);
if (d->sftpWorks) {
emit progressMessage(tr("SFTP will be used for deployment, because rsync "
"is not available.\n"));
} else {
emit errorMessage(tr("Deployment to this device will not work out of the box.\n"));
result = TestFailure;
}
} else { } else {
emit progressMessage(tr("rsync is functional.\n")); succeeded = true;
} }
d->device->setExtraData(Constants::SupportsRSync, error.isEmpty()); if (succeeded)
setFinished(result); emit progressMessage(tr("\"%1\" is functional.\n").arg(methodName));
else
emit errorMessage(error);
if (d->state == TestingSftp) {
d->sftpWorks = succeeded;
testFileTransfer(FileTransferMethod::Rsync);
} else {
if (!succeeded) {
if (d->sftpWorks) {
emit progressMessage(tr("SFTP will be used for deployment, because rsync "
"is not available.\n"));
} else {
emit errorMessage(tr("Deployment to this device will not work out of the box.\n"));
}
}
d->device->setExtraData(Constants::SupportsRSync, succeeded);
setFinished(d->sftpWorks || succeeded ? TestSuccess : TestFailure);
}
} }
void GenericLinuxDeviceTester::setFinished(TestResult result) void GenericLinuxDeviceTester::setFinished(TestResult result)
{ {
d->state = Inactive; d->state = Inactive;
if (d->sftpTransfer) {
disconnect(d->sftpTransfer.get(), nullptr, this, nullptr);
d->sftpTransfer.release()->deleteLater();
}
if (d->connection) { if (d->connection) {
disconnect(d->connection, nullptr, this, nullptr); disconnect(d->connection, nullptr, this, nullptr);
SshConnectionManager::releaseConnection(d->connection); SshConnectionManager::releaseConnection(d->connection);

View File

@@ -27,8 +27,12 @@
#include "remotelinux_export.h" #include "remotelinux_export.h"
#include "filetransfer.h"
#include <projectexplorer/devicesupport/idevice.h> #include <projectexplorer/devicesupport/idevice.h>
namespace Utils { class ProcessResultData; }
namespace RemoteLinux { namespace RemoteLinux {
namespace Internal { class GenericLinuxDeviceTesterPrivate; } namespace Internal { class GenericLinuxDeviceTesterPrivate; }
@@ -55,11 +59,8 @@ private:
void handlePortsGathererError(const QString &message); void handlePortsGathererError(const QString &message);
void handlePortsGathererDone(); void handlePortsGathererDone();
void testSftp(); void testFileTransfer(FileTransferMethod method);
void handleSftpDone(const QString &error); void handleFileTransferDone(const Utils::ProcessResultData &resultData);
void testRsync();
void handleRsyncDone();
void setFinished(ProjectExplorer::DeviceTester::TestResult result); void setFinished(ProjectExplorer::DeviceTester::TestResult result);