forked from qt-creator/qt-creator
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:
@@ -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) {
|
||||||
|
@@ -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);
|
||||||
|
@@ -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);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user