forked from qt-creator/qt-creator
Ssh: Re-base SshProcess on top of QtcProcess
Change-Id: I266820e0e2ea12d6e4a5a83a679a7279fab9cd83 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -58,7 +58,7 @@ struct Command
|
|||||||
|
|
||||||
struct SftpSession::SftpSessionPrivate
|
struct SftpSession::SftpSessionPrivate
|
||||||
{
|
{
|
||||||
SshProcess sftpProc;
|
SshProcess sftpProc = {ProcessMode::Writer};
|
||||||
QStringList connectionArgs;
|
QStringList connectionArgs;
|
||||||
QByteArray output;
|
QByteArray output;
|
||||||
QQueue<Command> pendingCommands;
|
QQueue<Command> pendingCommands;
|
||||||
@@ -112,17 +112,17 @@ static QByteArray prompt() { return "sftp> "; }
|
|||||||
SftpSession::SftpSession(const QStringList &connectionArgs) : d(new SftpSessionPrivate)
|
SftpSession::SftpSession(const QStringList &connectionArgs) : d(new SftpSessionPrivate)
|
||||||
{
|
{
|
||||||
d->connectionArgs = connectionArgs;
|
d->connectionArgs = connectionArgs;
|
||||||
connect(&d->sftpProc, &QProcess::started, [this] {
|
connect(&d->sftpProc, &QtcProcess::started, [this] {
|
||||||
qCDebug(sshLog) << "sftp process started";
|
qCDebug(sshLog) << "sftp process started";
|
||||||
d->sftpProc.write("\n"); // Force initial prompt.
|
d->sftpProc.write("\n"); // Force initial prompt.
|
||||||
});
|
});
|
||||||
connect(&d->sftpProc, &QProcess::errorOccurred, [this](QProcess::ProcessError error) {
|
connect(&d->sftpProc, &QtcProcess::errorOccurred, [this](QProcess::ProcessError error) {
|
||||||
if (error == QProcess::FailedToStart) {
|
if (error == QProcess::FailedToStart) {
|
||||||
d->state = State::Inactive;
|
d->state = State::Inactive;
|
||||||
emit done(tr("sftp failed to start: %1").arg(d->sftpProc.errorString()));
|
emit done(tr("sftp failed to start: %1").arg(d->sftpProc.errorString()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
connect(&d->sftpProc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), [this] {
|
connect(&d->sftpProc, &QtcProcess::finished, [this] {
|
||||||
qCDebug(sshLog) << "sftp process finished";
|
qCDebug(sshLog) << "sftp process finished";
|
||||||
|
|
||||||
d->state = State::Inactive;
|
d->state = State::Inactive;
|
||||||
@@ -136,7 +136,7 @@ SftpSession::SftpSession(const QStringList &connectionArgs) : d(new SftpSessionP
|
|||||||
}
|
}
|
||||||
emit done(QString());
|
emit done(QString());
|
||||||
});
|
});
|
||||||
connect(&d->sftpProc, &QProcess::readyReadStandardOutput, this, &SftpSession::handleStdout);
|
connect(&d->sftpProc, &QtcProcess::readyReadStandardOutput, this, &SftpSession::handleStdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SftpSession::doStart()
|
void SftpSession::doStart()
|
||||||
@@ -153,7 +153,8 @@ void SftpSession::doStart()
|
|||||||
d->activeCommand = Command();
|
d->activeCommand = Command();
|
||||||
const QStringList args = QStringList{"-q"} << d->connectionArgs;
|
const QStringList args = QStringList{"-q"} << d->connectionArgs;
|
||||||
qCDebug(sshLog) << "starting sftp session:" << sftpBinary.toUserOutput() << args;
|
qCDebug(sshLog) << "starting sftp session:" << sftpBinary.toUserOutput() << args;
|
||||||
d->sftpProc.start(sftpBinary.toString(), args);
|
d->sftpProc.setCommand(CommandLine(sftpBinary, args));
|
||||||
|
d->sftpProc.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SftpSession::handleStdout()
|
void SftpSession::handleStdout()
|
||||||
|
@@ -113,11 +113,11 @@ SftpTransfer::SftpTransfer(const FilesToTransfer &files, Internal::FileTransferT
|
|||||||
d->transferType = type;
|
d->transferType = type;
|
||||||
d->errorHandlingMode = errorHandlingMode;
|
d->errorHandlingMode = errorHandlingMode;
|
||||||
d->connectionArgs = connectionArgs;
|
d->connectionArgs = connectionArgs;
|
||||||
connect(&d->sftpProc, &QProcess::errorOccurred, [this](QProcess::ProcessError error) {
|
connect(&d->sftpProc, &QtcProcess::errorOccurred, [this](QProcess::ProcessError error) {
|
||||||
if (error == QProcess::FailedToStart)
|
if (error == QProcess::FailedToStart)
|
||||||
emitError(tr("sftp failed to start: %1").arg(d->sftpProc.errorString()));
|
emitError(tr("sftp failed to start: %1").arg(d->sftpProc.errorString()));
|
||||||
});
|
});
|
||||||
connect(&d->sftpProc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), [this] {
|
connect(&d->sftpProc, &QtcProcess::finished, [this] {
|
||||||
if (d->sftpProc.exitStatus() != QProcess::NormalExit) {
|
if (d->sftpProc.exitStatus() != QProcess::NormalExit) {
|
||||||
emitError(tr("sftp crashed."));
|
emitError(tr("sftp crashed."));
|
||||||
return;
|
return;
|
||||||
@@ -128,7 +128,7 @@ SftpTransfer::SftpTransfer(const FilesToTransfer &files, Internal::FileTransferT
|
|||||||
}
|
}
|
||||||
emit done(QString());
|
emit done(QString());
|
||||||
});
|
});
|
||||||
connect(&d->sftpProc, &QProcess::readyReadStandardOutput, [this] {
|
connect(&d->sftpProc, &QtcProcess::readyReadStandardOutput, [this] {
|
||||||
emit progress(QString::fromLocal8Bit(d->sftpProc.readAllStandardOutput()));
|
emit progress(QString::fromLocal8Bit(d->sftpProc.readAllStandardOutput()));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -179,7 +179,8 @@ void SftpTransfer::doStart()
|
|||||||
+ ProcessArgs::quoteArgUnix(f.targetFile).toLocal8Bit() + '\n');
|
+ ProcessArgs::quoteArgUnix(f.targetFile).toLocal8Bit() + '\n');
|
||||||
}
|
}
|
||||||
d->sftpProc.setStandardInputFile(batchFile.fileName());
|
d->sftpProc.setStandardInputFile(batchFile.fileName());
|
||||||
d->sftpProc.start(sftpBinary.toString(), d->connectionArgs);
|
d->sftpProc.setCommand(CommandLine(sftpBinary, d->connectionArgs));
|
||||||
|
d->sftpProc.start();
|
||||||
emit started();
|
emit started();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -167,7 +167,7 @@ SshConnection::SshConnection(const SshConnectionParameters &serverInfo, QObject
|
|||||||
qRegisterMetaType<QSsh::SftpFileInfo>("QSsh::SftpFileInfo");
|
qRegisterMetaType<QSsh::SftpFileInfo>("QSsh::SftpFileInfo");
|
||||||
qRegisterMetaType<QList <QSsh::SftpFileInfo> >("QList<QSsh::SftpFileInfo>");
|
qRegisterMetaType<QList <QSsh::SftpFileInfo> >("QList<QSsh::SftpFileInfo>");
|
||||||
d->connParams = serverInfo;
|
d->connParams = serverInfo;
|
||||||
connect(&d->masterProcess, &QProcess::started, [this] {
|
connect(&d->masterProcess, &QtcProcess::started, [this] {
|
||||||
QFileInfo socketInfo(d->socketFilePath());
|
QFileInfo socketInfo(d->socketFilePath());
|
||||||
if (socketInfo.exists()) {
|
if (socketInfo.exists()) {
|
||||||
emitConnected();
|
emitConnected();
|
||||||
@@ -194,7 +194,7 @@ SshConnection::SshConnection(const SshConnectionParameters &serverInfo, QObject
|
|||||||
socketWatcherTimer->start();
|
socketWatcherTimer->start();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
connect(&d->masterProcess, &QProcess::errorOccurred, [this] (QProcess::ProcessError error) {
|
connect(&d->masterProcess, &QtcProcess::errorOccurred, [this] (QProcess::ProcessError error) {
|
||||||
switch (error) {
|
switch (error) {
|
||||||
case QProcess::FailedToStart:
|
case QProcess::FailedToStart:
|
||||||
emitError(tr("Cannot establish SSH connection: Control process failed to start: %1")
|
emitError(tr("Cannot establish SSH connection: Control process failed to start: %1")
|
||||||
@@ -208,7 +208,7 @@ SshConnection::SshConnection(const SshConnectionParameters &serverInfo, QObject
|
|||||||
break; // Cannot happen.
|
break; // Cannot happen.
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
connect(&d->masterProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), [this] {
|
connect(&d->masterProcess, &QtcProcess::finished, [this] {
|
||||||
if (d->state == Disconnecting) {
|
if (d->state == Disconnecting) {
|
||||||
emitDisconnected();
|
emitDisconnected();
|
||||||
return;
|
return;
|
||||||
@@ -220,9 +220,9 @@ SshConnection::SshConnection(const SshConnectionParameters &serverInfo, QObject
|
|||||||
emitError(errorMsg);
|
emitError(errorMsg);
|
||||||
});
|
});
|
||||||
if (!d->connParams.x11DisplayName.isEmpty()) {
|
if (!d->connParams.x11DisplayName.isEmpty()) {
|
||||||
QProcessEnvironment env = d->masterProcess.processEnvironment();
|
Environment env = d->masterProcess.environment();
|
||||||
env.insert("DISPLAY", d->connParams.x11DisplayName);
|
env.set("DISPLAY", d->connParams.x11DisplayName);
|
||||||
d->masterProcess.setProcessEnvironment(env);
|
d->masterProcess.setEnvironment(env);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,16 +316,17 @@ SshConnection::~SshConnection()
|
|||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
SshRemoteProcessPtr SshConnection::createRemoteProcess(const QString &command)
|
SshRemoteProcessPtr SshConnection::createRemoteProcess(const QString &command, ProcessMode processMode)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(state() == Connected, return SshRemoteProcessPtr());
|
QTC_ASSERT(state() == Connected, return SshRemoteProcessPtr());
|
||||||
return SshRemoteProcessPtr(new SshRemoteProcess(command,
|
return SshRemoteProcessPtr(new SshRemoteProcess(command,
|
||||||
d->connectionArgs(SshSettings::sshFilePath())));
|
d->connectionArgs(SshSettings::sshFilePath()),
|
||||||
|
processMode));
|
||||||
}
|
}
|
||||||
|
|
||||||
SshRemoteProcessPtr SshConnection::createRemoteShell()
|
SshRemoteProcessPtr SshConnection::createRemoteShell(ProcessMode processMode)
|
||||||
{
|
{
|
||||||
return createRemoteProcess({});
|
return createRemoteProcess({}, processMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
SftpTransferPtr SshConnection::createUpload(const FilesToTransfer &files,
|
SftpTransferPtr SshConnection::createUpload(const FilesToTransfer &files,
|
||||||
@@ -372,7 +373,8 @@ void SshConnection::doConnectToHost()
|
|||||||
if (!d->connParams.x11DisplayName.isEmpty())
|
if (!d->connParams.x11DisplayName.isEmpty())
|
||||||
args.prepend("-X");
|
args.prepend("-X");
|
||||||
qCDebug(sshLog) << "establishing connection:" << sshBinary.toUserOutput() << args;
|
qCDebug(sshLog) << "establishing connection:" << sshBinary.toUserOutput() << args;
|
||||||
d->masterProcess.start(sshBinary.toString(), args);
|
d->masterProcess.setCommand(CommandLine(sshBinary, args));
|
||||||
|
d->masterProcess.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SshConnection::emitError(const QString &reason)
|
void SshConnection::emitError(const QString &reason)
|
||||||
|
@@ -28,6 +28,8 @@
|
|||||||
#include "sftpdefs.h"
|
#include "sftpdefs.h"
|
||||||
#include "ssh_global.h"
|
#include "ssh_global.h"
|
||||||
|
|
||||||
|
#include <utils/processutils.h>
|
||||||
|
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
#include <QFlags>
|
#include <QFlags>
|
||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
@@ -113,8 +115,10 @@ public:
|
|||||||
bool sharingEnabled() const;
|
bool sharingEnabled() const;
|
||||||
~SshConnection();
|
~SshConnection();
|
||||||
|
|
||||||
SshRemoteProcessPtr createRemoteProcess(const QString &command);
|
SshRemoteProcessPtr createRemoteProcess(const QString &command, Utils::ProcessMode processMode
|
||||||
SshRemoteProcessPtr createRemoteShell();
|
= Utils::ProcessMode::Reader);
|
||||||
|
SshRemoteProcessPtr createRemoteShell(Utils::ProcessMode processMode
|
||||||
|
= Utils::ProcessMode::Reader);
|
||||||
SftpTransferPtr createUpload(const FilesToTransfer &files,
|
SftpTransferPtr createUpload(const FilesToTransfer &files,
|
||||||
FileTransferErrorHandling errorHandlingMode);
|
FileTransferErrorHandling errorHandlingMode);
|
||||||
SftpTransferPtr createDownload(const FilesToTransfer &files,
|
SftpTransferPtr createDownload(const FilesToTransfer &files,
|
||||||
|
@@ -36,7 +36,8 @@
|
|||||||
|
|
||||||
namespace QSsh {
|
namespace QSsh {
|
||||||
|
|
||||||
SshProcess::SshProcess()
|
SshProcess::SshProcess(Utils::ProcessMode processMode)
|
||||||
|
: Utils::QtcProcess(processMode)
|
||||||
{
|
{
|
||||||
Utils::Environment env = Utils::Environment::systemEnvironment();
|
Utils::Environment env = Utils::Environment::systemEnvironment();
|
||||||
if (SshSettings::askpassFilePath().exists()) {
|
if (SshSettings::askpassFilePath().exists()) {
|
||||||
@@ -46,37 +47,10 @@ SshProcess::SshProcess()
|
|||||||
if (!env.hasKey("DISPLAY"))
|
if (!env.hasKey("DISPLAY"))
|
||||||
env.set("DISPLAY", ":0");
|
env.set("DISPLAY", ":0");
|
||||||
}
|
}
|
||||||
setProcessEnvironment(env.toProcessEnvironment());
|
setEnvironment(env);
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) && defined(Q_OS_UNIX)
|
|
||||||
setChildProcessModifier([this] { setupChildProcess_impl(); });
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
SshProcess::~SshProcess()
|
// Otherwise, ssh will ignore SSH_ASKPASS and read from /dev/tty directly.
|
||||||
{
|
setDisableUnixTerminal();
|
||||||
if (state() == QProcess::NotRunning)
|
|
||||||
return;
|
|
||||||
disconnect();
|
|
||||||
terminate();
|
|
||||||
waitForFinished(1000);
|
|
||||||
if (state() == QProcess::NotRunning)
|
|
||||||
return;
|
|
||||||
kill();
|
|
||||||
waitForFinished(1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
void SshProcess::setupChildProcess()
|
|
||||||
{
|
|
||||||
setupChildProcess_impl();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void SshProcess::setupChildProcess_impl()
|
|
||||||
{
|
|
||||||
#ifdef Q_OS_UNIX
|
|
||||||
setsid(); // Otherwise, ssh will ignore SSH_ASKPASS and read from /dev/tty directly.
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace QSsh
|
} // namespace QSsh
|
||||||
|
@@ -27,22 +27,14 @@
|
|||||||
|
|
||||||
#include "ssh_global.h"
|
#include "ssh_global.h"
|
||||||
|
|
||||||
#include <QProcess>
|
#include <utils/qtcprocess.h>
|
||||||
|
|
||||||
namespace QSsh {
|
namespace QSsh {
|
||||||
|
|
||||||
class QSSH_EXPORT SshProcess : public QProcess
|
class QSSH_EXPORT SshProcess : public Utils::QtcProcess
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SshProcess();
|
SshProcess(Utils::ProcessMode processMode = Utils::ProcessMode::Reader);
|
||||||
~SshProcess() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
void setupChildProcess() override;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void setupChildProcess_impl();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QSsh
|
} // namespace QSsh
|
||||||
|
@@ -60,13 +60,15 @@ struct SshRemoteProcess::SshRemoteProcessPrivate
|
|||||||
bool useTerminal = false;
|
bool useTerminal = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
SshRemoteProcess::SshRemoteProcess(const QString &command, const QStringList &connectionArgs)
|
SshRemoteProcess::SshRemoteProcess(const QString &command, const QStringList &connectionArgs,
|
||||||
: d(new SshRemoteProcessPrivate)
|
Utils::ProcessMode processMode)
|
||||||
|
: SshProcess(processMode)
|
||||||
|
, d(new SshRemoteProcessPrivate)
|
||||||
{
|
{
|
||||||
d->remoteCommand = command;
|
d->remoteCommand = command;
|
||||||
d->connectionArgs = connectionArgs;
|
d->connectionArgs = connectionArgs;
|
||||||
|
|
||||||
connect(this, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this] {
|
connect(this, &QtcProcess::finished, this, [this] {
|
||||||
QString error;
|
QString error;
|
||||||
if (exitStatus() == QProcess::CrashExit)
|
if (exitStatus() == QProcess::CrashExit)
|
||||||
error = tr("The ssh process crashed: %1").arg(errorString());
|
error = tr("The ssh process crashed: %1").arg(errorString());
|
||||||
@@ -74,7 +76,7 @@ SshRemoteProcess::SshRemoteProcess(const QString &command, const QStringList &co
|
|||||||
error = tr("Remote process crashed.");
|
error = tr("Remote process crashed.");
|
||||||
emit done(error);
|
emit done(error);
|
||||||
});
|
});
|
||||||
connect(this, &QProcess::errorOccurred, [this](QProcess::ProcessError error) {
|
connect(this, &QtcProcess::errorOccurred, [this](QProcess::ProcessError error) {
|
||||||
if (error == QProcess::FailedToStart)
|
if (error == QProcess::FailedToStart)
|
||||||
emit done(errorString());
|
emit done(errorString());
|
||||||
});
|
});
|
||||||
@@ -85,12 +87,13 @@ void SshRemoteProcess::doStart()
|
|||||||
QTC_ASSERT(!isRunning(), return);
|
QTC_ASSERT(!isRunning(), return);
|
||||||
const Utils::CommandLine cmd = fullLocalCommandLine();
|
const Utils::CommandLine cmd = fullLocalCommandLine();
|
||||||
if (!d->displayName.isEmpty()) {
|
if (!d->displayName.isEmpty()) {
|
||||||
QProcessEnvironment env = processEnvironment();
|
Utils::Environment env = environment();
|
||||||
env.insert("DISPLAY", d->displayName);
|
env.set("DISPLAY", d->displayName);
|
||||||
setProcessEnvironment(env);
|
setEnvironment(env);
|
||||||
}
|
}
|
||||||
qCDebug(sshLog) << "starting remote process:" << cmd.toUserOutput();
|
qCDebug(sshLog) << "starting remote process:" << cmd.toUserOutput();
|
||||||
QProcess::start(cmd.executable().toString(), cmd.splitArguments());
|
setCommand(cmd);
|
||||||
|
QtcProcess::start();
|
||||||
}
|
}
|
||||||
|
|
||||||
SshRemoteProcess::~SshRemoteProcess()
|
SshRemoteProcess::~SshRemoteProcess()
|
||||||
@@ -110,7 +113,7 @@ void SshRemoteProcess::requestX11Forwarding(const QString &displayName)
|
|||||||
|
|
||||||
void SshRemoteProcess::start()
|
void SshRemoteProcess::start()
|
||||||
{
|
{
|
||||||
QTimer::singleShot(0, this, &SshRemoteProcess::doStart);
|
doStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SshRemoteProcess::isRunning() const
|
bool SshRemoteProcess::isRunning() const
|
||||||
|
@@ -54,7 +54,8 @@ signals:
|
|||||||
void done(const QString &error);
|
void done(const QString &error);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SshRemoteProcess(const QString &command, const QStringList &connectionArgs);
|
SshRemoteProcess(const QString &command, const QStringList &connectionArgs,
|
||||||
|
Utils::ProcessMode processMode = Utils::ProcessMode::Reader);
|
||||||
void doStart();
|
void doStart();
|
||||||
|
|
||||||
struct SshRemoteProcessPrivate;
|
struct SshRemoteProcessPrivate;
|
||||||
|
@@ -186,7 +186,7 @@ void SshRemoteProcessRunner::setState(int newState)
|
|||||||
if (d->m_process) {
|
if (d->m_process) {
|
||||||
disconnect(d->m_process.get(), nullptr, this, nullptr);
|
disconnect(d->m_process.get(), nullptr, this, nullptr);
|
||||||
d->m_process->terminate();
|
d->m_process->terminate();
|
||||||
d->m_process.release()->deleteLater();
|
d->m_process.reset();
|
||||||
}
|
}
|
||||||
if (d->m_connection) {
|
if (d->m_connection) {
|
||||||
disconnect(d->m_connection, nullptr, this, nullptr);
|
disconnect(d->m_connection, nullptr, this, nullptr);
|
||||||
@@ -206,7 +206,7 @@ bool SshRemoteProcessRunner::isProcessRunning() const
|
|||||||
return d->m_process && d->m_process->isRunning();
|
return d->m_process && d->m_process->isRunning();
|
||||||
}
|
}
|
||||||
|
|
||||||
SshRemoteProcess::ExitStatus SshRemoteProcessRunner::processExitStatus() const
|
QProcess::ExitStatus SshRemoteProcessRunner::processExitStatus() const
|
||||||
{
|
{
|
||||||
QTC_CHECK(!isProcessRunning());
|
QTC_CHECK(!isProcessRunning());
|
||||||
return d->m_exitStatus;
|
return d->m_exitStatus;
|
||||||
@@ -214,7 +214,7 @@ SshRemoteProcess::ExitStatus SshRemoteProcessRunner::processExitStatus() const
|
|||||||
|
|
||||||
int SshRemoteProcessRunner::processExitCode() const
|
int SshRemoteProcessRunner::processExitCode() const
|
||||||
{
|
{
|
||||||
QTC_CHECK(processExitStatus() == SshRemoteProcess::NormalExit);
|
QTC_CHECK(processExitStatus() == QProcess::NormalExit);
|
||||||
return d->m_exitCode;
|
return d->m_exitCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -48,7 +48,7 @@ public:
|
|||||||
bool isProcessRunning() const;
|
bool isProcessRunning() const;
|
||||||
void writeDataToProcess(const QByteArray &data);
|
void writeDataToProcess(const QByteArray &data);
|
||||||
void cancel();
|
void cancel();
|
||||||
SshRemoteProcess::ExitStatus processExitStatus() const;
|
QProcess::ExitStatus processExitStatus() const;
|
||||||
int processExitCode() const;
|
int processExitCode() const;
|
||||||
QString processErrorString() const;
|
QString processErrorString() const;
|
||||||
QByteArray readAllStandardOutput();
|
QByteArray readAllStandardOutput();
|
||||||
|
@@ -149,7 +149,7 @@ QProcess::ProcessState SshDeviceProcess::state() const
|
|||||||
|
|
||||||
QProcess::ExitStatus SshDeviceProcess::exitStatus() const
|
QProcess::ExitStatus SshDeviceProcess::exitStatus() const
|
||||||
{
|
{
|
||||||
return d->exitStatus == QSsh::SshRemoteProcess::NormalExit && d->exitCode != 255
|
return d->exitStatus == QProcess::NormalExit && d->exitCode != 255
|
||||||
? QProcess::NormalExit : QProcess::CrashExit;
|
? QProcess::NormalExit : QProcess::CrashExit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,7 +237,7 @@ void SshDeviceProcess::handleDisconnected()
|
|||||||
emit error(QProcess::FailedToStart);
|
emit error(QProcess::FailedToStart);
|
||||||
break;
|
break;
|
||||||
case SshDeviceProcessPrivate::ProcessRunning:
|
case SshDeviceProcessPrivate::ProcessRunning:
|
||||||
d->exitStatus = QSsh::SshRemoteProcess::CrashExit;
|
d->exitStatus = QProcess::CrashExit;
|
||||||
emit finished();
|
emit finished();
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -284,7 +284,7 @@ void SshDeviceProcess::handleKillOperationFinished(const QString &errorMessage)
|
|||||||
if (errorMessage.isEmpty()) // Process will finish as expected; nothing to do here.
|
if (errorMessage.isEmpty()) // Process will finish as expected; nothing to do here.
|
||||||
return;
|
return;
|
||||||
|
|
||||||
d->exitStatus = QSsh::SshRemoteProcess::CrashExit; // Not entirely true, but it will get the message across.
|
d->exitStatus = QProcess::CrashExit; // Not entirely true, but it will get the message across.
|
||||||
d->errorMessage = tr("Failed to kill remote process: %1").arg(errorMessage);
|
d->errorMessage = tr("Failed to kill remote process: %1").arg(errorMessage);
|
||||||
d->setState(SshDeviceProcessPrivate::Inactive);
|
d->setState(SshDeviceProcessPrivate::Inactive);
|
||||||
emit finished();
|
emit finished();
|
||||||
@@ -292,7 +292,7 @@ void SshDeviceProcess::handleKillOperationFinished(const QString &errorMessage)
|
|||||||
|
|
||||||
void SshDeviceProcess::handleKillOperationTimeout()
|
void SshDeviceProcess::handleKillOperationTimeout()
|
||||||
{
|
{
|
||||||
d->exitStatus = QSsh::SshRemoteProcess::CrashExit; // Not entirely true, but it will get the message across.
|
d->exitStatus = QProcess::CrashExit; // Not entirely true, but it will get the message across.
|
||||||
d->errorMessage = tr("Timeout waiting for remote process to finish.");
|
d->errorMessage = tr("Timeout waiting for remote process to finish.");
|
||||||
d->setState(SshDeviceProcessPrivate::Inactive);
|
d->setState(SshDeviceProcessPrivate::Inactive);
|
||||||
emit finished();
|
emit finished();
|
||||||
|
@@ -220,19 +220,19 @@ void GenericLinuxDeviceTester::handleSftpFinished(const QString &error)
|
|||||||
void GenericLinuxDeviceTester::testRsync()
|
void GenericLinuxDeviceTester::testRsync()
|
||||||
{
|
{
|
||||||
emit progressMessage(tr("Checking whether rsync works..."));
|
emit progressMessage(tr("Checking whether rsync works..."));
|
||||||
connect(&d->rsyncProcess, &QProcess::errorOccurred, [this] {
|
connect(&d->rsyncProcess, &Utils::QtcProcess::errorOccurred, [this] {
|
||||||
if (d->rsyncProcess.error() == QProcess::FailedToStart)
|
if (d->rsyncProcess.error() == QProcess::FailedToStart)
|
||||||
handleRsyncFinished();
|
handleRsyncFinished();
|
||||||
});
|
});
|
||||||
connect(&d->rsyncProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
connect(&d->rsyncProcess, &Utils::QtcProcess::finished, this, [this] {
|
||||||
this, [this] {
|
|
||||||
handleRsyncFinished();
|
handleRsyncFinished();
|
||||||
});
|
});
|
||||||
const RsyncCommandLine cmdLine = RsyncDeployStep::rsyncCommand(*d->connection,
|
const RsyncCommandLine cmdLine = RsyncDeployStep::rsyncCommand(*d->connection,
|
||||||
RsyncDeployStep::defaultFlags());
|
RsyncDeployStep::defaultFlags());
|
||||||
const QStringList args = QStringList(cmdLine.options)
|
const QStringList args = QStringList(cmdLine.options)
|
||||||
<< "-n" << "--exclude=*" << (cmdLine.remoteHostSpec + ":/tmp");
|
<< "-n" << "--exclude=*" << (cmdLine.remoteHostSpec + ":/tmp");
|
||||||
d->rsyncProcess.start("rsync", args);
|
d->rsyncProcess.setCommand(Utils::CommandLine("rsync", args));
|
||||||
|
d->rsyncProcess.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericLinuxDeviceTester::handleRsyncFinished()
|
void GenericLinuxDeviceTester::handleRsyncFinished()
|
||||||
|
@@ -119,7 +119,7 @@ void RemoteLinuxSignalOperation::interruptProcess(const QString &filePath)
|
|||||||
void RemoteLinuxSignalOperation::runnerProcessFinished()
|
void RemoteLinuxSignalOperation::runnerProcessFinished()
|
||||||
{
|
{
|
||||||
m_errorMessage.clear();
|
m_errorMessage.clear();
|
||||||
if (m_runner->processExitStatus() != QSsh::SshRemoteProcess::NormalExit) {
|
if (m_runner->processExitStatus() != QProcess::NormalExit) {
|
||||||
m_errorMessage = m_runner->processErrorString();
|
m_errorMessage = m_runner->processErrorString();
|
||||||
} else if (m_runner->processExitCode() != 0) {
|
} else if (m_runner->processExitCode() != 0) {
|
||||||
m_errorMessage = tr("Exit code is %1. stderr:").arg(m_runner->processExitCode())
|
m_errorMessage = tr("Exit code is %1. stderr:").arg(m_runner->processExitCode())
|
||||||
|
@@ -123,19 +123,19 @@ void RsyncDeployService::createRemoteDirectories()
|
|||||||
|
|
||||||
void RsyncDeployService::deployFiles()
|
void RsyncDeployService::deployFiles()
|
||||||
{
|
{
|
||||||
connect(&m_rsync, &QProcess::readyReadStandardOutput, this, [this] {
|
connect(&m_rsync, &QtcProcess::readyReadStandardOutput, this, [this] {
|
||||||
emit progressMessage(QString::fromLocal8Bit(m_rsync.readAllStandardOutput()));
|
emit progressMessage(QString::fromLocal8Bit(m_rsync.readAllStandardOutput()));
|
||||||
});
|
});
|
||||||
connect(&m_rsync, &QProcess::readyReadStandardError, this, [this] {
|
connect(&m_rsync, &QtcProcess::readyReadStandardError, this, [this] {
|
||||||
emit warningMessage(QString::fromLocal8Bit(m_rsync.readAllStandardError()));
|
emit warningMessage(QString::fromLocal8Bit(m_rsync.readAllStandardError()));
|
||||||
});
|
});
|
||||||
connect(&m_rsync, &QProcess::errorOccurred, this, [this] {
|
connect(&m_rsync, &QtcProcess::errorOccurred, this, [this] {
|
||||||
if (m_rsync.error() == QProcess::FailedToStart) {
|
if (m_rsync.error() == QProcess::FailedToStart) {
|
||||||
emit errorMessage(tr("rsync failed to start: %1").arg(m_rsync.errorString()));
|
emit errorMessage(tr("rsync failed to start: %1").arg(m_rsync.errorString()));
|
||||||
setFinished();
|
setFinished();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
connect(&m_rsync, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this] {
|
connect(&m_rsync, &QtcProcess::finished, this, [this] {
|
||||||
if (m_rsync.exitStatus() == QProcess::CrashExit) {
|
if (m_rsync.exitStatus() == QProcess::CrashExit) {
|
||||||
emit errorMessage(tr("rsync crashed."));
|
emit errorMessage(tr("rsync crashed."));
|
||||||
setFinished();
|
setFinished();
|
||||||
@@ -173,7 +173,8 @@ void RsyncDeployService::deployNextFile()
|
|||||||
const QStringList args = QStringList(cmdLine.options)
|
const QStringList args = QStringList(cmdLine.options)
|
||||||
<< (localFilePath + (file.localFilePath().isDir() ? "/" : QString()))
|
<< (localFilePath + (file.localFilePath().isDir() ? "/" : QString()))
|
||||||
<< (cmdLine.remoteHostSpec + ':' + file.remoteFilePath());
|
<< (cmdLine.remoteHostSpec + ':' + file.remoteFilePath());
|
||||||
m_rsync.start("rsync", args); // TODO: Get rsync location from settings?
|
m_rsync.setCommand(CommandLine("rsync", args));
|
||||||
|
m_rsync.start(); // TODO: Get rsync location from settings?
|
||||||
}
|
}
|
||||||
|
|
||||||
void RsyncDeployService::setFinished()
|
void RsyncDeployService::setFinished()
|
||||||
|
@@ -1,4 +1,8 @@
|
|||||||
|
file(RELATIVE_PATH RELATIVE_TEST_PATH "${PROJECT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
|
file(RELATIVE_PATH TEST_RELATIVE_LIBEXEC_PATH "/${RELATIVE_TEST_PATH}" "/${IDE_LIBEXEC_PATH}")
|
||||||
|
|
||||||
add_qtc_test(tst_ssh
|
add_qtc_test(tst_ssh
|
||||||
|
DEFINES "TEST_RELATIVE_LIBEXEC_PATH=\"${TEST_RELATIVE_LIBEXEC_PATH}\""
|
||||||
DEPENDS Utils QtcSsh
|
DEPENDS Utils QtcSsh
|
||||||
SOURCES tst_ssh.cpp
|
SOURCES tst_ssh.cpp
|
||||||
)
|
)
|
||||||
|
@@ -2,4 +2,8 @@ QT = core network
|
|||||||
QTC_LIB_DEPENDS += ssh utils
|
QTC_LIB_DEPENDS += ssh utils
|
||||||
include(../qttest.pri)
|
include(../qttest.pri)
|
||||||
|
|
||||||
|
TEST_RELATIVE_LIBEXEC_PATH = $$relative_path($$IDE_LIBEXEC_PATH, $$OUT_PWD)
|
||||||
|
win32:TEST_RELATIVE_LIBEXEC_PATH=../$$TEST_RELATIVE_LIBEXEC_PATH
|
||||||
|
DEFINES += 'TEST_RELATIVE_LIBEXEC_PATH="\\\"$$TEST_RELATIVE_LIBEXEC_PATH\\\""'
|
||||||
|
|
||||||
SOURCES += tst_ssh.cpp
|
SOURCES += tst_ssh.cpp
|
||||||
|
@@ -1,8 +1,16 @@
|
|||||||
import qbs
|
import qbs.FileInfo
|
||||||
|
|
||||||
QtcAutotest {
|
QtcAutotest {
|
||||||
name: "SSH autotest"
|
name: "SSH autotest"
|
||||||
Depends { name: "QtcSsh" }
|
Depends { name: "QtcSsh" }
|
||||||
Depends { name: "Utils" }
|
Depends { name: "Utils" }
|
||||||
files: "tst_ssh.cpp"
|
files: "tst_ssh.cpp"
|
||||||
|
cpp.defines: {
|
||||||
|
var defines = base;
|
||||||
|
var absLibExecPath = FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix,
|
||||||
|
qtc.ide_libexec_path);
|
||||||
|
var relLibExecPath = FileInfo.relativePath(destinationDirectory, absLibExecPath);
|
||||||
|
defines.push('TEST_RELATIVE_LIBEXEC_PATH="' + relLibExecPath + '"');
|
||||||
|
return defines;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -29,8 +29,12 @@
|
|||||||
#include <ssh/sshconnectionmanager.h>
|
#include <ssh/sshconnectionmanager.h>
|
||||||
#include <ssh/sshremoteprocessrunner.h>
|
#include <ssh/sshremoteprocessrunner.h>
|
||||||
#include <ssh/sshsettings.h>
|
#include <ssh/sshsettings.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
|
#include <utils/launcherinterface.h>
|
||||||
|
#include <utils/processreaper.h>
|
||||||
|
#include <utils/qtcprocess.h>
|
||||||
#include <utils/temporarydirectory.h>
|
#include <utils/temporarydirectory.h>
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
@@ -114,14 +118,20 @@ private slots:
|
|||||||
void remoteProcessInput();
|
void remoteProcessInput();
|
||||||
void sftp();
|
void sftp();
|
||||||
|
|
||||||
|
void cleanupTestCase();
|
||||||
private:
|
private:
|
||||||
bool waitForConnection(SshConnection &connection);
|
bool waitForConnection(SshConnection &connection);
|
||||||
|
|
||||||
SshConnectionManager sshConnectionManager;
|
Utils::ProcessReaper *processReaper = nullptr;
|
||||||
|
SshConnectionManager *sshConnectionManager = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
void tst_Ssh::initTestCase()
|
void tst_Ssh::initTestCase()
|
||||||
{
|
{
|
||||||
|
processReaper = new Utils::ProcessReaper();
|
||||||
|
Utils::LauncherInterface::startLauncher(qApp->applicationDirPath() + '/'
|
||||||
|
+ QLatin1String(TEST_RELATIVE_LIBEXEC_PATH));
|
||||||
|
sshConnectionManager = new SshConnectionManager();
|
||||||
Utils::TemporaryDirectory::setMasterTemporaryDirectory(QDir::tempPath()
|
Utils::TemporaryDirectory::setMasterTemporaryDirectory(QDir::tempPath()
|
||||||
+ "/qtc-ssh-autotest-XXXXXX");
|
+ "/qtc-ssh-autotest-XXXXXX");
|
||||||
}
|
}
|
||||||
@@ -269,7 +279,7 @@ void tst_Ssh::remoteProcess()
|
|||||||
QVERIFY2(runner.lastConnectionErrorString().isEmpty(),
|
QVERIFY2(runner.lastConnectionErrorString().isEmpty(),
|
||||||
qPrintable(runner.lastConnectionErrorString()));
|
qPrintable(runner.lastConnectionErrorString()));
|
||||||
if (isBlocking) {
|
if (isBlocking) {
|
||||||
QVERIFY(runner.processExitStatus() == SshRemoteProcess::CrashExit
|
QVERIFY(runner.processExitStatus() == QProcess::CrashExit
|
||||||
|| runner.processExitCode() != 0);
|
|| runner.processExitCode() != 0);
|
||||||
} else {
|
} else {
|
||||||
QCOMPARE(successExpected, runner.processExitCode() == 0);
|
QCOMPARE(successExpected, runner.processExitCode() == 0);
|
||||||
@@ -291,11 +301,10 @@ void tst_Ssh::remoteProcessChannels()
|
|||||||
QByteArray remoteData;
|
QByteArray remoteData;
|
||||||
SshRemoteProcessPtr echoProcess
|
SshRemoteProcessPtr echoProcess
|
||||||
= connection.createRemoteProcess("printf " + QString::fromUtf8(testString) + " >&2");
|
= connection.createRemoteProcess("printf " + QString::fromUtf8(testString) + " >&2");
|
||||||
echoProcess->setReadChannel(QProcess::StandardError);
|
|
||||||
QEventLoop loop;
|
QEventLoop loop;
|
||||||
connect(echoProcess.get(), &SshRemoteProcess::done, &loop, &QEventLoop::quit);
|
connect(echoProcess.get(), &SshRemoteProcess::done, &loop, &QEventLoop::quit);
|
||||||
connect(echoProcess.get(), &QIODevice::readyRead,
|
connect(echoProcess.get(), &Utils::QtcProcess::readyReadStandardError,
|
||||||
[&remoteData, p = echoProcess.get()] { remoteData += p->readAll(); });
|
[&remoteData, p = echoProcess.get()] { remoteData += p->readAllStandardError(); });
|
||||||
connect(echoProcess.get(), &SshRemoteProcess::readyReadStandardOutput,
|
connect(echoProcess.get(), &SshRemoteProcess::readyReadStandardOutput,
|
||||||
[&remoteStdout, p = echoProcess.get()] { remoteStdout += p->readAllStandardOutput(); });
|
[&remoteStdout, p = echoProcess.get()] { remoteStdout += p->readAllStandardOutput(); });
|
||||||
connect(echoProcess.get(), &SshRemoteProcess::readyReadStandardError,
|
connect(echoProcess.get(), &SshRemoteProcess::readyReadStandardError,
|
||||||
@@ -324,7 +333,8 @@ void tst_Ssh::remoteProcessInput()
|
|||||||
SshConnection connection(params);
|
SshConnection connection(params);
|
||||||
QVERIFY(waitForConnection(connection));
|
QVERIFY(waitForConnection(connection));
|
||||||
|
|
||||||
SshRemoteProcessPtr catProcess = connection.createRemoteProcess("/bin/cat");
|
SshRemoteProcessPtr catProcess = connection.createRemoteProcess("/bin/cat",
|
||||||
|
Utils::ProcessMode::Writer);
|
||||||
QEventLoop loop;
|
QEventLoop loop;
|
||||||
connect(catProcess.get(), &SshRemoteProcess::started, &loop, &QEventLoop::quit);
|
connect(catProcess.get(), &SshRemoteProcess::started, &loop, &QEventLoop::quit);
|
||||||
connect(catProcess.get(), &SshRemoteProcess::done, &loop, &QEventLoop::quit);
|
connect(catProcess.get(), &SshRemoteProcess::done, &loop, &QEventLoop::quit);
|
||||||
@@ -340,17 +350,16 @@ void tst_Ssh::remoteProcessInput()
|
|||||||
QVERIFY(catProcess->isRunning());
|
QVERIFY(catProcess->isRunning());
|
||||||
|
|
||||||
static QString testString = "x\r\n";
|
static QString testString = "x\r\n";
|
||||||
connect(catProcess.get(), &QIODevice::readyRead, &loop, &QEventLoop::quit);
|
connect(catProcess.get(), &Utils::QtcProcess::readyReadStandardOutput, &loop, &QEventLoop::quit);
|
||||||
QTextStream stream(catProcess.get());
|
|
||||||
stream << testString;
|
catProcess->write(testString.toUtf8());
|
||||||
stream.flush();
|
|
||||||
timer.start();
|
timer.start();
|
||||||
loop.exec();
|
loop.exec();
|
||||||
QVERIFY(timer.isActive());
|
QVERIFY(timer.isActive());
|
||||||
timer.stop();
|
timer.stop();
|
||||||
QVERIFY(catProcess->isRunning());
|
QVERIFY(catProcess->isRunning());
|
||||||
|
|
||||||
const QString data = QString::fromUtf8(catProcess->readAll());
|
const QString data = QString::fromUtf8(catProcess->readAllStandardOutput());
|
||||||
QCOMPARE(data, testString);
|
QCOMPARE(data, testString);
|
||||||
SshRemoteProcessRunner * const killer = new SshRemoteProcessRunner(this);
|
SshRemoteProcessRunner * const killer = new SshRemoteProcessRunner(this);
|
||||||
killer->run("pkill -9 cat", params);
|
killer->run("pkill -9 cat", params);
|
||||||
@@ -623,6 +632,13 @@ void tst_Ssh::sftp()
|
|||||||
QVERIFY2(connection.errorString().isEmpty(), qPrintable(connection.errorString()));
|
QVERIFY2(connection.errorString().isEmpty(), qPrintable(connection.errorString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_Ssh::cleanupTestCase()
|
||||||
|
{
|
||||||
|
delete sshConnectionManager;
|
||||||
|
Utils::LauncherInterface::stopLauncher();
|
||||||
|
delete processReaper;
|
||||||
|
}
|
||||||
|
|
||||||
bool tst_Ssh::waitForConnection(SshConnection &connection)
|
bool tst_Ssh::waitForConnection(SshConnection &connection)
|
||||||
{
|
{
|
||||||
QEventLoop loop;
|
QEventLoop loop;
|
||||||
|
Reference in New Issue
Block a user