summaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/projectexplorer/devicesupport/devicemanager.cpp20
-rw-r--r--src/plugins/projectexplorer/devicesupport/devicemanager.h3
-rw-r--r--src/plugins/projectexplorer/devicesupport/idevice.cpp24
-rw-r--r--src/plugins/projectexplorer/devicesupport/sshdeviceprocess.cpp110
-rw-r--r--src/plugins/projectexplorer/devicesupport/sshdeviceprocess.h5
-rw-r--r--src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.cpp36
-rw-r--r--src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.h2
-rw-r--r--src/plugins/projectexplorer/devicesupport/sshsettingspage.cpp188
-rw-r--r--src/plugins/projectexplorer/devicesupport/sshsettingspage.h53
-rw-r--r--src/plugins/projectexplorer/projectexplorer.cpp25
-rw-r--r--src/plugins/projectexplorer/projectexplorer.pro2
-rw-r--r--src/plugins/projectexplorer/projectexplorer.qbs1
-rw-r--r--src/plugins/projectexplorer/projectexplorerconstants.h1
-rw-r--r--src/plugins/qnx/qnxdevicetester.cpp4
-rw-r--r--src/plugins/qnx/qnxdevicetester.h2
-rw-r--r--src/plugins/qnx/qnxdevicewizard.cpp4
-rw-r--r--src/plugins/remotelinux/abstractremotelinuxdeployservice.cpp2
-rw-r--r--src/plugins/remotelinux/genericdirectuploadservice.cpp498
-rw-r--r--src/plugins/remotelinux/genericdirectuploadservice.h24
-rw-r--r--src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp44
-rw-r--r--src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.h2
-rw-r--r--src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.ui45
-rw-r--r--src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp3
-rw-r--r--src/plugins/remotelinux/genericlinuxdeviceconfigurationwizardpages.cpp20
-rw-r--r--src/plugins/remotelinux/genericlinuxdeviceconfigurationwizardsetuppage.ui50
-rw-r--r--src/plugins/remotelinux/linuxdevicetester.cpp54
-rw-r--r--src/plugins/remotelinux/linuxdevicetester.h5
-rw-r--r--src/plugins/remotelinux/packageuploader.cpp72
-rw-r--r--src/plugins/remotelinux/packageuploader.h12
-rw-r--r--src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.cpp13
-rw-r--r--src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.cpp8
-rw-r--r--src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.h2
-rw-r--r--src/plugins/remotelinux/remotelinuxpackageinstaller.cpp4
-rw-r--r--src/plugins/remotelinux/remotelinuxpackageinstaller.h2
-rw-r--r--src/plugins/remotelinux/sshkeydeployer.cpp15
-rw-r--r--src/plugins/remotelinux/sshkeydeployer.h2
-rw-r--r--src/plugins/valgrind/callgrind/callgrindcontroller.cpp14
-rw-r--r--src/plugins/valgrind/callgrind/callgrindcontroller.h5
-rw-r--r--src/plugins/valgrind/memchecktool.cpp2
39 files changed, 623 insertions, 755 deletions
diff --git a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp
index 939d4d3884..e5bcc779a9 100644
--- a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp
+++ b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp
@@ -31,7 +31,6 @@
#include <coreplugin/messagemanager.h>
#include <projectexplorer/projectexplorerconstants.h>
-#include <ssh/sshhostkeydatabase.h>
#include <utils/algorithm.h>
#include <utils/fileutils.h>
#include <utils/persistentsettings.h>
@@ -72,7 +71,6 @@ public:
static DeviceManager *clonedInstance;
QList<IDevice::Ptr> devices;
QHash<Core::Id, Core::Id> defaultDevices;
- QSsh::SshHostKeyDatabasePtr hostKeyDatabase;
Utils::PersistentSettingsWriter *writer = nullptr;
};
@@ -134,7 +132,6 @@ void DeviceManager::save()
QVariantMap data;
data.insert(QLatin1String(DeviceManagerKey), toMap());
d->writer->save(data, Core::ICore::mainWindow());
- d->hostKeyDatabase->store(hostKeysFilePath());
}
void DeviceManager::load()
@@ -315,11 +312,6 @@ bool DeviceManager::isLoaded() const
return d->writer;
}
-QSsh::SshHostKeyDatabasePtr DeviceManager::hostKeyDatabase() const
-{
- return d->hostKeyDatabase;
-}
-
void DeviceManager::setDefaultDevice(Core::Id id)
{
QTC_ASSERT(this != instance(), return);
@@ -356,13 +348,6 @@ DeviceManager::DeviceManager(bool isInstance) : d(std::make_unique<DeviceManager
if (isInstance) {
QTC_ASSERT(!m_instance, return);
m_instance = this;
- d->hostKeyDatabase = QSsh::SshHostKeyDatabasePtr::create();
- const QString keyFilePath = hostKeysFilePath();
- if (QFileInfo::exists(keyFilePath)) {
- QString error;
- if (!d->hostKeyDatabase->load(keyFilePath, &error))
- Core::MessageManager::write(error);
- }
connect(Core::ICore::instance(), &Core::ICore::saveSettingsRequested, this, &DeviceManager::save);
}
}
@@ -406,11 +391,6 @@ IDevice::ConstPtr DeviceManager::defaultDevice(Core::Id deviceType) const
return id.isValid() ? find(id) : IDevice::ConstPtr();
}
-QString DeviceManager::hostKeysFilePath()
-{
- return settingsFilePath(QLatin1String("/ssh-hostkeys")).toString();
-}
-
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/devicemanager.h b/src/plugins/projectexplorer/devicesupport/devicemanager.h
index 2b086f0683..bd9c2b606e 100644
--- a/src/plugins/projectexplorer/devicesupport/devicemanager.h
+++ b/src/plugins/projectexplorer/devicesupport/devicemanager.h
@@ -33,7 +33,6 @@
#include <memory>
-namespace QSsh { class SshHostKeyDatabase; }
namespace Utils { class FileName; }
namespace ProjectExplorer {
@@ -97,8 +96,6 @@ private:
static void replaceInstance();
static void removeClonedInstance();
- static QString hostKeysFilePath();
- QSharedPointer<QSsh::SshHostKeyDatabase> hostKeyDatabase() const;
static Utils::FileName settingsFilePath(const QString &extension);
static Utils::FileName systemSettingsFilePath(const QString &deviceFileRelativePath);
static void copy(const DeviceManager *source, DeviceManager *target, bool deep);
diff --git a/src/plugins/projectexplorer/devicesupport/idevice.cpp b/src/plugins/projectexplorer/devicesupport/idevice.cpp
index 2ff4090ffd..0487954312 100644
--- a/src/plugins/projectexplorer/devicesupport/idevice.cpp
+++ b/src/plugins/projectexplorer/devicesupport/idevice.cpp
@@ -120,16 +120,14 @@ const char PortsSpecKey[] = "FreePortsSpec";
const char UserNameKey[] = "Uname";
const char AuthKey[] = "Authentication";
const char KeyFileKey[] = "KeyFile";
-const char PasswordKey[] = "Password";
const char TimeoutKey[] = "Timeout";
const char HostKeyCheckingKey[] = "HostKeyChecking";
-const char SshOptionsKey[] = "SshOptions";
const char DebugServerKey[] = "DebugServerKey";
const char QmlsceneKey[] = "QmlsceneKey";
using AuthType = QSsh::SshConnectionParameters::AuthenticationType;
-const AuthType DefaultAuthType = QSsh::SshConnectionParameters::AuthenticationTypePublicKey;
+const AuthType DefaultAuthType = QSsh::SshConnectionParameters::AuthenticationTypeAll;
const IDevice::MachineType DefaultMachineType = IDevice::Hardware;
const int DefaultTimeout = 10;
@@ -161,7 +159,6 @@ DeviceTester::DeviceTester(QObject *parent) : QObject(parent) { }
IDevice::IDevice() : d(new Internal::IDevicePrivate)
{
- d->sshParameters.hostKeyDatabase = DeviceManager::instance()->hostKeyDatabase();
}
IDevice::IDevice(Core::Id type, Origin origin, MachineType machineType, Core::Id id)
@@ -172,7 +169,6 @@ IDevice::IDevice(Core::Id type, Origin origin, MachineType machineType, Core::Id
d->machineType = machineType;
QTC_CHECK(origin == ManuallyAdded || id.isValid());
d->id = id.isValid() ? id : newId();
- d->sshParameters.hostKeyDatabase = DeviceManager::instance()->hostKeyDatabase();
}
IDevice::IDevice(const IDevice &other)
@@ -328,16 +324,19 @@ void IDevice::fromMap(const QVariantMap &map)
d->sshParameters.setHost(map.value(QLatin1String(HostKey)).toString());
d->sshParameters.setPort(map.value(QLatin1String(SshPortKey), 22).toInt());
d->sshParameters.setUserName(map.value(QLatin1String(UserNameKey)).toString());
- d->sshParameters.authenticationType
- = static_cast<AuthType>(map.value(QLatin1String(AuthKey), DefaultAuthType).toInt());
- d->sshParameters.setPassword(map.value(QLatin1String(PasswordKey)).toString());
+
+ // Pre-4.9, the authentication enum used to have more values
+ const int storedAuthType = map.value(QLatin1String(AuthKey), DefaultAuthType).toInt();
+ const bool outdatedAuthType = storedAuthType
+ > QSsh::SshConnectionParameters::AuthenticationTypeSpecificKey;
+ d->sshParameters.authenticationType = outdatedAuthType
+ ? QSsh::SshConnectionParameters::AuthenticationTypeAll
+ : static_cast<AuthType>(storedAuthType);
+
d->sshParameters.privateKeyFile = map.value(QLatin1String(KeyFileKey), defaultPrivateKeyFilePath()).toString();
d->sshParameters.timeout = map.value(QLatin1String(TimeoutKey), DefaultTimeout).toInt();
d->sshParameters.hostKeyCheckingMode = static_cast<QSsh::SshHostKeyCheckingMode>
(map.value(QLatin1String(HostKeyCheckingKey), QSsh::SshHostKeyCheckingNone).toInt());
- const QVariant optionsVariant = map.value(QLatin1String(SshOptionsKey));
- if (optionsVariant.isValid()) // false for QtC < 3.4
- d->sshParameters.options = QSsh::SshConnectionOptions(optionsVariant.toInt());
QString portsSpec = map.value(PortsSpecKey).toString();
if (portsSpec.isEmpty())
@@ -369,11 +368,9 @@ QVariantMap IDevice::toMap() const
map.insert(QLatin1String(SshPortKey), d->sshParameters.port());
map.insert(QLatin1String(UserNameKey), d->sshParameters.userName());
map.insert(QLatin1String(AuthKey), d->sshParameters.authenticationType);
- map.insert(QLatin1String(PasswordKey), d->sshParameters.password());
map.insert(QLatin1String(KeyFileKey), d->sshParameters.privateKeyFile);
map.insert(QLatin1String(TimeoutKey), d->sshParameters.timeout);
map.insert(QLatin1String(HostKeyCheckingKey), d->sshParameters.hostKeyCheckingMode);
- map.insert(QLatin1String(SshOptionsKey), static_cast<int>(d->sshParameters.options));
map.insert(QLatin1String(PortsSpecKey), d->freePorts.toString());
map.insert(QLatin1String(VersionKey), d->version);
@@ -404,7 +401,6 @@ QSsh::SshConnectionParameters IDevice::sshParameters() const
void IDevice::setSshParameters(const QSsh::SshConnectionParameters &sshParameters)
{
d->sshParameters = sshParameters;
- d->sshParameters.hostKeyDatabase = DeviceManager::instance()->hostKeyDatabase();
}
QUrl IDevice::toolControlChannel(const ControlChannelHint &) const
diff --git a/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.cpp b/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.cpp
index 9feb7e7166..e3cc959a5d 100644
--- a/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.cpp
+++ b/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.cpp
@@ -39,18 +39,19 @@
namespace ProjectExplorer {
+enum class Signal { Interrupt, Terminate, Kill };
+
class SshDeviceProcess::SshDeviceProcessPrivate
{
public:
SshDeviceProcessPrivate(SshDeviceProcess *q) : q(q) {}
SshDeviceProcess * const q;
- bool serverSupportsSignals = false;
QSsh::SshConnection *connection = nullptr;
- QSsh::SshRemoteProcess::Ptr process;
+ QSsh::SshRemoteProcessPtr process;
Runnable runnable;
QString errorMessage;
- QSsh::SshRemoteProcess::ExitStatus exitStatus;
+ QProcess::ExitStatus exitStatus = QProcess::NormalExit;
DeviceProcessSignalOperation::Ptr killOperation;
QTimer killTimer;
QByteArray stdOut;
@@ -59,7 +60,7 @@ public:
enum State { Inactive, Connecting, Connected, ProcessRunning } state = Inactive;
void setState(State newState);
- void doSignal(QSsh::SshRemoteProcess::Signal signal);
+ void doSignal(Signal signal);
QString displayName() const
{
@@ -85,15 +86,12 @@ void SshDeviceProcess::start(const Runnable &runnable)
d->errorMessage.clear();
d->exitCode = -1;
+ d->exitStatus = QProcess::NormalExit;
d->runnable = runnable;
- d->connection = QSsh::acquireConnection(device()->sshParameters());
- const QString displayName = d->displayName();
- const QString connDisplayName = d->connection->x11DisplayName();
- if (!displayName.isEmpty() && !connDisplayName.isEmpty() && connDisplayName != displayName) {
- QSsh::releaseConnection(d->connection);
- d->connection = new QSsh::SshConnection(device()->sshParameters(), this);
- }
- connect(d->connection, &QSsh::SshConnection::error,
+ QSsh::SshConnectionParameters params = device()->sshParameters();
+ params.x11DisplayName = d->displayName();
+ d->connection = QSsh::acquireConnection(params);
+ connect(d->connection, &QSsh::SshConnection::errorOccurred,
this, &SshDeviceProcess::handleConnectionError);
connect(d->connection, &QSsh::SshConnection::disconnected,
this, &SshDeviceProcess::handleDisconnected);
@@ -110,17 +108,17 @@ void SshDeviceProcess::start(const Runnable &runnable)
void SshDeviceProcess::interrupt()
{
QTC_ASSERT(d->state == SshDeviceProcessPrivate::ProcessRunning, return);
- d->doSignal(QSsh::SshRemoteProcess::IntSignal);
+ d->doSignal(Signal::Interrupt);
}
void SshDeviceProcess::terminate()
{
- d->doSignal(QSsh::SshRemoteProcess::TermSignal);
+ d->doSignal(Signal::Terminate);
}
void SshDeviceProcess::kill()
{
- d->doSignal(QSsh::SshRemoteProcess::KillSignal);
+ d->doSignal(Signal::Kill);
}
QProcess::ProcessState SshDeviceProcess::state() const
@@ -169,11 +167,6 @@ QByteArray SshDeviceProcess::readAllStandardError()
return data;
}
-void SshDeviceProcess::setSshServerSupportsSignals(bool signalsSupported)
-{
- d->serverSupportsSignals = signalsSupported;
-}
-
qint64 SshDeviceProcess::processId() const
{
return 0;
@@ -185,15 +178,11 @@ void SshDeviceProcess::handleConnected()
d->setState(SshDeviceProcessPrivate::Connected);
d->process = d->connection->createRemoteProcess(fullCommandLine(d->runnable).toUtf8());
- connect(d->process.data(), &QSsh::SshRemoteProcess::started, this, &SshDeviceProcess::handleProcessStarted);
- connect(d->process.data(), &QSsh::SshRemoteProcess::closed, this, &SshDeviceProcess::handleProcessFinished);
- connect(d->process.data(), &QSsh::SshRemoteProcess::readyReadStandardOutput, this, &SshDeviceProcess::handleStdout);
- connect(d->process.data(), &QSsh::SshRemoteProcess::readyReadStandardError, this, &SshDeviceProcess::handleStderr);
-
- d->process->clearEnvironment();
- const Utils::Environment env = d->runnable.environment;
- for (Utils::Environment::const_iterator it = env.constBegin(); it != env.constEnd(); ++it)
- d->process->addToEnvironment(env.key(it).toUtf8(), env.value(it).toUtf8());
+ connect(d->process.get(), &QSsh::SshRemoteProcess::started, this, &SshDeviceProcess::handleProcessStarted);
+ connect(d->process.get(), &QSsh::SshRemoteProcess::done, this, &SshDeviceProcess::handleProcessFinished);
+ connect(d->process.get(), &QSsh::SshRemoteProcess::readyReadStandardOutput, this, &SshDeviceProcess::handleStdout);
+ connect(d->process.get(), &QSsh::SshRemoteProcess::readyReadStandardError, this, &SshDeviceProcess::handleStderr);
+
const QString display = d->displayName();
if (!display.isEmpty())
d->process->requestX11Forwarding(display);
@@ -234,24 +223,10 @@ void SshDeviceProcess::handleProcessStarted()
emit started();
}
-void SshDeviceProcess::handleProcessFinished(int exitStatus)
+void SshDeviceProcess::handleProcessFinished()
{
- d->exitStatus = static_cast<QSsh::SshRemoteProcess::ExitStatus>(exitStatus);
- switch (d->exitStatus) {
- case QSsh::SshRemoteProcess::FailedToStart:
- QTC_ASSERT(d->state == SshDeviceProcessPrivate::Connected, return);
- break;
- case QSsh::SshRemoteProcess::CrashExit:
- QTC_ASSERT(d->state == SshDeviceProcessPrivate::ProcessRunning, return);
- break;
- case QSsh::SshRemoteProcess::NormalExit:
- QTC_ASSERT(d->state == SshDeviceProcessPrivate::ProcessRunning, return);
- d->exitCode = d->process->exitCode();
- break;
- default:
- QTC_ASSERT(false, return);
- }
d->errorMessage = d->process->errorString();
+ d->exitCode = d->process->exitCode();
d->setState(SshDeviceProcessPrivate::Inactive);
emit finished();
}
@@ -302,7 +277,7 @@ QString SshDeviceProcess::fullCommandLine(const Runnable &runnable) const
return cmdLine;
}
-void SshDeviceProcess::SshDeviceProcessPrivate::doSignal(QSsh::SshRemoteProcess::Signal signal)
+void SshDeviceProcess::SshDeviceProcessPrivate::doSignal(Signal signal)
{
switch (state) {
case SshDeviceProcessPrivate::Inactive:
@@ -315,28 +290,24 @@ void SshDeviceProcess::SshDeviceProcessPrivate::doSignal(QSsh::SshRemoteProcess:
break;
case SshDeviceProcessPrivate::Connected:
case SshDeviceProcessPrivate::ProcessRunning:
- if (serverSupportsSignals) {
- process->sendSignal(signal);
+ DeviceProcessSignalOperation::Ptr signalOperation = q->device()->signalOperation();
+ quint64 processId = q->processId();
+ if (signal == Signal::Interrupt) {
+ if (processId != 0)
+ signalOperation->interruptProcess(processId);
+ else
+ signalOperation->interruptProcess(runnable.executable);
} else {
- DeviceProcessSignalOperation::Ptr signalOperation = q->device()->signalOperation();
- quint64 processId = q->processId();
- if (signal == QSsh::SshRemoteProcess::IntSignal) {
- if (processId != 0)
- signalOperation->interruptProcess(processId);
- else
- signalOperation->interruptProcess(runnable.executable);
- } else {
- if (killOperation) // We are already in the process of killing the app.
- return;
- killOperation = signalOperation;
- connect(signalOperation.data(), &DeviceProcessSignalOperation::finished, q,
- &SshDeviceProcess::handleKillOperationFinished);
- killTimer.start(5000);
- if (processId != 0)
- signalOperation->killProcess(processId);
- else
- signalOperation->killProcess(runnable.executable);
- }
+ if (killOperation) // We are already in the process of killing the app.
+ return;
+ killOperation = signalOperation;
+ connect(signalOperation.data(), &DeviceProcessSignalOperation::finished, q,
+ &SshDeviceProcess::handleKillOperationFinished);
+ killTimer.start(5000);
+ if (processId != 0)
+ signalOperation->killProcess(processId);
+ else
+ signalOperation->killProcess(runnable.executable);
}
break;
}
@@ -360,10 +331,7 @@ void SshDeviceProcess::SshDeviceProcessPrivate::setState(SshDeviceProcess::SshDe
process->disconnect(q);
if (connection) {
connection->disconnect(q);
- if (connection->parent() == q)
- connection->deleteLater();
- else
- QSsh::releaseConnection(connection);
+ QSsh::releaseConnection(connection);
connection = nullptr;
}
}
diff --git a/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.h b/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.h
index 19acc31769..7bbe942354 100644
--- a/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.h
+++ b/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.h
@@ -55,15 +55,12 @@ public:
qint64 write(const QByteArray &data) override;
- // Default is "false" due to OpenSSH not implementing this feature for some reason.
- void setSshServerSupportsSignals(bool signalsSupported);
-
private:
void handleConnected();
void handleConnectionError();
void handleDisconnected();
void handleProcessStarted();
- void handleProcessFinished(int exitStatus);
+ void handleProcessFinished();
void handleStdout();
void handleStderr();
void handleKillOperationFinished(const QString &errorMessage);
diff --git a/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.cpp b/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.cpp
index 589b3d1721..c1c7b0a45f 100644
--- a/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.cpp
+++ b/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.cpp
@@ -72,31 +72,21 @@ void SshDeviceProcessList::handleConnectionError()
reportError(tr("Connection failure: %1").arg(d->process.lastConnectionErrorString()));
}
-void SshDeviceProcessList::handleListProcessFinished(int exitStatus)
+void SshDeviceProcessList::handleListProcessFinished(const QString &error)
{
setFinished();
- switch (exitStatus) {
- case SshRemoteProcess::FailedToStart:
- handleProcessError(tr("Error: Process listing command failed to start: %1")
- .arg(d->process.processErrorString()));
- break;
- case SshRemoteProcess::CrashExit:
- handleProcessError(tr("Error: Process listing command crashed: %1")
- .arg(d->process.processErrorString()));
- break;
- case SshRemoteProcess::NormalExit:
- if (d->process.processExitCode() == 0) {
- const QByteArray remoteStdout = d->process.readAllStandardOutput();
- const QString stdoutString
- = QString::fromUtf8(remoteStdout.data(), remoteStdout.count());
- reportProcessListUpdated(buildProcessList(stdoutString));
- } else {
- handleProcessError(tr("Process listing command failed with exit code %1.")
- .arg(d->process.processExitCode()));
- }
- break;
- default:
- Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid exit status");
+ if (!error.isEmpty()) {
+ handleProcessError(error);
+ return;
+ }
+ if (d->process.processExitCode() == 0) {
+ const QByteArray remoteStdout = d->process.readAllStandardOutput();
+ const QString stdoutString
+ = QString::fromUtf8(remoteStdout.data(), remoteStdout.count());
+ reportProcessListUpdated(buildProcessList(stdoutString));
+ } else {
+ handleProcessError(tr("Process listing command failed with exit code %1.")
+ .arg(d->process.processExitCode()));
}
}
diff --git a/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.h b/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.h
index 8ecefce9b9..60937e65cc 100644
--- a/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.h
+++ b/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.h
@@ -40,7 +40,7 @@ public:
private:
void handleConnectionError();
- void handleListProcessFinished(int exitStatus);
+ void handleListProcessFinished(const QString &error);
void handleKillProcessFinished(const QString &errorString);
virtual QString listProcessesCommandLine() const = 0;
diff --git a/src/plugins/projectexplorer/devicesupport/sshsettingspage.cpp b/src/plugins/projectexplorer/devicesupport/sshsettingspage.cpp
new file mode 100644
index 0000000000..c87d27d978
--- /dev/null
+++ b/src/plugins/projectexplorer/devicesupport/sshsettingspage.cpp
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "sshsettingspage.h"
+
+#include <coreplugin/icore.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <ssh/sshsettings.h>
+#include <utils/pathchooser.h>
+
+#include <QCheckBox>
+#include <QCoreApplication>
+#include <QFormLayout>
+#include <QLabel>
+#include <QSpinBox>
+#include <QString>
+
+using namespace QSsh;
+using namespace Utils;
+
+namespace ProjectExplorer {
+namespace Internal {
+
+class SshSettingsWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ SshSettingsWidget();
+ void saveSettings();
+
+private:
+ void setupConnectionSharingCheckBox();
+ void setupConnectionSharingSpinBox();
+ void setupSshPathChooser();
+ void setupSftpPathChooser();
+ void setupAskpassPathChooser();
+ void setupKeygenPathChooser();
+ void setupPathChooser(PathChooser &chooser, const FileName &initialPath, bool &changedFlag);
+ void updateSpinboxEnabled();
+
+ QCheckBox m_connectionSharingCheckBox;
+ QSpinBox m_connectionSharingSpinBox;
+ PathChooser m_sshChooser;
+ PathChooser m_sftpChooser;
+ PathChooser m_askpassChooser;
+ PathChooser m_keygenChooser;
+ bool m_sshPathChanged = false;
+ bool m_sftpPathChanged = false;
+ bool m_askpassPathChanged = false;
+ bool m_keygenPathChanged = false;
+};
+
+SshSettingsPage::SshSettingsPage(QObject *parent) : Core::IOptionsPage(parent)
+{
+ setId(Constants::SSH_SETTINGS_PAGE_ID);
+ setDisplayName(tr("SSH"));
+ setCategory(Constants::DEVICE_SETTINGS_CATEGORY);
+ setDisplayCategory(QCoreApplication::translate("ProjectExplorer", "SSH"));
+ setCategoryIcon(Utils::Icon({{":/projectexplorer/images/settingscategory_devices.png",
+ Utils::Theme::PanelTextColorDark}}, Utils::Icon::Tint));
+}
+
+QWidget *SshSettingsPage::widget()
+{
+ if (!m_widget)
+ m_widget = new SshSettingsWidget;
+ return m_widget;
+}
+
+void SshSettingsPage::apply()
+{
+ m_widget->saveSettings();
+}
+
+void SshSettingsPage::finish()
+{
+ delete m_widget;
+}
+
+
+SshSettingsWidget::SshSettingsWidget()
+{
+ setupConnectionSharingCheckBox();
+ setupConnectionSharingSpinBox();
+ setupSshPathChooser();
+ setupSftpPathChooser();
+ setupAskpassPathChooser();
+ setupKeygenPathChooser();
+ auto * const layout = new QFormLayout(this);
+ layout->addRow(tr("Enable connection sharing:"), &m_connectionSharingCheckBox);
+ layout->addRow(tr("Connection sharing timeout:"), &m_connectionSharingSpinBox);
+ layout->addRow(tr("Path to ssh executable:"), &m_sshChooser);
+ layout->addRow(tr("Path to sftp executable:"), &m_sftpChooser);
+ layout->addRow(tr("Path to ssh-askpass executable:"), &m_askpassChooser);
+ layout->addRow(tr("Path to ssh-keygen executable:"), &m_keygenChooser);
+ updateSpinboxEnabled();
+}
+
+void SshSettingsWidget::saveSettings()
+{
+ SshSettings::setConnectionSharingEnabled(m_connectionSharingCheckBox.isChecked());
+ SshSettings::setConnectionSharingTimeout(m_connectionSharingSpinBox.value());
+ if (m_sshPathChanged)
+ SshSettings::setSshFilePath(m_sshChooser.fileName());
+ if (m_sftpPathChanged)
+ SshSettings::setSftpFilePath(m_sftpChooser.fileName());
+ if (m_askpassPathChanged)
+ SshSettings::setAskpassFilePath(m_askpassChooser.fileName());
+ if (m_keygenPathChanged)
+ SshSettings::setKeygenFilePath(m_keygenChooser.fileName());
+ SshSettings::storeSettings(Core::ICore::settings());
+}
+
+void SshSettingsWidget::setupConnectionSharingCheckBox()
+{
+ m_connectionSharingCheckBox.setChecked(SshSettings::connectionSharingEnabled());
+ connect(&m_connectionSharingCheckBox, &QCheckBox::toggled,
+ this, &SshSettingsWidget::updateSpinboxEnabled);
+}
+
+void SshSettingsWidget::setupConnectionSharingSpinBox()
+{
+ m_connectionSharingSpinBox.setMinimum(1);
+ m_connectionSharingSpinBox.setValue(SshSettings::connectionSharingTimeout());
+ m_connectionSharingSpinBox.setSuffix(tr(" minutes"));
+}
+
+void SshSettingsWidget::setupSshPathChooser()
+{
+ setupPathChooser(m_sshChooser, SshSettings::sshFilePath(), m_sshPathChanged);
+}
+
+void SshSettingsWidget::setupSftpPathChooser()
+{
+ setupPathChooser(m_sftpChooser, SshSettings::sftpFilePath(), m_sftpPathChanged);
+}
+
+void SshSettingsWidget::setupAskpassPathChooser()
+{
+ setupPathChooser(m_askpassChooser, SshSettings::askpassFilePath(), m_askpassPathChanged);
+}
+
+void SshSettingsWidget::setupKeygenPathChooser()
+{
+ setupPathChooser(m_keygenChooser, SshSettings::keygenFilePath(), m_keygenPathChanged);
+}
+
+void SshSettingsWidget::setupPathChooser(PathChooser &chooser, const FileName &initialPath,
+ bool &changedFlag)
+{
+ chooser.setExpectedKind(PathChooser::ExistingCommand);
+ chooser.setFileName(initialPath);
+ connect(&chooser, &PathChooser::pathChanged, [&changedFlag] { changedFlag = true; });
+}
+
+void SshSettingsWidget::updateSpinboxEnabled()
+{
+ m_connectionSharingSpinBox.setEnabled(m_connectionSharingCheckBox.isChecked());
+ static_cast<QFormLayout *>(layout())->labelForField(&m_connectionSharingSpinBox)
+ ->setEnabled(m_connectionSharingCheckBox.isChecked());
+}
+
+} // namespace Internal
+} // namespace ProjectExplorer
+
+#include <sshsettingspage.moc>
diff --git a/src/plugins/projectexplorer/devicesupport/sshsettingspage.h b/src/plugins/projectexplorer/devicesupport/sshsettingspage.h
new file mode 100644
index 0000000000..e43ef93826
--- /dev/null
+++ b/src/plugins/projectexplorer/devicesupport/sshsettingspage.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <coreplugin/dialogs/ioptionspage.h>
+
+#include <QPointer>
+
+namespace ProjectExplorer {
+namespace Internal {
+
+class SshSettingsWidget;
+
+class SshSettingsPage : public Core::IOptionsPage
+{
+ Q_OBJECT
+
+public:
+ SshSettingsPage(QObject *parent = 0);
+
+private:
+ QWidget *widget() override;
+ void apply() override;
+ void finish() override;
+
+ QPointer<SshSettingsWidget> m_widget;
+};
+
+} // namespace Internal
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp
index 5048c2d0ca..068b4f720b 100644
--- a/src/plugins/projectexplorer/projectexplorer.cpp
+++ b/src/plugins/projectexplorer/projectexplorer.cpp
@@ -84,6 +84,7 @@
#include "devicesupport/desktopdevicefactory.h"
#include "devicesupport/devicemanager.h"
#include "devicesupport/devicesettingspage.h"
+#include "devicesupport/sshsettingspage.h"
#include "targetsettingspanel.h"
#include "projectpanelfactory.h"
#include "waitforstopdialog.h"
@@ -119,6 +120,7 @@
#include <texteditor/textdocument.h>
#include <texteditor/texteditorconstants.h>
#include <ssh/sshconnection.h>
+#include <ssh/sshsettings.h>
#include <utils/algorithm.h>
#include <utils/fileutils.h>
@@ -536,6 +538,7 @@ public:
// Settings pages
ProjectExplorerSettingsPage m_projectExplorerSettingsPage;
DeviceSettingsPage m_deviceSettingsPage;
+ SshSettingsPage m_sshSettingsPage;
ProjectTreeWidgetFactory m_projectTreeFactory;
FolderNavigationWidgetFactory m_folderNavigationWidgetFactory;
@@ -1715,6 +1718,28 @@ void ProjectExplorerPlugin::extensionsInitialized()
BuildManager::extensionsInitialized();
DeviceManager::instance()->addDevice(IDevice::Ptr(new DesktopDevice));
+
+ QSsh::SshSettings::loadSettings(Core::ICore::settings());
+ if (Utils::HostOsInfo::isWindowsHost()) {
+ const auto searchPathRetriever = [] {
+ const QString gitBinary = Core::ICore::settings()->value("Git/BinaryPath", "git")
+ .toString();
+ const QStringList rawGitSearchPaths = Core::ICore::settings()->value("Git/Path")
+ .toString().split(':', QString::SkipEmptyParts);
+ const Utils::FileNameList gitSearchPaths = Utils::transform(rawGitSearchPaths,
+ [](const QString &rawPath) { return Utils::FileName::fromString(rawPath); });
+ const Utils::FileName fullGitPath = Utils::Environment::systemEnvironment()
+ .searchInPath(gitBinary, gitSearchPaths);
+ if (fullGitPath.isEmpty())
+ return Utils::FileNameList();
+ return Utils::FileNameList{
+ fullGitPath.parentDir(),
+ fullGitPath.parentDir().parentDir() + "/usr/bin"
+ };
+ };
+ QSsh::SshSettings::setExtraSearchPathRetriever(searchPathRetriever);
+ }
+
// delay restoring kits until UI is shown for improved perceived startup performance
QTimer::singleShot(0, this, &ProjectExplorerPlugin::restoreKits);
}
diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro
index 21f70f48e2..8ef32ae9ba 100644
--- a/src/plugins/projectexplorer/projectexplorer.pro
+++ b/src/plugins/projectexplorer/projectexplorer.pro
@@ -130,6 +130,7 @@ HEADERS += projectexplorer.h \
devicesupport/localprocesslist.h \
devicesupport/sshdeviceprocess.h \
devicesupport/sshdeviceprocesslist.h \
+ devicesupport/sshsettingspage.h \
devicesupport/desktopdeviceconfigurationwidget.h \
devicesupport/desktopprocesssignaloperation.h \
deploymentdata.h \
@@ -271,6 +272,7 @@ SOURCES += projectexplorer.cpp \
devicesupport/localprocesslist.cpp \
devicesupport/sshdeviceprocess.cpp \
devicesupport/sshdeviceprocesslist.cpp \
+ devicesupport/sshsettingspage.cpp \
devicesupport/desktopdeviceconfigurationwidget.cpp \
devicesupport/desktopprocesssignaloperation.cpp \
deployablefile.cpp \
diff --git a/src/plugins/projectexplorer/projectexplorer.qbs b/src/plugins/projectexplorer/projectexplorer.qbs
index d25b52c7d4..5836c06c45 100644
--- a/src/plugins/projectexplorer/projectexplorer.qbs
+++ b/src/plugins/projectexplorer/projectexplorer.qbs
@@ -220,6 +220,7 @@ Project {
"localprocesslist.cpp", "localprocesslist.h",
"sshdeviceprocess.cpp", "sshdeviceprocess.h",
"sshdeviceprocesslist.cpp", "sshdeviceprocesslist.h",
+ "sshsettingspage.cpp", "sshsettingspage.h",
"desktopprocesssignaloperation.cpp", "desktopprocesssignaloperation.h",
"desktopdeviceconfigurationwidget.cpp", "desktopdeviceconfigurationwidget.h", "desktopdeviceconfigurationwidget.ui"
]
diff --git a/src/plugins/projectexplorer/projectexplorerconstants.h b/src/plugins/projectexplorer/projectexplorerconstants.h
index 61f1429fbe..de81a42833 100644
--- a/src/plugins/projectexplorer/projectexplorerconstants.h
+++ b/src/plugins/projectexplorer/projectexplorerconstants.h
@@ -107,6 +107,7 @@ const char KITS_SETTINGS_CATEGORY[] = "A.Kits";
// Kits pages
const char KITS_SETTINGS_PAGE_ID[] = "D.ProjectExplorer.KitsOptions";
const char DEVICE_SETTINGS_PAGE_ID[] = "E.ProjectExplorer.DeviceOptions";
+const char SSH_SETTINGS_PAGE_ID[] = "F.ProjectExplorer.SshOptions";
const char TOOLCHAIN_SETTINGS_PAGE_ID[] = "M.ProjectExplorer.ToolChainOptions";
const char DEBUGGER_SETTINGS_PAGE_ID[] = "N.ProjectExplorer.DebuggerOptions";
diff --git a/src/plugins/qnx/qnxdevicetester.cpp b/src/plugins/qnx/qnxdevicetester.cpp
index 3c8c37e98a..004de59acb 100644
--- a/src/plugins/qnx/qnxdevicetester.cpp
+++ b/src/plugins/qnx/qnxdevicetester.cpp
@@ -113,12 +113,12 @@ void QnxDeviceTester::handleGenericTestFinished(TestResult result)
testNextCommand();
}
-void QnxDeviceTester::handleProcessFinished(int exitStatus)
+void QnxDeviceTester::handleProcessFinished(const QString &error)
{
QTC_ASSERT(m_state == CommandsTest, return);
const QString command = m_commandsToTest[m_currentCommandIndex];
- if (exitStatus == QSsh::SshRemoteProcess::NormalExit) {
+ if (error.isEmpty()) {
if (m_processRunner->processExitCode() == 0) {
emit progressMessage(tr("%1 found.").arg(command) + QLatin1Char('\n'));
} else {
diff --git a/src/plugins/qnx/qnxdevicetester.h b/src/plugins/qnx/qnxdevicetester.h
index 67acf1c776..91d5548bda 100644
--- a/src/plugins/qnx/qnxdevicetester.h
+++ b/src/plugins/qnx/qnxdevicetester.h
@@ -46,7 +46,7 @@ public:
private slots:
void handleGenericTestFinished(ProjectExplorer::DeviceTester::TestResult result);
- void handleProcessFinished(int exitStatus);
+ void handleProcessFinished(const QString &error);
void handleConnectionError();
private:
diff --git a/src/plugins/qnx/qnxdevicewizard.cpp b/src/plugins/qnx/qnxdevicewizard.cpp
index 58b71f9586..2ca8968388 100644
--- a/src/plugins/qnx/qnxdevicewizard.cpp
+++ b/src/plugins/qnx/qnxdevicewizard.cpp
@@ -63,12 +63,10 @@ QnxDeviceWizard::QnxDeviceWizard(QWidget *parent) :
IDevice::Ptr QnxDeviceWizard::device()
{
QSsh::SshConnectionParameters sshParams;
- sshParams.options = QSsh::SshIgnoreDefaultProxy;
sshParams.url = m_setupPage->url();
sshParams.timeout = 10;
sshParams.authenticationType = m_setupPage->authenticationType();
- if (sshParams.authenticationType != QSsh::SshConnectionParameters::AuthenticationTypeTryAllPasswordBasedMethods
- && sshParams.authenticationType != QSsh::SshConnectionParameters::AuthenticationTypePassword)
+ if (sshParams.authenticationType == QSsh::SshConnectionParameters::AuthenticationTypeSpecificKey)
sshParams.privateKeyFile = m_setupPage->privateKeyFilePath();
QnxDevice::Ptr device = QnxDevice::create(m_setupPage->configurationName(),
diff --git a/src/plugins/remotelinux/abstractremotelinuxdeployservice.cpp b/src/plugins/remotelinux/abstractremotelinuxdeployservice.cpp
index c63e16ce5a..12e47ca0d2 100644
--- a/src/plugins/remotelinux/abstractremotelinuxdeployservice.cpp
+++ b/src/plugins/remotelinux/abstractremotelinuxdeployservice.cpp
@@ -196,7 +196,7 @@ void AbstractRemoteLinuxDeployService::handleDeviceSetupDone(bool success)
d->state = Connecting;
d->connection = QSsh::acquireConnection(deviceConfiguration()->sshParameters());
- connect(d->connection, &SshConnection::error,
+ connect(d->connection, &SshConnection::errorOccurred,
this, &AbstractRemoteLinuxDeployService::handleConnectionFailure);
if (d->connection->state() == SshConnection::Connected) {
handleConnected();
diff --git a/src/plugins/remotelinux/genericdirectuploadservice.cpp b/src/plugins/remotelinux/genericdirectuploadservice.cpp
index 3112d519c8..100cf04020 100644
--- a/src/plugins/remotelinux/genericdirectuploadservice.cpp
+++ b/src/plugins/remotelinux/genericdirectuploadservice.cpp
@@ -26,9 +26,10 @@
#include "genericdirectuploadservice.h"
#include <projectexplorer/deployablefile.h>
+#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
-#include <ssh/sftpchannel.h>
+#include <ssh/sftptransfer.h>
#include <ssh/sshconnection.h>
#include <ssh/sshremoteprocess.h>
@@ -44,46 +45,27 @@ using namespace QSsh;
namespace RemoteLinux {
namespace Internal {
-namespace {
-enum State { Inactive, InitializingSftp, Uploading };
-} // anonymous namespace
-
-enum class JobType {
- PreQuery,
- Upload,
- Mkdir,
- Ln,
- Chmod,
- PostQuery,
- None
-};
-struct Job
-{
- DeployableFile file;
- JobType type;
- QDateTime result;
- explicit Job(const DeployableFile &file = DeployableFile(), JobType type = JobType::None,
- const QDateTime &result = QDateTime())
- : file(file), type(type), result(result) {}
-};
+enum State { Inactive, PreChecking, Uploading, PostProcessing };
class GenericDirectUploadServicePrivate
{
public:
+ DeployableFile getFileForProcess(SshRemoteProcess *proc)
+ {
+ const auto it = remoteProcs.find(proc);
+ QTC_ASSERT(it != remoteProcs.end(), return DeployableFile());
+ const DeployableFile file = *it;
+ remoteProcs.erase(it);
+ return file;
+ }
+
bool incremental = false;
bool ignoreMissingFiles = false;
- bool uploadJobRunning = false;
+ QHash<SshRemoteProcess *, DeployableFile> remoteProcs;
State state = Inactive;
-
QList<DeployableFile> filesToUpload;
-
- QHash<SftpJobId, Job> runningJobs;
-
- SshRemoteProcess::Ptr runningProc;
- DeployableFile runningProcFile;
-
- SftpChannel::Ptr uploader;
+ SftpTransferPtr uploader;
QList<DeployableFile> deployableFiles;
};
@@ -145,253 +127,62 @@ void GenericDirectUploadService::stopDeviceSetup()
void GenericDirectUploadService::doDeploy()
{
QTC_ASSERT(d->state == Inactive, setFinished(); return);
-
- d->uploader = connection()->createSftpChannel();
- connect(d->uploader.data(), &SftpChannel::initialized,
- this, &GenericDirectUploadService::handleSftpInitialized);
- connect(d->uploader.data(), &SftpChannel::channelError,
- this, &GenericDirectUploadService::handleSftpChannelError);
- d->uploader->initialize();
- d->state = InitializingSftp;
-}
-
-void GenericDirectUploadService::handleSftpInitialized()
-{
- QTC_ASSERT(d->state == InitializingSftp, setFinished(); return);
- QTC_ASSERT(!d->deployableFiles.isEmpty(), setFinished(); return);
- connect(d->uploader.data(), &SftpChannel::finished,
- this, &GenericDirectUploadService::handleJobFinished);
- connect(d->uploader.data(), &SftpChannel::fileInfoAvailable,
- this, &GenericDirectUploadService::handleFileInfoAvailable);
- d->state = Uploading;
+ d->state = PreChecking;
queryFiles();
}
-void GenericDirectUploadService::handleSftpChannelError(const QString &message)
+QDateTime GenericDirectUploadService::timestampFromStat(const DeployableFile &file,
+ SshRemoteProcess *statProc)
{
- QTC_ASSERT(d->state == InitializingSftp, setFinished(); return);
-
- emit errorMessage(tr("SFTP initialization failed: %1").arg(message));
- setFinished();
- handleDeploymentDone();
-}
-
-void GenericDirectUploadService::handleFileInfoAvailable(SftpJobId jobId,
- const QList<SftpFileInfo> &fileInfos)
-{
- QTC_ASSERT(d->state == Uploading, return);
- QTC_ASSERT(fileInfos.length() == 1, return);
- auto it = d->runningJobs.find(jobId);
- QTC_ASSERT(it != d->runningJobs.end(), return);
- it->result = QDateTime::fromSecsSinceEpoch(fileInfos.at(0).mtime);
-}
-
-void GenericDirectUploadService::handleJobFinished(SftpJobId jobId, const QString &errorMsg)
-{
- auto it = d->runningJobs.find(jobId);
- QTC_ASSERT(it != d->runningJobs.end(), return);
-
- Job job = *it;
- d->runningJobs.erase(it);
-
- switch (job.type) {
- case JobType::PreQuery:
- if (hasRemoteFileChanged(job.file, job.result)) {
- d->filesToUpload.append(job.file);
- if (!d->uploadJobRunning)
- uploadNextFile();
- } else {
- tryFinish();
- }
- break;
- case JobType::Upload:
- QTC_CHECK(d->uploadJobRunning);
-
- if (!errorMsg.isEmpty()) {
- QString errorString = tr("Upload of file \"%1\" failed. The server said: \"%2\".")
- .arg(job.file.localFilePath().toUserOutput(), errorMsg);
- if (errorMsg == QLatin1String("Failure")
- && job.file.remoteDirectory().contains(QLatin1String("/bin"))) {
- errorString += QLatin1Char(' ')
- + tr("If \"%1\" is currently running on the remote host, "
- "you might need to stop it first.").arg(job.file.remoteFilePath());
- }
- emit errorMessage(errorString);
- setFinished();
- handleDeploymentDone();
- return;
- }
-
- // This is done for Windows.
- if (job.file.isExecutable()) {
- const QString command = QLatin1String("chmod a+x ")
- + Utils::QtcProcess::quoteArgUnix(job.file.remoteFilePath());
- d->runningProc = connection()->createRemoteProcess(command.toUtf8());
- d->runningProcFile = job.file;
- connect(d->runningProc.data(), &SshRemoteProcess::closed,
- this, &GenericDirectUploadService::handleUploadProcFinished);
- connect(d->runningProc.data(), &SshRemoteProcess::readyReadStandardOutput,
- this, &GenericDirectUploadService::handleStdOutData);
- connect(d->runningProc.data(), &SshRemoteProcess::readyReadStandardError,
- this, &GenericDirectUploadService::handleStdErrData);
- connect(d->runningProc.data(), &SshRemoteProcess::readChannelFinished,
- this, &GenericDirectUploadService::handleReadChannelFinished);
- d->runningProc->start();
- } else {
- d->uploadJobRunning = false;
- const SftpJobId jobId = d->uploader->statFile(job.file.remoteFilePath());
- if (jobId == SftpInvalidJob) {
- emit errorMessage(tr("SFTP stat query for %1 failed.")
- .arg(job.file.remoteFilePath()));
- saveDeploymentTimeStamp(job.file, QDateTime());
- } else {
- d->runningJobs.insert(jobId, Job(job.file, JobType::PostQuery));
- }
- uploadNextFile();
- }
- break;
- case JobType::PostQuery:
- if (!errorMsg.isEmpty()) {
- emit warningMessage(tr("Could not determine remote timestamp of %1: %2")
- .arg(job.file.remoteFilePath()).arg(errorMsg));
- }
- saveDeploymentTimeStamp(job.file, job.result);
- tryFinish();
- break;
- default:
- QTC_CHECK(false);
- break;
+ QString errorDetails;
+ if (statProc->exitStatus() != QProcess::NormalExit)
+ errorDetails = statProc->errorString();
+ else if (statProc->exitCode() != 0)
+ errorDetails = QString::fromUtf8(statProc->readAllStandardError());
+ if (!errorDetails.isEmpty()) {
+ emit warningMessage(tr("Failed to retrieve remote timestamp for file \"%1\". "
+ "Incremental deployment will not work. Error message was: %2")
+ .arg(file.remoteFilePath(), errorDetails));
+ return QDateTime();
}
-}
-
-void GenericDirectUploadService::clearRunningProc()
-{
- d->runningProc.clear();
- d->runningProcFile = DeployableFile();
- d->uploadJobRunning = false;
-}
-
-void GenericDirectUploadService::handleUploadProcFinished(int exitStatus)
-{
- QTC_ASSERT(d->state == Uploading, setFinished(); return);
- QTC_ASSERT(d->uploadJobRunning, return);
-
- if (exitStatus != SshRemoteProcess::NormalExit || d->runningProc->exitCode() != 0)
- handleProcFailure();
- else
- runPostQueryOnProcResult();
-}
-
-void GenericDirectUploadService::handleProcFailure()
-{
- emit errorMessage(tr("Failed to upload file \"%1\".")
- .arg(d->runningProcFile.localFilePath().toUserOutput()));
- clearRunningProc();
- setFinished();
- handleDeploymentDone();
-}
-
-void GenericDirectUploadService::runPostQueryOnProcResult()
-{
- const SftpJobId jobId = d->uploader->statFile(d->runningProcFile.remoteFilePath());
- if (jobId == SftpInvalidJob) {
- emit errorMessage(tr("SFTP stat query for %1 failed.")
- .arg(d->runningProcFile.remoteFilePath()));
- saveDeploymentTimeStamp(d->runningProcFile, QDateTime());
- } else {
- d->runningJobs.insert(jobId, Job(d->runningProcFile, JobType::PostQuery));
+ QByteArray output = statProc->readAllStandardOutput().trimmed();
+ const QString warningString(tr("Unexpected stat output for remote file \"%1\": %2")
+ .arg(file.remoteFilePath()).arg(QString::fromUtf8(output)));
+ if (!output.startsWith(file.remoteFilePath().toUtf8())) {
+ emit warningMessage(warningString);
+ return QDateTime();
}
- clearRunningProc();
- uploadNextFile();
-}
-
-void GenericDirectUploadService::tryFinish()
-{
- if (d->filesToUpload.isEmpty() && d->runningJobs.isEmpty() && d->runningProc.isNull()) {
- emit progressMessage(tr("All files successfully deployed."));
- setFinished();
- handleDeploymentDone();
+ const QByteArrayList columns = output.mid(file.remoteFilePath().toUtf8().size() + 1).split(' ');
+ if (columns.size() < 15) { // Normal Linux stat: 16 columns, busybox stat: 15 columns
+ emit warningMessage(warningString);
+ return QDateTime();
}
-}
-
-void GenericDirectUploadService::handleMkdirFinished(int exitStatus)
-{
- QTC_ASSERT(d->state == Uploading, setFinished(); return);
-
- QFileInfo fi = d->runningProcFile.localFilePath().toFileInfo();
- if (exitStatus != SshRemoteProcess::NormalExit || d->runningProc->exitCode() != 0) {
- handleProcFailure();
- } else if (fi.isDir()) {
- runPostQueryOnProcResult();
- } else {
- const QString remoteFilePath = d->runningProcFile.remoteFilePath();
- if (fi.isSymLink()) {
- const QString target = fi.dir().relativeFilePath(fi.symLinkTarget()); // see QTBUG-5817.
- const QStringList args = QStringList() << QLatin1String("ln") << QLatin1String("-sf")
- << target << remoteFilePath;
- const QString command = Utils::QtcProcess::joinArgs(args, Utils::OsTypeLinux);
-
- // See comment in SftpChannel::createLink as to why we can't use it.
- d->runningProc = connection()->createRemoteProcess(command.toUtf8());
- connect(d->runningProc.data(), &SshRemoteProcess::closed,
- this, &GenericDirectUploadService::handleUploadProcFinished);
- connect(d->runningProc.data(), &SshRemoteProcess::readyReadStandardOutput,
- this, &GenericDirectUploadService::handleStdOutData);
- connect(d->runningProc.data(), &SshRemoteProcess::readyReadStandardError,
- this, &GenericDirectUploadService::handleStdErrData);
- connect(d->runningProc.data(), &SshRemoteProcess::readChannelFinished,
- this, &GenericDirectUploadService::handleReadChannelFinished);
- d->runningProc->start();
- } else {
- const SftpJobId job = d->uploader->uploadFile(
- d->runningProcFile.localFilePath().toString(), remoteFilePath,
- SftpOverwriteExisting);
- if (job == SftpInvalidJob) {
- const QString message = tr("Failed to upload file \"%1\": "
- "Could not open for reading.")
- .arg(d->runningProcFile.localFilePath().toUserOutput());
- clearRunningProc();
- if (d->ignoreMissingFiles) {
- emit warningMessage(message);
- uploadNextFile();
- } else {
- emit errorMessage(message);
- setFinished();
- handleDeploymentDone();
- }
- } else {
- d->runningJobs[job] = Job(d->runningProcFile, JobType::Upload);
- clearRunningProc();
- d->uploadJobRunning = true;
- }
- }
+ bool isNumber;
+ const qint64 secsSinceEpoch = columns.at(12).toLongLong(&isNumber);
+ if (!isNumber) {
+ emit warningMessage(warningString);
+ return QDateTime();
}
+ return QDateTime::fromSecsSinceEpoch(secsSinceEpoch);
}
-void GenericDirectUploadService::handleStdOutData()
-{
- auto const process = qobject_cast<SshRemoteProcess *>(sender());
- if (process)
- emit stdOutData(QString::fromUtf8(process->readAllStandardOutput()));
-}
-
-void GenericDirectUploadService::handleStdErrData()
-{
- auto const process = qobject_cast<SshRemoteProcess *>(sender());
- if (process)
- emit stdErrData(QString::fromUtf8(process->readAllStandardError()));
-}
-
-void GenericDirectUploadService::handleReadChannelFinished()
+void GenericDirectUploadService::checkForStateChangeOnRemoteProcFinished()
{
- auto const process = qobject_cast<SshRemoteProcess *>(sender());
- if (process && process->atEnd())
- process->close();
+ if (!d->remoteProcs.isEmpty())
+ return;
+ if (d->state == PreChecking) {
+ uploadFiles();
+ return;
+ }
+ QTC_ASSERT(d->state == PostProcessing, return);
+ emit progressMessage(tr("All files successfully deployed."));
+ setFinished();
+ handleDeploymentDone();
}
void GenericDirectUploadService::stopDeployment()
{
- QTC_ASSERT(d->state == InitializingSftp || d->state == Uploading, setFinished(); return);
+ QTC_ASSERT(d->state != Inactive, return);
setFinished();
handleDeploymentDone();
@@ -419,80 +210,143 @@ QList<DeployableFile> GenericDirectUploadService::collectFilesToUpload(
void GenericDirectUploadService::setFinished()
{
d->state = Inactive;
- if (d->runningProc)
- disconnect(d->runningProc.data(), nullptr, this, nullptr);
+ for (auto it = d->remoteProcs.begin(); it != d->remoteProcs.end(); ++it) {
+ it.key()->disconnect();
+ it.key()->terminate();
+ }
+ d->remoteProcs.clear();
if (d->uploader) {
- disconnect(d->uploader.data(), nullptr, this, nullptr);
- d->uploader->closeChannel();
+ d->uploader->disconnect();
+ d->uploader->stop();
+ d->uploader.release()->deleteLater();
}
- clearRunningProc();
- d->uploadJobRunning = false;
- d->runningJobs.clear();
d->filesToUpload.clear();
}
-void GenericDirectUploadService::uploadNextFile()
+void GenericDirectUploadService::queryFiles()
{
- QTC_ASSERT(!d->uploadJobRunning, return);
+ QTC_ASSERT(d->state == PreChecking || d->state == PostProcessing, return);
+ QTC_ASSERT(d->state == PostProcessing || d->remoteProcs.isEmpty(), return);
- if (d->filesToUpload.isEmpty()) {
- tryFinish();
- return;
+ const QList<DeployableFile> &filesToCheck = d->state == PreChecking
+ ? d->deployableFiles : d->filesToUpload;
+ for (const DeployableFile &file : filesToCheck) {
+ if (d->state == PreChecking && (!d->incremental || hasLocalFileChanged(file))) {
+ d->filesToUpload.append(file);
+ continue;
+ }
+ // We'd like to use --format=%Y, but it's not supported by busybox.
+ const QByteArray statCmd = "stat -t "
+ + Utils::QtcProcess::quoteArgUnix(file.remoteFilePath()).toUtf8();
+ SshRemoteProcess * const statProc = connection()->createRemoteProcess(statCmd).release();
+ statProc->setParent(this);
+ connect(statProc, &SshRemoteProcess::done, this,
+ [this, statProc, state = d->state] {
+ QTC_ASSERT(d->state == state, return);
+ const DeployableFile file = d->getFileForProcess(statProc);
+ QTC_ASSERT(file.isValid(), return);
+ const QDateTime timestamp = timestampFromStat(file, statProc);
+ statProc->deleteLater();
+ switch (state) {
+ case PreChecking:
+ if (!timestamp.isValid() || hasRemoteFileChanged(file, timestamp))
+ d->filesToUpload.append(file);
+ break;
+ case PostProcessing:
+ if (timestamp.isValid())
+ saveDeploymentTimeStamp(file, timestamp);
+ break;
+ case Inactive:
+ case Uploading:
+ QTC_CHECK(false);
+ break;
+ }
+ checkForStateChangeOnRemoteProcFinished();
+ });
+ d->remoteProcs.insert(statProc, file);
+ statProc->start();
}
+ checkForStateChangeOnRemoteProcFinished();
+}
- const DeployableFile df = d->filesToUpload.takeFirst();
-
- QString dirToCreate = df.remoteDirectory();
- if (dirToCreate.isEmpty()) {
- emit warningMessage(tr("Warning: No remote path set for local file \"%1\". "
- "Skipping upload.").arg(df.localFilePath().toUserOutput()));
- uploadNextFile();
+void GenericDirectUploadService::uploadFiles()
+{
+ QTC_ASSERT(d->state == PreChecking, return);
+ d->state = Uploading;
+ if (d->filesToUpload.empty()) {
+ emit progressMessage(tr("No files need to be uploaded."));
+ setFinished();
+ handleDeploymentDone();
return;
}
-
- QFileInfo fi = df.localFilePath().toFileInfo();
- if (fi.isDir())
- dirToCreate += QLatin1Char('/') + fi.fileName();
- const QString command = QLatin1String("mkdir -p ")
- + Utils::QtcProcess::quoteArgUnix(dirToCreate);
- QTC_CHECK(d->runningProc.isNull());
- d->runningProc = connection()->createRemoteProcess(command.toUtf8());
- connect(d->runningProc.data(), &SshRemoteProcess::closed,
- this, &GenericDirectUploadService::handleMkdirFinished);
- connect(d->runningProc.data(), &SshRemoteProcess::readyReadStandardOutput,
- this, &GenericDirectUploadService::handleStdOutData);
- connect(d->runningProc.data(), &SshRemoteProcess::readyReadStandardError,
- this, &GenericDirectUploadService::handleStdErrData);
- connect(d->runningProc.data(), &SshRemoteProcess::readChannelFinished,
- this, &GenericDirectUploadService::handleReadChannelFinished);
- emit progressMessage(tr("Uploading file \"%1\"...")
- .arg(df.localFilePath().toUserOutput()));
- d->runningProcFile = df;
- d->runningProc->start();
- d->uploadJobRunning = true;
+ emit progressMessage(tr("%n file(s) need to be uploaded.", "", d->filesToUpload.size()));
+ FilesToTransfer filesToTransfer;
+ for (const DeployableFile &f : d->filesToUpload) {
+ if (!f.localFilePath().exists()) {
+ const QString message = tr("Local file \"%1\" does not exist.")
+ .arg(f.localFilePath().toUserOutput());
+ if (d->ignoreMissingFiles) {
+ emit warningMessage(message);
+ continue;
+ } else {
+ emit errorMessage(message);
+ setFinished();
+ handleDeploymentDone();
+ return;
+ }
+ }
+ filesToTransfer << FileToTransfer(f.localFilePath().toString(), f.remoteFilePath());
+ }
+ d->uploader = connection()->createUpload(filesToTransfer, FileTransferErrorHandling::Abort);
+ connect(d->uploader.get(), &SftpTransfer::done, [this](const QString &error) {
+ QTC_ASSERT(d->state == Uploading, return);
+ if (!error.isEmpty()) {
+ emit errorMessage(error);
+ setFinished();
+ handleDeploymentDone();
+ return;
+ }
+ d->state = PostProcessing;
+ chmod();
+ queryFiles();
+ });
+ connect(d->uploader.get(), &SftpTransfer::progress,
+ this, &GenericDirectUploadService::progressMessage);
+ d->uploader->start();
}
-void GenericDirectUploadService::queryFiles()
+void GenericDirectUploadService::chmod()
{
- QTC_ASSERT(d->state == Uploading, return);
-
- for (const DeployableFile &file : qAsConst(d->deployableFiles)) {
- if (!d->incremental || hasLocalFileChanged(file)) {
- d->filesToUpload.append(file);
- continue;
- }
-
- const SftpJobId jobId = d->uploader->statFile(file.remoteFilePath());
- if (jobId == SftpInvalidJob) {
- emit warningMessage(tr("SFTP stat query for %1 failed.").arg(file.remoteFilePath()));
- d->filesToUpload.append(file);
+ QTC_ASSERT(d->state == PostProcessing, return);
+ if (!Utils::HostOsInfo::isWindowsHost())
+ return;
+ for (const DeployableFile &f : d->filesToUpload) {
+ if (!f.isExecutable())
continue;
- }
-
- d->runningJobs.insert(jobId, Job(file, JobType::PreQuery));
+ const QString command = QLatin1String("chmod a+x ")
+ + Utils::QtcProcess::quoteArgUnix(f.remoteFilePath());
+ SshRemoteProcess * const chmodProc
+ = connection()->createRemoteProcess(command.toUtf8()).release();
+ chmodProc->setParent(this);
+ connect(chmodProc, &SshRemoteProcess::done, this,
+ [this, chmodProc, state = d->state](const QString &error) {
+ QTC_ASSERT(state == d->state, return);
+ const DeployableFile file = d->getFileForProcess(chmodProc);
+ QTC_ASSERT(file.isValid(), return);
+ if (!error.isEmpty()) {
+ emit warningMessage(tr("Remote chmod failed for file \"%1\": %2")
+ .arg(file.remoteFilePath(), error));
+ } else if (chmodProc->exitCode() != 0) {
+ emit warningMessage(tr("Remote chmod failed for file \"%1\": %2")
+ .arg(file.remoteFilePath(),
+ QString::fromUtf8(chmodProc->readAllStandardError())));
+ }
+ chmodProc->deleteLater();
+ checkForStateChangeOnRemoteProcFinished();
+ });
+ d->remoteProcs.insert(chmodProc, f);
+ chmodProc->start();
}
-
- uploadNextFile();
}
} //namespace RemoteLinux
diff --git a/src/plugins/remotelinux/genericdirectuploadservice.h b/src/plugins/remotelinux/genericdirectuploadservice.h
index 4f5dbb71b2..c41f8f99cc 100644
--- a/src/plugins/remotelinux/genericdirectuploadservice.h
+++ b/src/plugins/remotelinux/genericdirectuploadservice.h
@@ -32,10 +32,11 @@
#include <QList>
+QT_FORWARD_DECLARE_CLASS(QDateTime)
QT_FORWARD_DECLARE_CLASS(QString)
namespace ProjectExplorer { class DeployableFile; }
-
+namespace QSsh { class SshRemoteProcess; }
namespace RemoteLinux {
namespace Internal { class GenericDirectUploadServicePrivate; }
@@ -60,27 +61,16 @@ public:
void stopDeployment() override;
private:
- void handleSftpInitialized();
- void handleSftpChannelError(const QString &errorMessage);
- void handleFileInfoAvailable(QSsh::SftpJobId jobId, const QList<QSsh::SftpFileInfo> &fileInfos);
- void handleJobFinished(QSsh::SftpJobId jobId, const QString &errorMsg);
- void handleUploadProcFinished(int exitStatus);
- void handleMkdirFinished(int exitStatus);
- void handleStdOutData();
- void handleStdErrData();
- void handleReadChannelFinished();
+ QDateTime timestampFromStat(const ProjectExplorer::DeployableFile &file,
+ QSsh::SshRemoteProcess *statProc);
+ void checkForStateChangeOnRemoteProcFinished();
QList<ProjectExplorer::DeployableFile> collectFilesToUpload(
const ProjectExplorer::DeployableFile &file) const;
void setFinished();
- void uploadNextFile();
void queryFiles();
- void clearRunningProc();
-
- void handleProcFailure();
- void runPostQueryOnProcResult();
-
- void tryFinish();
+ void uploadFiles();
+ void chmod();
Internal::GenericDirectUploadServicePrivate * const d;
};
diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp
index 9ef6561a3e..5957ac428b 100644
--- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp
+++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp
@@ -48,18 +48,12 @@ GenericLinuxDeviceConfigurationWidget::GenericLinuxDeviceConfigurationWidget(
this, &GenericLinuxDeviceConfigurationWidget::hostNameEditingFinished);
connect(m_ui->userLineEdit, &QLineEdit::editingFinished,
this, &GenericLinuxDeviceConfigurationWidget::userNameEditingFinished);
- connect(m_ui->pwdLineEdit, &QLineEdit::editingFinished,
- this, &GenericLinuxDeviceConfigurationWidget::passwordEditingFinished);
- connect(m_ui->passwordButton, &QAbstractButton::toggled,
- this, &GenericLinuxDeviceConfigurationWidget::authenticationTypeChanged);
connect(m_ui->keyFileLineEdit, &PathChooser::editingFinished,
this, &GenericLinuxDeviceConfigurationWidget::keyFileEditingFinished);
connect(m_ui->keyFileLineEdit, &PathChooser::browsingFinished,
this, &GenericLinuxDeviceConfigurationWidget::keyFileEditingFinished);
connect(m_ui->keyButton, &QAbstractButton::toggled,
this, &GenericLinuxDeviceConfigurationWidget::authenticationTypeChanged);
- connect(m_ui->agentButton, &QAbstractButton::toggled,
- this, &GenericLinuxDeviceConfigurationWidget::authenticationTypeChanged);
connect(m_ui->timeoutSpinBox, &QAbstractSpinBox::editingFinished,
this, &GenericLinuxDeviceConfigurationWidget::timeoutEditingFinished);
connect(m_ui->timeoutSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
@@ -68,8 +62,6 @@ GenericLinuxDeviceConfigurationWidget::GenericLinuxDeviceConfigurationWidget(
this, &GenericLinuxDeviceConfigurationWidget::sshPortEditingFinished);
connect(m_ui->sshPortSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
this, &GenericLinuxDeviceConfigurationWidget::sshPortEditingFinished);
- connect(m_ui->showPasswordCheckBox, &QAbstractButton::toggled,
- this, &GenericLinuxDeviceConfigurationWidget::showPassword);
connect(m_ui->portsLineEdit, &QLineEdit::editingFinished,
this, &GenericLinuxDeviceConfigurationWidget::handleFreePortsChanged);
connect(m_ui->createKeyButton, &QAbstractButton::clicked,
@@ -91,15 +83,11 @@ GenericLinuxDeviceConfigurationWidget::~GenericLinuxDeviceConfigurationWidget()
void GenericLinuxDeviceConfigurationWidget::authenticationTypeChanged()
{
SshConnectionParameters sshParams = device()->sshParameters();
- const bool usePassword = m_ui->passwordButton->isChecked();
const bool useKeyFile = m_ui->keyButton->isChecked();
- sshParams.authenticationType
- = usePassword ? SshConnectionParameters::AuthenticationTypeTryAllPasswordBasedMethods
- : useKeyFile ? SshConnectionParameters::AuthenticationTypePublicKey
- : SshConnectionParameters::AuthenticationTypeAgent;
+ sshParams.authenticationType = useKeyFile
+ ? SshConnectionParameters::AuthenticationTypeSpecificKey
+ : SshConnectionParameters::AuthenticationTypeAll;
device()->setSshParameters(sshParams);
- m_ui->pwdLineEdit->setEnabled(usePassword);
- m_ui->passwordLabel->setEnabled(usePassword);
m_ui->keyFileLineEdit->setEnabled(useKeyFile);
m_ui->keyLabel->setEnabled(useKeyFile);
}
@@ -132,13 +120,6 @@ void GenericLinuxDeviceConfigurationWidget::userNameEditingFinished()
device()->setSshParameters(sshParams);
}
-void GenericLinuxDeviceConfigurationWidget::passwordEditingFinished()
-{
- SshConnectionParameters sshParams = device()->sshParameters();
- sshParams.setPassword(m_ui->pwdLineEdit->text());
- device()->setSshParameters(sshParams);
-}
-
void GenericLinuxDeviceConfigurationWidget::keyFileEditingFinished()
{
SshConnectionParameters sshParams = device()->sshParameters();
@@ -157,12 +138,6 @@ void GenericLinuxDeviceConfigurationWidget::handleFreePortsChanged()
updatePortsWarningLabel();
}
-void GenericLinuxDeviceConfigurationWidget::showPassword(bool showClearText)
-{
- m_ui->pwdLineEdit->setEchoMode(showClearText
- ? QLineEdit::Normal : QLineEdit::Password);
-}
-
void GenericLinuxDeviceConfigurationWidget::setPrivateKey(const QString &path)
{
m_ui->keyFileLineEdit->setPath(path);
@@ -190,7 +165,6 @@ void GenericLinuxDeviceConfigurationWidget::updateDeviceFromUi()
sshPortEditingFinished();
timeoutEditingFinished();
userNameEditingFinished();
- passwordEditingFinished();
keyFileEditingFinished();
handleFreePortsChanged();
gdbServerEditingFinished();
@@ -220,16 +194,12 @@ void GenericLinuxDeviceConfigurationWidget::initGui()
const SshConnectionParameters &sshParams = device()->sshParameters();
switch (sshParams.authenticationType) {
- case SshConnectionParameters::AuthenticationTypePublicKey:
+ case SshConnectionParameters::AuthenticationTypeSpecificKey:
m_ui->keyButton->setChecked(true);
break;
- case SshConnectionParameters::AuthenticationTypeAgent:
- m_ui->agentButton->setChecked(true);
+ case SshConnectionParameters::AuthenticationTypeAll:
+ m_ui->defaultAuthButton->setChecked(true);
break;
- case SshConnectionParameters::AuthenticationTypePassword:
- case SshConnectionParameters::AuthenticationTypeKeyboardInteractive:
- case SshConnectionParameters::AuthenticationTypeTryAllPasswordBasedMethods:
- m_ui->passwordButton->setChecked(true);
}
m_ui->timeoutSpinBox->setValue(sshParams.timeout);
m_ui->hostLineEdit->setEnabled(!device()->isAutoDetected());
@@ -241,9 +211,7 @@ void GenericLinuxDeviceConfigurationWidget::initGui()
m_ui->portsLineEdit->setText(device()->freePorts().toString());
m_ui->timeoutSpinBox->setValue(sshParams.timeout);
m_ui->userLineEdit->setText(sshParams.userName());
- m_ui->pwdLineEdit->setText(sshParams.password());
m_ui->keyFileLineEdit->setPath(sshParams.privateKeyFile);
- m_ui->showPasswordCheckBox->setChecked(false);
m_ui->gdbServerLineEdit->setText(device()->debugServerPath());
updatePortsWarningLabel();
}
diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.h b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.h
index 217e5b1379..7faf3494d6 100644
--- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.h
+++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.h
@@ -49,10 +49,8 @@ private:
void sshPortEditingFinished();
void timeoutEditingFinished();
void userNameEditingFinished();
- void passwordEditingFinished();
void keyFileEditingFinished();
void gdbServerEditingFinished();
- void showPassword(bool showClearText);
void handleFreePortsChanged();
void setPrivateKey(const QString &path);
void createNewKey();
diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.ui b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.ui
index 108ab2f344..6e08ace732 100644
--- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.ui
+++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.ui
@@ -52,23 +52,16 @@
<number>0</number>
</property>
<item>
- <widget class="QRadioButton" name="passwordButton">
+ <widget class="QRadioButton" name="defaultAuthButton">
<property name="text">
- <string>Password</string>
+ <string>Default</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="keyButton">
<property name="text">
- <string>&amp;Key</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QRadioButton" name="agentButton">
- <property name="text">
- <string>Key via ssh-agent</string>
+ <string>Specific &amp;key</string>
</property>
</widget>
</item>
@@ -206,33 +199,8 @@
<item row="4" column="1">
<widget class="QLineEdit" name="userLineEdit"/>
</item>
- <item row="5" column="0">
- <widget class="QLabel" name="passwordLabel">
- <property name="text">
- <string>&amp;Password:</string>
- </property>
- <property name="buddy">
- <cstring>pwdLineEdit</cstring>
- </property>
- </widget>
- </item>
<item row="5" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout_6">
- <item>
- <widget class="QLineEdit" name="pwdLineEdit">
- <property name="echoMode">
- <enum>QLineEdit::Password</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCheckBox" name="showPasswordCheckBox">
- <property name="text">
- <string>Show password</string>
- </property>
- </widget>
- </item>
- </layout>
+ <layout class="QHBoxLayout" name="horizontalLayout_6"/>
</item>
<item row="6" column="0">
<widget class="QLabel" name="keyLabel">
@@ -280,7 +248,6 @@
</widget>
</item>
</layout>
- <zorder>passwordLabel</zorder>
<zorder>authTypeButtonsWidget</zorder>
<zorder>hostNameLabel</zorder>
<zorder>userNameLabel</zorder>
@@ -302,7 +269,7 @@
</customwidget>
</customwidgets>
<tabstops>
- <tabstop>passwordButton</tabstop>
+ <tabstop>defaultAuthButton</tabstop>
<tabstop>keyButton</tabstop>
<tabstop>hostLineEdit</tabstop>
<tabstop>sshPortSpinBox</tabstop>
@@ -310,8 +277,6 @@
<tabstop>portsLineEdit</tabstop>
<tabstop>timeoutSpinBox</tabstop>
<tabstop>userLineEdit</tabstop>
- <tabstop>pwdLineEdit</tabstop>
- <tabstop>showPasswordCheckBox</tabstop>
<tabstop>createKeyButton</tabstop>
<tabstop>gdbServerLineEdit</tabstop>
</tabstops>
diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp
index f2eb58a613..30a26d66d7 100644
--- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp
+++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp
@@ -71,11 +71,10 @@ GenericLinuxDeviceConfigurationWizard::~GenericLinuxDeviceConfigurationWizard()
IDevice::Ptr GenericLinuxDeviceConfigurationWizard::device()
{
SshConnectionParameters sshParams;
- sshParams.options &= ~SshConnectionOptions(SshEnableStrictConformanceChecks); // For older SSH servers.
sshParams.url = d->setupPage.url();
sshParams.timeout = 10;
sshParams.authenticationType = d->setupPage.authenticationType();
- if (sshParams.authenticationType == SshConnectionParameters::AuthenticationTypePublicKey)
+ if (sshParams.authenticationType == SshConnectionParameters::AuthenticationTypeSpecificKey)
sshParams.privateKeyFile = d->setupPage.privateKeyFilePath();
IDevice::Ptr device = LinuxDevice::create(d->setupPage.configurationName(),
Core::Id(Constants::GenericLinuxOsType), IDevice::Hardware);
diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizardpages.cpp b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizardpages.cpp
index 88c62bcaf8..2ed7f6b1fa 100644
--- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizardpages.cpp
+++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizardpages.cpp
@@ -62,12 +62,10 @@ GenericLinuxDeviceConfigurationWizardSetupPage::GenericLinuxDeviceConfigurationW
connect(d->ui.userNameLineEdit, &QLineEdit::textChanged, this, &QWizardPage::completeChanged);
connect(d->ui.privateKeyPathChooser, &PathChooser::validChanged,
this, &QWizardPage::completeChanged);
- connect(d->ui.passwordButton, &QAbstractButton::toggled,
+ connect(d->ui.defaultAuthButton, &QAbstractButton::toggled,
this, &GenericLinuxDeviceConfigurationWizardSetupPage::handleAuthTypeChanged);
connect(d->ui.keyButton, &QAbstractButton::toggled,
this, &GenericLinuxDeviceConfigurationWizardSetupPage::handleAuthTypeChanged);
- connect(d->ui.agentButton, &QAbstractButton::toggled,
- this, &GenericLinuxDeviceConfigurationWizardSetupPage::handleAuthTypeChanged);
}
GenericLinuxDeviceConfigurationWizardSetupPage::~GenericLinuxDeviceConfigurationWizardSetupPage()
@@ -80,8 +78,7 @@ void GenericLinuxDeviceConfigurationWizardSetupPage::initializePage()
d->ui.nameLineEdit->setText(defaultConfigurationName());
d->ui.hostNameLineEdit->setText(defaultHostName());
d->ui.userNameLineEdit->setText(defaultUserName());
- d->ui.passwordButton->setChecked(true);
- d->ui.passwordLineEdit->setText(defaultPassWord());
+ d->ui.defaultAuthButton->setChecked(true);
d->ui.privateKeyPathChooser->setPath(ProjectExplorer::IDevice::defaultPrivateKeyFilePath());
handleAuthTypeChanged();
}
@@ -91,7 +88,7 @@ bool GenericLinuxDeviceConfigurationWizardSetupPage::isComplete() const
return !configurationName().isEmpty()
&& !d->ui.hostNameLineEdit->text().trimmed().isEmpty()
&& !d->ui.userNameLineEdit->text().trimmed().isEmpty()
- && (authenticationType() != SshConnectionParameters::AuthenticationTypePublicKey
+ && (authenticationType() != SshConnectionParameters::AuthenticationTypeSpecificKey
|| d->ui.privateKeyPathChooser->isValid());
}
@@ -105,17 +102,14 @@ QUrl GenericLinuxDeviceConfigurationWizardSetupPage::url() const
QUrl url;
url.setHost(d->ui.hostNameLineEdit->text().trimmed());
url.setUserName(d->ui.userNameLineEdit->text().trimmed());
- url.setPassword(d->ui.passwordLineEdit->text());
url.setPort(22);
return url;
}
SshConnectionParameters::AuthenticationType GenericLinuxDeviceConfigurationWizardSetupPage::authenticationType() const
{
- return d->ui.passwordButton->isChecked()
- ? SshConnectionParameters::AuthenticationTypeTryAllPasswordBasedMethods
- : d->ui.keyButton->isChecked() ? SshConnectionParameters::AuthenticationTypePublicKey
- : SshConnectionParameters::AuthenticationTypeAgent;
+ return d->ui.keyButton->isChecked() ? SshConnectionParameters::AuthenticationTypeSpecificKey
+ : SshConnectionParameters::AuthenticationTypeAll;
}
QString GenericLinuxDeviceConfigurationWizardSetupPage::privateKeyFilePath() const
@@ -145,10 +139,8 @@ QString GenericLinuxDeviceConfigurationWizardSetupPage::defaultPassWord() const
void GenericLinuxDeviceConfigurationWizardSetupPage::handleAuthTypeChanged()
{
- d->ui.passwordLineEdit->setEnabled(authenticationType()
- == SshConnectionParameters::AuthenticationTypeTryAllPasswordBasedMethods);
d->ui.privateKeyPathChooser->setEnabled(authenticationType()
- == SshConnectionParameters::AuthenticationTypePublicKey);
+ == SshConnectionParameters::AuthenticationTypeSpecificKey);
emit completeChanged();
}
diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizardsetuppage.ui b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizardsetuppage.ui
index 54ccf0d7b0..1c93a359b7 100644
--- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizardsetuppage.ui
+++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizardsetuppage.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>564</width>
- <height>207</height>
+ <width>590</width>
+ <height>188</height>
</rect>
</property>
<property name="windowTitle">
@@ -92,23 +92,16 @@
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
- <widget class="QRadioButton" name="passwordButton">
+ <widget class="QRadioButton" name="defaultAuthButton">
<property name="text">
- <string>Password</string>
+ <string>Default</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="keyButton">
<property name="text">
- <string>Key</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QRadioButton" name="agentButton">
- <property name="text">
- <string>Agent</string>
+ <string>Specific key</string>
</property>
</widget>
</item>
@@ -128,44 +121,13 @@
</layout>
</item>
<item row="4" column="0">
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>The user's password:</string>
- </property>
- </widget>
- </item>
- <item row="4" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout_5">
- <item>
- <widget class="QLineEdit" name="passwordLineEdit">
- <property name="echoMode">
- <enum>QLineEdit::Password</enum>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_4">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item row="5" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>The file containing the user's private key:</string>
</property>
</widget>
</item>
- <item row="5" column="1">
+ <item row="4" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="Utils::PathChooser" name="privateKeyPathChooser" native="true"/>
diff --git a/src/plugins/remotelinux/linuxdevicetester.cpp b/src/plugins/remotelinux/linuxdevicetester.cpp
index 913b3250e2..0702c41738 100644
--- a/src/plugins/remotelinux/linuxdevicetester.cpp
+++ b/src/plugins/remotelinux/linuxdevicetester.cpp
@@ -28,7 +28,7 @@
#include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
#include <utils/port.h>
#include <utils/qtcassert.h>
-#include <ssh/sftpchannel.h>
+#include <ssh/sftptransfer.h>
#include <ssh/sshremoteprocess.h>
#include <ssh/sshconnection.h>
@@ -48,9 +48,9 @@ class GenericLinuxDeviceTesterPrivate
public:
IDevice::ConstPtr deviceConfiguration;
SshConnection *connection = nullptr;
- SshRemoteProcess::Ptr process;
+ SshRemoteProcessPtr process;
DeviceUsedPortsGatherer portsGatherer;
- SftpChannel::Ptr sftpChannel;
+ SftpTransferPtr sftpUpload;
State state = Inactive;
};
@@ -76,7 +76,7 @@ void GenericLinuxDeviceTester::testDevice(const IDevice::ConstPtr &deviceConfigu
d->connection = new SshConnection(deviceConfiguration->sshParameters(), this);
connect(d->connection, &SshConnection::connected,
this, &GenericLinuxDeviceTester::handleConnected);
- connect(d->connection, &SshConnection::error,
+ connect(d->connection, &SshConnection::errorOccurred,
this, &GenericLinuxDeviceTester::handleConnectionFailure);
emit progressMessage(tr("Connecting to host..."));
@@ -99,7 +99,7 @@ void GenericLinuxDeviceTester::stopTest()
d->process->close();
break;
case TestingSftp:
- d->sftpChannel->closeChannel();
+ d->sftpUpload->stop();
break;
case Inactive:
break;
@@ -113,7 +113,7 @@ void GenericLinuxDeviceTester::handleConnected()
QTC_ASSERT(d->state == Connecting, return);
d->process = d->connection->createRemoteProcess("uname -rsm");
- connect(d->process.data(), &SshRemoteProcess::closed,
+ connect(d->process.get(), &SshRemoteProcess::done,
this, &GenericLinuxDeviceTester::handleProcessFinished);
emit progressMessage(tr("Checking kernel version..."));
@@ -125,15 +125,16 @@ void GenericLinuxDeviceTester::handleConnectionFailure()
{
QTC_ASSERT(d->state != Inactive, return);
- emit errorMessage(tr("SSH connection failure: %1").arg(d->connection->errorString()) + QLatin1Char('\n'));
+ emit errorMessage(d->connection->errorString() + QLatin1Char('\n'));
+
setFinished(TestFailure);
}
-void GenericLinuxDeviceTester::handleProcessFinished(int exitStatus)
+void GenericLinuxDeviceTester::handleProcessFinished(const QString &error)
{
QTC_ASSERT(d->state == RunningUname, return);
- if (exitStatus != SshRemoteProcess::NormalExit || d->process->exitCode() != 0) {
+ if (!error.isEmpty() || d->process->exitCode() != 0) {
const QByteArray stderrOutput = d->process->readAllStandardError();
if (!stderrOutput.isEmpty())
emit errorMessage(tr("uname failed: %1").arg(QString::fromUtf8(stderrOutput)) + QLatin1Char('\n'));
@@ -176,34 +177,35 @@ void GenericLinuxDeviceTester::handlePortListReady()
.arg(portList) + QLatin1Char('\n'));
}
- emit progressMessage(tr("Checking if an SFTP channel can be set up..."));
- d->sftpChannel = d->connection->createSftpChannel();
- connect(d->sftpChannel.data(), &SftpChannel::initialized,
- this, &GenericLinuxDeviceTester::handleSftpInitialized);
- connect(d->sftpChannel.data(), &SftpChannel::channelError,
- this, &GenericLinuxDeviceTester::handleSftpError);
+ emit progressMessage(tr("Checking whether an SFTP connection can be set up..."));
+ d->sftpUpload = d->connection->createUpload(FilesToTransfer(),
+ FileTransferErrorHandling::Abort);
+ connect(d->sftpUpload.get(), &SftpTransfer::done,
+ this, &GenericLinuxDeviceTester::handleSftpFinished);
d->state = TestingSftp;
- d->sftpChannel->initialize();
-}
-
-void GenericLinuxDeviceTester::handleSftpInitialized()
-{
- QTC_ASSERT(d->state == TestingSftp, return);
- emit progressMessage(tr("SFTP channel successfully initialized.\n"));
- setFinished(TestSuccess);
+ d->sftpUpload->start();
}
-void GenericLinuxDeviceTester::handleSftpError(const QString &message)
+void GenericLinuxDeviceTester::handleSftpFinished(const QString &error)
{
QTC_ASSERT(d->state == TestingSftp, return);
- emit errorMessage(tr("Error setting up SFTP channel: %1\n").arg(message));
- setFinished(TestFailure);
+ if (!error.isEmpty()) {
+ emit errorMessage(tr("Error setting up SFTP connection: %1\n").arg(error));
+ setFinished(TestFailure);
+ } else {
+ emit progressMessage(tr("SFTP service available.\n"));
+ setFinished(TestSuccess);
+ }
}
void GenericLinuxDeviceTester::setFinished(TestResult result)
{
d->state = Inactive;
disconnect(&d->portsGatherer, nullptr, this, nullptr);
+ if (d->sftpUpload) {
+ disconnect(d->sftpUpload.get(), nullptr, this, nullptr);
+ d->sftpUpload.release()->deleteLater();
+ }
if (d->connection) {
disconnect(d->connection, nullptr, this, nullptr);
d->connection->deleteLater();
diff --git a/src/plugins/remotelinux/linuxdevicetester.h b/src/plugins/remotelinux/linuxdevicetester.h
index d845c2e26c..a63ec51d04 100644
--- a/src/plugins/remotelinux/linuxdevicetester.h
+++ b/src/plugins/remotelinux/linuxdevicetester.h
@@ -47,11 +47,10 @@ public:
private:
void handleConnected();
void handleConnectionFailure();
- void handleProcessFinished(int exitStatus);
+ void handleProcessFinished(const QString &error);
void handlePortsGatheringError(const QString &message);
void handlePortListReady();
- void handleSftpInitialized();
- void handleSftpError(const QString &message);
+ void handleSftpFinished(const QString &error);
void setFinished(ProjectExplorer::DeviceTester::TestResult result);
Internal::GenericLinuxDeviceTesterPrivate * const d;
diff --git a/src/plugins/remotelinux/packageuploader.cpp b/src/plugins/remotelinux/packageuploader.cpp
index 5de62edf07..cb5af23784 100644
--- a/src/plugins/remotelinux/packageuploader.cpp
+++ b/src/plugins/remotelinux/packageuploader.cpp
@@ -26,7 +26,7 @@
#include "packageuploader.h"
#include <utils/qtcassert.h>
-#include <ssh/sftpchannel.h>
+#include <ssh/sftptransfer.h>
#include <ssh/sshconnection.h>
using namespace QSsh;
@@ -46,29 +46,24 @@ void PackageUploader::uploadPackage(SshConnection *connection,
{
QTC_ASSERT(m_state == Inactive, return);
- setState(InitializingSftp);
+ setState(Uploading);
emit progress(tr("Preparing SFTP connection..."));
- m_localFilePath = localFilePath;
- m_remoteFilePath = remoteFilePath;
m_connection = connection;
- connect(m_connection, &SshConnection::error,
+ connect(m_connection, &SshConnection::errorOccurred,
this, &PackageUploader::handleConnectionFailure);
- m_uploader = m_connection->createSftpChannel();
- connect(m_uploader.data(), &SftpChannel::initialized,
- this, &PackageUploader::handleSftpChannelInitialized);
- connect(m_uploader.data(), &SftpChannel::channelError,
- this, &PackageUploader::handleSftpChannelError);
- connect(m_uploader.data(), &SftpChannel::finished,
- this, &PackageUploader::handleSftpJobFinished);
- m_uploader->initialize();
+ m_uploader = m_connection->createUpload({FileToTransfer(localFilePath, remoteFilePath)},
+ FileTransferErrorHandling::Abort);
+ connect(m_uploader.get(), &SftpTransfer::done, this, &PackageUploader::handleUploadDone);
+ m_uploader->start();
}
void PackageUploader::cancelUpload()
{
- QTC_ASSERT(m_state == InitializingSftp || m_state == Uploading, return);
+ QTC_ASSERT(m_state == Uploading, return);
- cleanup();
+ setState(Inactive);
+ emit uploadFinished(tr("Package upload canceled."));
}
void PackageUploader::handleConnectionFailure()
@@ -81,53 +76,15 @@ void PackageUploader::handleConnectionFailure()
emit uploadFinished(tr("Connection failed: %1").arg(errorMsg));
}
-void PackageUploader::handleSftpChannelError(const QString &errorMsg)
+void PackageUploader::handleUploadDone(const QString &errorMsg)
{
- QTC_ASSERT(m_state == InitializingSftp || m_state == Inactive, return);
-
- if (m_state == Inactive)
- return;
+ QTC_ASSERT(m_state == Uploading, return);
setState(Inactive);
- emit uploadFinished(tr("SFTP error: %1").arg(errorMsg));
-}
-
-void PackageUploader::handleSftpChannelInitialized()
-{
- QTC_ASSERT(m_state == InitializingSftp || m_state == Inactive, return);
-
- if (m_state == Inactive)
- return;
-
- const SftpJobId job = m_uploader->uploadFile(m_localFilePath,
- m_remoteFilePath, SftpOverwriteExisting);
- if (job == SftpInvalidJob) {
- setState(Inactive);
- emit uploadFinished(tr("Package upload failed: Could not open file."));
- } else {
- emit progress(tr("Starting upload..."));
- setState(Uploading);
- }
-}
-
-void PackageUploader::handleSftpJobFinished(SftpJobId, const QString &errorMsg)
-{
- QTC_ASSERT(m_state == Uploading || m_state == Inactive, return);
-
- if (m_state == Inactive)
- return;
-
if (!errorMsg.isEmpty())
emit uploadFinished(tr("Failed to upload package: %2").arg(errorMsg));
else
emit uploadFinished();
- cleanup();
-}
-
-void PackageUploader::cleanup()
-{
- m_uploader->closeChannel();
- setState(Inactive);
}
void PackageUploader::setState(State newState)
@@ -136,8 +93,9 @@ void PackageUploader::setState(State newState)
return;
if (newState == Inactive) {
if (m_uploader) {
- disconnect(m_uploader.data(), nullptr, this, nullptr);
- m_uploader.clear();
+ disconnect(m_uploader.get(), nullptr, this, nullptr);
+ m_uploader->stop();
+ m_uploader.release()->deleteLater();
}
if (m_connection) {
disconnect(m_connection, nullptr, this, nullptr);
diff --git a/src/plugins/remotelinux/packageuploader.h b/src/plugins/remotelinux/packageuploader.h
index 7e61eefbe3..99499e9a16 100644
--- a/src/plugins/remotelinux/packageuploader.h
+++ b/src/plugins/remotelinux/packageuploader.h
@@ -26,7 +26,6 @@
#pragma once
#include <QObject>
-#include <QSharedPointer>
#include <QString>
#include <ssh/sftpdefs.h>
@@ -56,20 +55,15 @@ signals:
void uploadFinished(const QString &errorMsg = QString());
private:
- enum State { InitializingSftp, Uploading, Inactive };
+ enum State { Uploading, Inactive };
void handleConnectionFailure();
- void handleSftpChannelInitialized();
- void handleSftpChannelError(const QString &error);
- void handleSftpJobFinished(QSsh::SftpJobId job, const QString &error);
- void cleanup();
+ void handleUploadDone(const QString &error);
void setState(State newState);
State m_state;
QSsh::SshConnection *m_connection;
- QSharedPointer<QSsh::SftpChannel> m_uploader;
- QString m_localFilePath;
- QString m_remoteFilePath;
+ QSsh::SftpTransferPtr m_uploader;
};
} // namespace Internal
diff --git a/src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.cpp b/src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.cpp
index 5a336125ed..de2d43906c 100644
--- a/src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.cpp
+++ b/src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.cpp
@@ -69,17 +69,12 @@ void RemoteLinuxCheckForFreeDiskSpaceService::handleStdErr()
void RemoteLinuxCheckForFreeDiskSpaceService::handleProcessFinished()
{
- switch (d->processRunner->processExitStatus()) {
- case QSsh::SshRemoteProcess::FailedToStart:
- emit errorMessage(tr("Remote process failed to start."));
+ if (!d->processRunner->processErrorString().isEmpty()) {
+ emit errorMessage(tr("Remote process failed: %1")
+ .arg(d->processRunner->processErrorString()));
stopDeployment();
return;
- case QSsh::SshRemoteProcess::CrashExit:
- emit errorMessage(tr("Remote process crashed."));
- stopDeployment();
- return;
- case QSsh::SshRemoteProcess::NormalExit:
- break;
+
}
bool isNumber;
diff --git a/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.cpp b/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.cpp
index eddcda0f19..ffa1dfe6af 100644
--- a/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.cpp
+++ b/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.cpp
@@ -119,14 +119,12 @@ void RemoteLinuxCustomCommandDeployService::handleStderr()
emit stdErrData(QString::fromUtf8(d->runner->readAllStandardError()));
}
-void RemoteLinuxCustomCommandDeployService::handleProcessClosed(int exitStatus)
+void RemoteLinuxCustomCommandDeployService::handleProcessClosed(const QString &error)
{
QTC_ASSERT(d->state == Running, return);
- if (exitStatus == SshRemoteProcess::FailedToStart) {
- emit errorMessage(tr("Remote process failed to start."));
- } else if (exitStatus == SshRemoteProcess::CrashExit) {
- emit errorMessage(tr("Remote process was killed by a signal."));
+ if (!error.isEmpty()) {
+ emit errorMessage(tr("Remote process failed: %1").arg(error));
} else if (d->runner->processExitCode() != 0) {
emit errorMessage(tr("Remote process finished with exit code %1.")
.arg(d->runner->processExitCode()));
diff --git a/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.h b/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.h
index 75352420f6..33b0e67b1d 100644
--- a/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.h
+++ b/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.h
@@ -52,7 +52,7 @@ protected:
private:
void handleStdout();
void handleStderr();
- void handleProcessClosed(int exitStatus);
+ void handleProcessClosed(const QString &error);
Internal::RemoteLinuxCustomCommandDeployservicePrivate *d;
};
diff --git a/src/plugins/remotelinux/remotelinuxpackageinstaller.cpp b/src/plugins/remotelinux/remotelinuxpackageinstaller.cpp
index 3f84fa7c37..4d3439931b 100644
--- a/src/plugins/remotelinux/remotelinuxpackageinstaller.cpp
+++ b/src/plugins/remotelinux/remotelinuxpackageinstaller.cpp
@@ -98,12 +98,12 @@ void AbstractRemoteLinuxPackageInstaller::handleConnectionError()
setFinished();
}
-void AbstractRemoteLinuxPackageInstaller::handleInstallationFinished(int exitStatus)
+void AbstractRemoteLinuxPackageInstaller::handleInstallationFinished(const QString &error)
{
if (!d->isRunning)
return;
- if (exitStatus != SshRemoteProcess::NormalExit || d->installer->processExitCode() != 0)
+ if (!error.isEmpty() || d->installer->processExitCode() != 0)
emit finished(tr("Installing package failed."));
else if (!errorString().isEmpty())
emit finished(errorString());
diff --git a/src/plugins/remotelinux/remotelinuxpackageinstaller.h b/src/plugins/remotelinux/remotelinuxpackageinstaller.h
index 25f1b34f77..ddf713eda2 100644
--- a/src/plugins/remotelinux/remotelinuxpackageinstaller.h
+++ b/src/plugins/remotelinux/remotelinuxpackageinstaller.h
@@ -54,7 +54,7 @@ protected:
private:
void handleConnectionError();
- void handleInstallationFinished(int exitStatus);
+ void handleInstallationFinished(const QString &error);
void handleInstallerOutput();
void handleInstallerErrorOutput();
diff --git a/src/plugins/remotelinux/sshkeydeployer.cpp b/src/plugins/remotelinux/sshkeydeployer.cpp
index 5d7cccdc8f..7581a72018 100644
--- a/src/plugins/remotelinux/sshkeydeployer.cpp
+++ b/src/plugins/remotelinux/sshkeydeployer.cpp
@@ -79,19 +79,18 @@ void SshKeyDeployer::handleConnectionFailure()
emit error(tr("Connection failed: %1").arg(d->deployProcess.lastConnectionErrorString()));
}
-void SshKeyDeployer::handleKeyUploadFinished(int exitStatus)
+void SshKeyDeployer::handleKeyUploadFinished()
{
- Q_ASSERT(exitStatus == SshRemoteProcess::FailedToStart
- || exitStatus == SshRemoteProcess::CrashExit
- || exitStatus == SshRemoteProcess::NormalExit);
-
const int exitCode = d->deployProcess.processExitCode();
const QString errorMsg = d->deployProcess.processErrorString();
cleanup();
- if (exitStatus == SshRemoteProcess::NormalExit && exitCode == 0)
+ if (errorMsg.isEmpty() && exitCode == 0) {
emit finishedSuccessfully();
- else
- emit error(tr("Key deployment failed: %1.").arg(errorMsg));
+ } else {
+ emit error(tr("Key deployment failed: %1.").arg(errorMsg.isEmpty()
+ ? QString::fromUtf8(d->deployProcess.readAllStandardError())
+ : errorMsg));
+ }
}
void SshKeyDeployer::stopDeployment()
diff --git a/src/plugins/remotelinux/sshkeydeployer.h b/src/plugins/remotelinux/sshkeydeployer.h
index 8c5df26d8a..664543cb3c 100644
--- a/src/plugins/remotelinux/sshkeydeployer.h
+++ b/src/plugins/remotelinux/sshkeydeployer.h
@@ -52,7 +52,7 @@ signals:
private:
void handleConnectionFailure();
- void handleKeyUploadFinished(int exitStatus);
+ void handleKeyUploadFinished();
void cleanup();
Internal::SshKeyDeployerPrivate * const d;
diff --git a/src/plugins/valgrind/callgrind/callgrindcontroller.cpp b/src/plugins/valgrind/callgrind/callgrindcontroller.cpp
index 40a025b5d9..1974ced68f 100644
--- a/src/plugins/valgrind/callgrind/callgrindcontroller.cpp
+++ b/src/plugins/valgrind/callgrind/callgrindcontroller.cpp
@@ -25,7 +25,7 @@
#include "callgrindcontroller.h"
-#include <ssh/sftpchannel.h>
+#include <ssh/sftpsession.h>
#include <ssh/sshconnectionmanager.h>
#include <utils/fileutils.h>
@@ -237,12 +237,12 @@ void CallgrindController::foundRemoteFile()
{
m_remoteFile = m_findRemoteFile->readAllStandardOutput().trimmed();
- m_sftp = m_ssh->createSftpChannel();
- connect(m_sftp.data(), &QSsh::SftpChannel::finished,
+ m_sftp = m_ssh->createSftpSession();
+ connect(m_sftp.get(), &QSsh::SftpSession::commandFinished,
this, &CallgrindController::sftpJobFinished);
- connect(m_sftp.data(), &QSsh::SftpChannel::initialized,
+ connect(m_sftp.get(), &QSsh::SftpSession::started,
this, &CallgrindController::sftpInitialized);
- m_sftp->initialize();
+ m_sftp->start();
}
void CallgrindController::sftpInitialized()
@@ -254,14 +254,14 @@ void CallgrindController::sftpInitialized()
dataFile.setAutoRemove(false);
dataFile.close();
- m_downloadJob = m_sftp->downloadFile(QString::fromUtf8(m_remoteFile), m_tempDataFile, QSsh::SftpOverwriteExisting);
+ m_downloadJob = m_sftp->downloadFile(QString::fromUtf8(m_remoteFile), m_tempDataFile);
}
void CallgrindController::sftpJobFinished(QSsh::SftpJobId job, const QString &error)
{
QTC_ASSERT(job == m_downloadJob, return);
- m_sftp->closeChannel();
+ m_sftp->quit();
if (error.isEmpty())
emit localParseDataAvailable(m_tempDataFile);
diff --git a/src/plugins/valgrind/callgrind/callgrindcontroller.h b/src/plugins/valgrind/callgrind/callgrindcontroller.h
index 057ec794a8..d3a6639e4e 100644
--- a/src/plugins/valgrind/callgrind/callgrindcontroller.h
+++ b/src/plugins/valgrind/callgrind/callgrindcontroller.h
@@ -26,7 +26,6 @@
#pragma once
#include <ssh/sshremoteprocess.h>
-#include <ssh/sftpchannel.h>
#include <ssh/sshconnection.h>
#include <projectexplorer/runconfiguration.h>
@@ -91,8 +90,8 @@ private:
// remote callgrind support
QSsh::SshConnection *m_ssh = nullptr;
QString m_tempDataFile;
- QSsh::SshRemoteProcess::Ptr m_findRemoteFile;
- QSsh::SftpChannel::Ptr m_sftp;
+ QSsh::SshRemoteProcessPtr m_findRemoteFile;
+ QSsh::SftpSessionPtr m_sftp;
QSsh::SftpJobId m_downloadJob = 0;
QByteArray m_remoteFile;
};
diff --git a/src/plugins/valgrind/memchecktool.cpp b/src/plugins/valgrind/memchecktool.cpp
index 31fbab64cf..a9e8fbd51c 100644
--- a/src/plugins/valgrind/memchecktool.cpp
+++ b/src/plugins/valgrind/memchecktool.cpp
@@ -155,7 +155,7 @@ public:
*localServerAddress = connection.connectionInfo().localAddress;
reportStarted();
});
- connect(&connection, &QSsh::SshConnection::error, this, [this] {
+ connect(&connection, &QSsh::SshConnection::errorOccurred, this, [this] {
reportFailure();
});
}