1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25
26 #include "remotelinuxpackageinstaller.h"
27
28 #include <utils/qtcassert.h>
29 #include <utils/fileutils.h>
30 #include <ssh/sshremoteprocessrunner.h>
31
32 using namespace ProjectExplorer;
33 using namespace QSsh;
34
35 namespace RemoteLinux {
36 namespace Internal {
37
38 class AbstractRemoteLinuxPackageInstallerPrivate
39 {
40 public:
41 bool isRunning = false;
42 IDevice::ConstPtr deviceConfig;
43 SshRemoteProcessRunner *installer = nullptr;
44 SshRemoteProcessRunner *killProcess = nullptr;
45 };
46
47 } // namespace Internal
48
AbstractRemoteLinuxPackageInstaller(QObject * parent)49 AbstractRemoteLinuxPackageInstaller::AbstractRemoteLinuxPackageInstaller(QObject *parent)
50 : QObject(parent), d(new Internal::AbstractRemoteLinuxPackageInstallerPrivate)
51 {
52 }
53
~AbstractRemoteLinuxPackageInstaller()54 AbstractRemoteLinuxPackageInstaller::~AbstractRemoteLinuxPackageInstaller()
55 {
56 delete d;
57 }
58
installPackage(const IDevice::ConstPtr & deviceConfig,const QString & packageFilePath,bool removePackageFile)59 void AbstractRemoteLinuxPackageInstaller::installPackage(const IDevice::ConstPtr &deviceConfig,
60 const QString &packageFilePath, bool removePackageFile)
61 {
62 QTC_ASSERT(!d->isRunning, return);
63
64 d->deviceConfig = deviceConfig;
65 prepareInstallation();
66 if (!d->installer)
67 d->installer = new SshRemoteProcessRunner(this);
68 connect(d->installer, &SshRemoteProcessRunner::connectionError,
69 this, &AbstractRemoteLinuxPackageInstaller::handleConnectionError);
70 connect(d->installer, &SshRemoteProcessRunner::readyReadStandardOutput,
71 this, &AbstractRemoteLinuxPackageInstaller::handleInstallerOutput);
72 connect(d->installer, &SshRemoteProcessRunner::readyReadStandardError,
73 this, &AbstractRemoteLinuxPackageInstaller::handleInstallerErrorOutput);
74 connect(d->installer, &SshRemoteProcessRunner::processClosed,
75 this, &AbstractRemoteLinuxPackageInstaller::handleInstallationFinished);
76
77 QString cmdLine = installCommandLine(packageFilePath);
78 if (removePackageFile)
79 cmdLine += QLatin1String(" && (rm ") + packageFilePath + QLatin1String(" || :)");
80 d->installer->run(cmdLine, deviceConfig->sshParameters());
81 d->isRunning = true;
82 }
83
cancelInstallation()84 void AbstractRemoteLinuxPackageInstaller::cancelInstallation()
85 {
86 QTC_ASSERT(d->installer && d->isRunning, return);
87
88 if (!d->killProcess)
89 d->killProcess = new SshRemoteProcessRunner(this);
90 d->killProcess->run(cancelInstallationCommandLine(), d->deviceConfig->sshParameters());
91 setFinished();
92 }
93
handleConnectionError()94 void AbstractRemoteLinuxPackageInstaller::handleConnectionError()
95 {
96 if (!d->isRunning)
97 return;
98 emit finished(tr("Connection failure: %1").arg(d->installer->lastConnectionErrorString()));
99 setFinished();
100 }
101
handleInstallationFinished(const QString & error)102 void AbstractRemoteLinuxPackageInstaller::handleInstallationFinished(const QString &error)
103 {
104 if (!d->isRunning)
105 return;
106
107 if (!error.isEmpty() || d->installer->processExitCode() != 0)
108 emit finished(tr("Installing package failed."));
109 else if (!errorString().isEmpty())
110 emit finished(errorString());
111 else
112 emit finished();
113
114 setFinished();
115 }
116
handleInstallerOutput()117 void AbstractRemoteLinuxPackageInstaller::handleInstallerOutput()
118 {
119 emit stdoutData(QString::fromUtf8(d->installer->readAllStandardOutput()));
120 }
121
handleInstallerErrorOutput()122 void AbstractRemoteLinuxPackageInstaller::handleInstallerErrorOutput()
123 {
124 emit stderrData(QString::fromUtf8(d->installer->readAllStandardError()));
125 }
126
setFinished()127 void AbstractRemoteLinuxPackageInstaller::setFinished()
128 {
129 disconnect(d->installer, nullptr, this, nullptr);
130 d->isRunning = false;
131 }
132
133
RemoteLinuxTarPackageInstaller(QObject * parent)134 RemoteLinuxTarPackageInstaller::RemoteLinuxTarPackageInstaller(QObject *parent)
135 : AbstractRemoteLinuxPackageInstaller(parent)
136 {
137 }
138
installCommandLine(const QString & packageFilePath) const139 QString RemoteLinuxTarPackageInstaller::installCommandLine(const QString &packageFilePath) const
140 {
141 return QLatin1String("cd / && tar xvf ") + packageFilePath;
142 }
143
cancelInstallationCommandLine() const144 QString RemoteLinuxTarPackageInstaller::cancelInstallationCommandLine() const
145 {
146 return QLatin1String("pkill tar");
147 }
148
149 } // namespace RemoteLinux
150