LinuxDeviceTester: Test if required commands are available

Change-Id: Iaad3ec8667c4134ead86ca9e3239e810554b8f43
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Jarek Kobus
2022-05-31 18:03:05 +02:00
parent 53896ed295
commit af8f6dc039
2 changed files with 101 additions and 2 deletions

View File

@@ -42,7 +42,13 @@ namespace RemoteLinux {
namespace Internal { namespace Internal {
namespace { namespace {
enum State { Inactive, TestingEcho, TestingUname, TestingPorts, TestingSftp, TestingRsync }; enum State { Inactive,
TestingEcho,
TestingUname,
TestingPorts,
TestingSftp,
TestingRsync,
TestingCommands };
} // anonymous namespace } // anonymous namespace
@@ -56,8 +62,43 @@ public:
FileTransfer fileTransfer; FileTransfer fileTransfer;
State state = Inactive; State state = Inactive;
bool sftpWorks = false; bool sftpWorks = false;
int currentCommandIndex = 0;
bool commandFailed = false;
QtcProcess commandsProcess;
}; };
const QStringList s_commandsToTest = {"base64",
"cat",
"chmod",
"cp",
"cut",
"dd",
"df",
"echo",
"eval",
"exit",
"kill",
"ls",
"mkdir",
"mkfifo",
"mktemp",
"mv",
"printf",
"read",
"readlink",
"rm",
"sed",
"sh",
"shift",
"stat",
"tail",
"test",
"trap",
"touch",
"which"};
// other possible commands (checked for qnx):
// "awk", "grep", "netstat", "print", "pidin", "sleep", "uname"
} // namespace Internal } // namespace Internal
using namespace Internal; using namespace Internal;
@@ -75,6 +116,8 @@ GenericLinuxDeviceTester::GenericLinuxDeviceTester(QObject *parent)
this, &GenericLinuxDeviceTester::handlePortsGathererDone); this, &GenericLinuxDeviceTester::handlePortsGathererDone);
connect(&d->fileTransfer, &FileTransfer::done, connect(&d->fileTransfer, &FileTransfer::done,
this, &GenericLinuxDeviceTester::handleFileTransferDone); this, &GenericLinuxDeviceTester::handleFileTransferDone);
connect(&d->commandsProcess, &QtcProcess::done,
this, &GenericLinuxDeviceTester::handleCommandDone);
} }
GenericLinuxDeviceTester::~GenericLinuxDeviceTester() = default; GenericLinuxDeviceTester::~GenericLinuxDeviceTester() = default;
@@ -106,6 +149,9 @@ void GenericLinuxDeviceTester::stopTest()
case TestingRsync: case TestingRsync:
d->fileTransfer.stop(); d->fileTransfer.stop();
break; break;
case TestingCommands:
d->commandsProcess.close();
break;
case Inactive: case Inactive:
break; break;
} }
@@ -254,10 +300,59 @@ void GenericLinuxDeviceTester::handleFileTransferDone(const ProcessResultData &r
} }
} }
d->device->setExtraData(Constants::SupportsRSync, succeeded); d->device->setExtraData(Constants::SupportsRSync, succeeded);
setFinished(d->sftpWorks || succeeded ? TestSuccess : TestFailure); if (d->sftpWorks || succeeded)
testCommands();
else
setFinished(TestFailure);
} }
} }
void GenericLinuxDeviceTester::testCommands()
{
d->state = TestingCommands;
emit progressMessage(tr("Checking if required commands are available..."));
d->currentCommandIndex = 0;
d->commandFailed = false;
testNextCommand();
}
void GenericLinuxDeviceTester::testNextCommand()
{
d->commandsProcess.close();
if (s_commandsToTest.size() == d->currentCommandIndex) {
setFinished(d->commandFailed ? TestFailure : TestSuccess);
return;
}
const QString commandName = s_commandsToTest[d->currentCommandIndex];
emit progressMessage(tr("%1...").arg(commandName));
CommandLine command{d->device->filePath("/bin/sh"), {"-c"}};
command.addArgs(QLatin1String("\"command -v %1\"").arg(commandName), CommandLine::Raw);
d->commandsProcess.setCommand(command);
d->commandsProcess.start();
}
void GenericLinuxDeviceTester::handleCommandDone()
{
QTC_ASSERT(d->state == TestingCommands, return);
const QString command = s_commandsToTest[d->currentCommandIndex];
if (d->commandsProcess.result() == ProcessResult::FinishedWithSuccess) {
emit progressMessage(tr("%1 found.").arg(command));
} else {
d->commandFailed = true;
const QString message = d->commandsProcess.result() == ProcessResult::StartFailed
? tr("An error occurred while checking for %1.").arg(command)
+ '\n' + d->commandsProcess.errorString()
: tr("%1 not found.").arg(command);
emit errorMessage(message);
}
++d->currentCommandIndex;
testNextCommand();
}
void GenericLinuxDeviceTester::setFinished(TestResult result) void GenericLinuxDeviceTester::setFinished(TestResult result)
{ {
d->state = Inactive; d->state = Inactive;

View File

@@ -61,6 +61,10 @@ private:
void testFileTransfer(ProjectExplorer::FileTransferMethod method); void testFileTransfer(ProjectExplorer::FileTransferMethod method);
void handleFileTransferDone(const Utils::ProcessResultData &resultData); void handleFileTransferDone(const Utils::ProcessResultData &resultData);
void testCommands();
void testNextCommand();
void handleCommandDone();
void setFinished(ProjectExplorer::DeviceTester::TestResult result); void setFinished(ProjectExplorer::DeviceTester::TestResult result);
std::unique_ptr<Internal::GenericLinuxDeviceTesterPrivate> d; std::unique_ptr<Internal::GenericLinuxDeviceTesterPrivate> d;