forked from qt-creator/qt-creator
RemoteLinux: Add new deploy step that checks for free space.
Tool output in the "disk full" case can be rather unhelpful, so we check in advance. Change-Id: Ia3f5f0b456b91acf9a8f8e72de870e1df6ea8e80 Reviewed-by: Nikolai Kosjar <nikolai.kosjar@nokia.com>
This commit is contained in:
@@ -43,6 +43,7 @@
|
|||||||
#include <projectexplorer/projectexplorerconstants.h>
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
#include <projectexplorer/target.h>
|
#include <projectexplorer/target.h>
|
||||||
#include <remotelinux/genericdirectuploadstep.h>
|
#include <remotelinux/genericdirectuploadstep.h>
|
||||||
|
#include <remotelinux/remotelinuxcheckforfreediskspacestep.h>
|
||||||
#include <remotelinux/uploadandinstalltarpackagestep.h>
|
#include <remotelinux/uploadandinstalltarpackagestep.h>
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
@@ -83,6 +84,7 @@ QList<Core::Id> MaemoDeployStepFactory::availableCreationIds(BuildStepList *pare
|
|||||||
if (qobject_cast<Qt4Maemo5Target *>(parent->target()))
|
if (qobject_cast<Qt4Maemo5Target *>(parent->target()))
|
||||||
ids << MaemoInstallPackageViaMountStep::stepId()
|
ids << MaemoInstallPackageViaMountStep::stepId()
|
||||||
<< MaemoCopyFilesViaMountStep::stepId();
|
<< MaemoCopyFilesViaMountStep::stepId();
|
||||||
|
ids << RemoteLinuxCheckForFreeDiskSpaceStep::stepId();
|
||||||
|
|
||||||
return ids;
|
return ids;
|
||||||
}
|
}
|
||||||
@@ -107,6 +109,8 @@ QString MaemoDeployStepFactory::displayNameForId(const Core::Id id) const
|
|||||||
return MaemoMakeInstallToSysrootStep::displayName();
|
return MaemoMakeInstallToSysrootStep::displayName();
|
||||||
else if (id == GenericDirectUploadStep::stepId())
|
else if (id == GenericDirectUploadStep::stepId())
|
||||||
return GenericDirectUploadStep::displayName();
|
return GenericDirectUploadStep::displayName();
|
||||||
|
if (id == RemoteLinuxCheckForFreeDiskSpaceStep::stepId())
|
||||||
|
return RemoteLinuxCheckForFreeDiskSpaceStep::stepDisplayName();
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,6 +144,8 @@ BuildStep *MaemoDeployStepFactory::create(BuildStepList *parent, const Core::Id
|
|||||||
return new MeegoUploadAndInstallPackageStep(parent);
|
return new MeegoUploadAndInstallPackageStep(parent);
|
||||||
} else if (id == GenericDirectUploadStep::stepId()) {
|
} else if (id == GenericDirectUploadStep::stepId()) {
|
||||||
return new GenericDirectUploadStep(parent, id);
|
return new GenericDirectUploadStep(parent, id);
|
||||||
|
} else if (id == RemoteLinuxCheckForFreeDiskSpaceStep::stepId()) {
|
||||||
|
return new RemoteLinuxCheckForFreeDiskSpaceStep(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -197,7 +203,10 @@ BuildStep *MaemoDeployStepFactory::clone(BuildStepList *parent, BuildStep *produ
|
|||||||
} else if (product->id() == GenericDirectUploadStep::stepId()) {
|
} else if (product->id() == GenericDirectUploadStep::stepId()) {
|
||||||
return new GenericDirectUploadStep(parent,
|
return new GenericDirectUploadStep(parent,
|
||||||
qobject_cast<GenericDirectUploadStep *>(product));
|
qobject_cast<GenericDirectUploadStep *>(product));
|
||||||
|
} else if (RemoteLinuxCheckForFreeDiskSpaceStep * const other = qobject_cast<RemoteLinuxCheckForFreeDiskSpaceStep *>(product)) {
|
||||||
|
return new RemoteLinuxCheckForFreeDiskSpaceStep(parent, other);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -44,6 +44,7 @@
|
|||||||
#include <remotelinux/deployablefile.h>
|
#include <remotelinux/deployablefile.h>
|
||||||
#include <remotelinux/deployablefilesperprofile.h>
|
#include <remotelinux/deployablefilesperprofile.h>
|
||||||
#include <remotelinux/deploymentinfo.h>
|
#include <remotelinux/deploymentinfo.h>
|
||||||
|
#include <remotelinux/remotelinuxcheckforfreediskspacestep.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
@@ -158,19 +159,23 @@ DeployConfiguration *Qt4MaemoDeployConfigurationFactory::create(Target *parent,
|
|||||||
DeployConfiguration * const dc = new Qt4MaemoDeployConfiguration(parent, id, displayName);
|
DeployConfiguration * const dc = new Qt4MaemoDeployConfiguration(parent, id, displayName);
|
||||||
if (id == Qt4MaemoDeployConfiguration::fremantleWithoutPackagingId()) {
|
if (id == Qt4MaemoDeployConfiguration::fremantleWithoutPackagingId()) {
|
||||||
dc->stepList()->insertStep(0, new MaemoMakeInstallToSysrootStep(dc->stepList()));
|
dc->stepList()->insertStep(0, new MaemoMakeInstallToSysrootStep(dc->stepList()));
|
||||||
dc->stepList()->insertStep(1, new MaemoCopyFilesViaMountStep(dc->stepList()));
|
dc->stepList()->insertStep(1, new RemoteLinuxCheckForFreeDiskSpaceStep(dc->stepList()));
|
||||||
|
dc->stepList()->insertStep(2, new MaemoCopyFilesViaMountStep(dc->stepList()));
|
||||||
} else if (id == Qt4MaemoDeployConfiguration::fremantleWithPackagingId()) {
|
} else if (id == Qt4MaemoDeployConfiguration::fremantleWithPackagingId()) {
|
||||||
dc->stepList()->insertStep(0, new MaemoDebianPackageCreationStep(dc->stepList()));
|
dc->stepList()->insertStep(0, new MaemoDebianPackageCreationStep(dc->stepList()));
|
||||||
dc->stepList()->insertStep(1, new MaemoInstallDebianPackageToSysrootStep(dc->stepList()));
|
dc->stepList()->insertStep(1, new MaemoInstallDebianPackageToSysrootStep(dc->stepList()));
|
||||||
dc->stepList()->insertStep(2, new MaemoInstallPackageViaMountStep(dc->stepList()));
|
dc->stepList()->insertStep(2, new RemoteLinuxCheckForFreeDiskSpaceStep(dc->stepList()));
|
||||||
|
dc->stepList()->insertStep(3, new MaemoInstallPackageViaMountStep(dc->stepList()));
|
||||||
} else if (id == Qt4MaemoDeployConfiguration::harmattanId()) {
|
} else if (id == Qt4MaemoDeployConfiguration::harmattanId()) {
|
||||||
dc->stepList()->insertStep(0, new MaemoDebianPackageCreationStep(dc->stepList()));
|
dc->stepList()->insertStep(0, new MaemoDebianPackageCreationStep(dc->stepList()));
|
||||||
dc->stepList()->insertStep(1, new MaemoInstallDebianPackageToSysrootStep(dc->stepList()));
|
dc->stepList()->insertStep(1, new MaemoInstallDebianPackageToSysrootStep(dc->stepList()));
|
||||||
dc->stepList()->insertStep(2, new MaemoUploadAndInstallPackageStep(dc->stepList()));
|
dc->stepList()->insertStep(2, new RemoteLinuxCheckForFreeDiskSpaceStep(dc->stepList()));
|
||||||
|
dc->stepList()->insertStep(3, new MaemoUploadAndInstallPackageStep(dc->stepList()));
|
||||||
} else if (id == Qt4MaemoDeployConfiguration::meegoId()) {
|
} else if (id == Qt4MaemoDeployConfiguration::meegoId()) {
|
||||||
dc->stepList()->insertStep(0, new MaemoRpmPackageCreationStep(dc->stepList()));
|
dc->stepList()->insertStep(0, new MaemoRpmPackageCreationStep(dc->stepList()));
|
||||||
dc->stepList()->insertStep(1, new MaemoInstallRpmPackageToSysrootStep(dc->stepList()));
|
dc->stepList()->insertStep(1, new MaemoInstallRpmPackageToSysrootStep(dc->stepList()));
|
||||||
dc->stepList()->insertStep(2, new MeegoUploadAndInstallPackageStep(dc->stepList()));
|
dc->stepList()->insertStep(2, new RemoteLinuxCheckForFreeDiskSpaceStep(dc->stepList()));
|
||||||
|
dc->stepList()->insertStep(3, new MeegoUploadAndInstallPackageStep(dc->stepList()));
|
||||||
}
|
}
|
||||||
return dc;
|
return dc;
|
||||||
}
|
}
|
||||||
|
@@ -32,6 +32,7 @@
|
|||||||
#include "genericremotelinuxdeploystepfactory.h"
|
#include "genericremotelinuxdeploystepfactory.h"
|
||||||
|
|
||||||
#include "genericdirectuploadstep.h"
|
#include "genericdirectuploadstep.h"
|
||||||
|
#include "remotelinuxcheckforfreediskspacestep.h"
|
||||||
#include "remotelinuxdeployconfigurationfactory.h"
|
#include "remotelinuxdeployconfigurationfactory.h"
|
||||||
#include "remotelinuxcustomcommanddeploymentstep.h"
|
#include "remotelinuxcustomcommanddeploymentstep.h"
|
||||||
#include "tarpackagecreationstep.h"
|
#include "tarpackagecreationstep.h"
|
||||||
@@ -58,7 +59,8 @@ QList<Core::Id> GenericRemoteLinuxDeployStepFactory::availableCreationIds(BuildS
|
|||||||
return ids;
|
return ids;
|
||||||
ids << TarPackageCreationStep::stepId() << UploadAndInstallTarPackageStep::stepId()
|
ids << TarPackageCreationStep::stepId() << UploadAndInstallTarPackageStep::stepId()
|
||||||
<< GenericDirectUploadStep::stepId()
|
<< GenericDirectUploadStep::stepId()
|
||||||
<< GenericRemoteLinuxCustomCommandDeploymentStep::stepId();
|
<< GenericRemoteLinuxCustomCommandDeploymentStep::stepId()
|
||||||
|
<< RemoteLinuxCheckForFreeDiskSpaceStep::stepId();
|
||||||
return ids;
|
return ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,6 +74,8 @@ QString GenericRemoteLinuxDeployStepFactory::displayNameForId(const Core::Id id)
|
|||||||
return GenericDirectUploadStep::displayName();
|
return GenericDirectUploadStep::displayName();
|
||||||
if (id == GenericRemoteLinuxCustomCommandDeploymentStep::stepId())
|
if (id == GenericRemoteLinuxCustomCommandDeploymentStep::stepId())
|
||||||
return GenericRemoteLinuxCustomCommandDeploymentStep::stepDisplayName();
|
return GenericRemoteLinuxCustomCommandDeploymentStep::stepDisplayName();
|
||||||
|
if (id == RemoteLinuxCheckForFreeDiskSpaceStep::stepId())
|
||||||
|
return RemoteLinuxCheckForFreeDiskSpaceStep::stepDisplayName();
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,6 +96,8 @@ BuildStep *GenericRemoteLinuxDeployStepFactory::create(BuildStepList *parent, co
|
|||||||
return new GenericDirectUploadStep(parent, GenericDirectUploadStep::stepId());
|
return new GenericDirectUploadStep(parent, GenericDirectUploadStep::stepId());
|
||||||
if (id == GenericRemoteLinuxCustomCommandDeploymentStep::stepId())
|
if (id == GenericRemoteLinuxCustomCommandDeploymentStep::stepId())
|
||||||
return new GenericRemoteLinuxCustomCommandDeploymentStep(parent);
|
return new GenericRemoteLinuxCustomCommandDeploymentStep(parent);
|
||||||
|
if (id == RemoteLinuxCheckForFreeDiskSpaceStep::stepId())
|
||||||
|
return new RemoteLinuxCheckForFreeDiskSpaceStep(parent);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,6 +135,8 @@ BuildStep *GenericRemoteLinuxDeployStepFactory::clone(BuildStepList *parent, Bui
|
|||||||
return new GenericDirectUploadStep(parent, other);
|
return new GenericDirectUploadStep(parent, other);
|
||||||
if (GenericRemoteLinuxCustomCommandDeploymentStep * const other = qobject_cast<GenericRemoteLinuxCustomCommandDeploymentStep *>(product))
|
if (GenericRemoteLinuxCustomCommandDeploymentStep * const other = qobject_cast<GenericRemoteLinuxCustomCommandDeploymentStep *>(product))
|
||||||
return new GenericRemoteLinuxCustomCommandDeploymentStep(parent, other);
|
return new GenericRemoteLinuxCustomCommandDeploymentStep(parent, other);
|
||||||
|
if (RemoteLinuxCheckForFreeDiskSpaceStep * const other = qobject_cast<RemoteLinuxCheckForFreeDiskSpaceStep *>(product))
|
||||||
|
return new RemoteLinuxCheckForFreeDiskSpaceStep(parent, other);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -57,7 +57,9 @@ HEADERS += \
|
|||||||
remotelinuxcustomcommanddeployservice.h \
|
remotelinuxcustomcommanddeployservice.h \
|
||||||
remotelinuxcustomcommanddeploymentstep.h \
|
remotelinuxcustomcommanddeploymentstep.h \
|
||||||
abstractembeddedlinuxtarget.h \
|
abstractembeddedlinuxtarget.h \
|
||||||
genericlinuxdeviceconfigurationwidget.h
|
genericlinuxdeviceconfigurationwidget.h \
|
||||||
|
remotelinuxcheckforfreediskspaceservice.h \
|
||||||
|
remotelinuxcheckforfreediskspacestep.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
genericembeddedlinuxtarget.cpp \
|
genericembeddedlinuxtarget.cpp \
|
||||||
@@ -108,7 +110,9 @@ SOURCES += \
|
|||||||
remotelinuxcustomcommanddeployservice.cpp \
|
remotelinuxcustomcommanddeployservice.cpp \
|
||||||
remotelinuxcustomcommanddeploymentstep.cpp \
|
remotelinuxcustomcommanddeploymentstep.cpp \
|
||||||
abstractembeddedlinuxtarget.cpp \
|
abstractembeddedlinuxtarget.cpp \
|
||||||
genericlinuxdeviceconfigurationwidget.cpp
|
genericlinuxdeviceconfigurationwidget.cpp \
|
||||||
|
remotelinuxcheckforfreediskspaceservice.cpp \
|
||||||
|
remotelinuxcheckforfreediskspacestep.cpp
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
genericlinuxdeviceconfigurationwizardsetuppage.ui \
|
genericlinuxdeviceconfigurationwizardsetuppage.ui \
|
||||||
@@ -116,7 +120,8 @@ FORMS += \
|
|||||||
remotelinuxprocessesdialog.ui \
|
remotelinuxprocessesdialog.ui \
|
||||||
remotelinuxdeployconfigurationwidget.ui \
|
remotelinuxdeployconfigurationwidget.ui \
|
||||||
profilesupdatedialog.ui \
|
profilesupdatedialog.ui \
|
||||||
genericlinuxdeviceconfigurationwidget.ui
|
genericlinuxdeviceconfigurationwidget.ui \
|
||||||
|
remotelinuxcheckforfreediskspacestepwidget.ui
|
||||||
|
|
||||||
RESOURCES += remotelinux.qrc
|
RESOURCES += remotelinux.qrc
|
||||||
|
|
||||||
|
@@ -129,6 +129,11 @@ QtcPlugin {
|
|||||||
"remotelinuxruncontrolfactory.h",
|
"remotelinuxruncontrolfactory.h",
|
||||||
"tarpackagecreationstep.cpp",
|
"tarpackagecreationstep.cpp",
|
||||||
"uploadandinstalltarpackagestep.cpp",
|
"uploadandinstalltarpackagestep.cpp",
|
||||||
|
"remotelinuxcheckforfreediskspaceservice.h",
|
||||||
|
"remotelinuxcheckforfreediskspaceservice.cpp",
|
||||||
|
"remotelinuxcheckforfreediskspacestep.h",
|
||||||
|
"remotelinuxcheckforfreediskspacestep.cpp",
|
||||||
|
"remotelinuxcheckforfreediskspacestepwidget.ui",
|
||||||
"images/embeddedtarget.png"
|
"images/embeddedtarget.png"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@@ -0,0 +1,169 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
||||||
|
** Please review the following information to ensure the GNU Lesser General
|
||||||
|
** Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** If you have questions regarding the use of this file, please contact
|
||||||
|
** Nokia at qt-info@nokia.com.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
#include "remotelinuxcheckforfreediskspaceservice.h"
|
||||||
|
|
||||||
|
#include "linuxdeviceconfiguration.h"
|
||||||
|
|
||||||
|
#include <ssh/sshremoteprocessrunner.h>
|
||||||
|
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace RemoteLinux {
|
||||||
|
namespace Internal {
|
||||||
|
class RemoteLinuxCheckForFreeDiskSpaceServicePrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QString pathToCheck;
|
||||||
|
quint64 requiredSpaceInBytes;
|
||||||
|
QSsh::SshRemoteProcessRunner *processRunner;
|
||||||
|
QByteArray processOutput;
|
||||||
|
};
|
||||||
|
} // namespace Internal
|
||||||
|
|
||||||
|
RemoteLinuxCheckForFreeDiskSpaceService::RemoteLinuxCheckForFreeDiskSpaceService(QObject *parent)
|
||||||
|
: AbstractRemoteLinuxDeployService(parent),
|
||||||
|
d(new Internal::RemoteLinuxCheckForFreeDiskSpaceServicePrivate)
|
||||||
|
{
|
||||||
|
d->processRunner = 0;
|
||||||
|
d->requiredSpaceInBytes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoteLinuxCheckForFreeDiskSpaceService::~RemoteLinuxCheckForFreeDiskSpaceService()
|
||||||
|
{
|
||||||
|
cleanup();
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteLinuxCheckForFreeDiskSpaceService::setPathToCheck(const QString &path)
|
||||||
|
{
|
||||||
|
d->pathToCheck = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteLinuxCheckForFreeDiskSpaceService::setRequiredSpaceInBytes(quint64 sizeInBytes)
|
||||||
|
{
|
||||||
|
d->requiredSpaceInBytes = sizeInBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteLinuxCheckForFreeDiskSpaceService::handleStdOut(const QByteArray &output)
|
||||||
|
{
|
||||||
|
d->processOutput += output;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteLinuxCheckForFreeDiskSpaceService::handleStdErr(const QByteArray &output)
|
||||||
|
{
|
||||||
|
emit stdErrData(QString::fromUtf8(output));
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteLinuxCheckForFreeDiskSpaceService::handleProcessFinished()
|
||||||
|
{
|
||||||
|
switch (d->processRunner->processExitStatus()) {
|
||||||
|
case QSsh::SshRemoteProcess::FailedToStart:
|
||||||
|
emit errorMessage(tr("Remote process failed to start."));
|
||||||
|
stopDeployment();
|
||||||
|
return;
|
||||||
|
case QSsh::SshRemoteProcess::KilledBySignal:
|
||||||
|
emit errorMessage(tr("Remote process crashed."));
|
||||||
|
stopDeployment();
|
||||||
|
return;
|
||||||
|
case QSsh::SshRemoteProcess::ExitedNormally:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isNumber;
|
||||||
|
d->processOutput.chop(1); // newline
|
||||||
|
quint64 freeSpace = d->processOutput.toULongLong(&isNumber);
|
||||||
|
if (!isNumber) {
|
||||||
|
emit errorMessage(tr("Unexpected output from remote process: '%1'.")
|
||||||
|
.arg(QString::fromUtf8(d->processOutput)));
|
||||||
|
stopDeployment();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
freeSpace *= 1024;
|
||||||
|
if (freeSpace < d->requiredSpaceInBytes) {
|
||||||
|
emit errorMessage(tr("The remote file system has only %1 bytes of free space, "
|
||||||
|
"but %2 bytes are required.").arg(freeSpace).arg(d->requiredSpaceInBytes));
|
||||||
|
stopDeployment();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit progressMessage(tr("The remote file system has %1 bytes of free space, going ahead.")
|
||||||
|
.arg(freeSpace));
|
||||||
|
stopDeployment();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RemoteLinuxCheckForFreeDiskSpaceService::isDeploymentPossible(QString *whyNot) const
|
||||||
|
{
|
||||||
|
if (!AbstractRemoteLinuxDeployService::isDeploymentPossible(whyNot))
|
||||||
|
return false;
|
||||||
|
if (!d->pathToCheck.startsWith(QLatin1Char('/'))) {
|
||||||
|
if (whyNot) {
|
||||||
|
*whyNot = tr("Cannot check for free disk space: '%1' is not an absolute path.")
|
||||||
|
.arg(d->pathToCheck);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteLinuxCheckForFreeDiskSpaceService::doDeploy()
|
||||||
|
{
|
||||||
|
d->processRunner = new QSsh::SshRemoteProcessRunner;
|
||||||
|
connect(d->processRunner, SIGNAL(processClosed(int)), SLOT(handleProcessFinished()));
|
||||||
|
connect(d->processRunner, SIGNAL(processOutputAvailable(QByteArray)),
|
||||||
|
SLOT(handleStdOut(QByteArray)));
|
||||||
|
connect(d->processRunner, SIGNAL(processErrorOutputAvailable(QByteArray)),
|
||||||
|
SLOT(handleStdErr(QByteArray)));
|
||||||
|
const QString command = QString::fromLocal8Bit("df -k -P %1 |tail -n 1 |sed 's/ */ /g' "
|
||||||
|
"|cut -d ' ' -f 4").arg(d->pathToCheck);
|
||||||
|
d->processRunner->run(command.toUtf8(), deviceConfiguration()->sshParameters());
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteLinuxCheckForFreeDiskSpaceService::stopDeployment()
|
||||||
|
{
|
||||||
|
cleanup();
|
||||||
|
handleDeploymentDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteLinuxCheckForFreeDiskSpaceService::cleanup()
|
||||||
|
{
|
||||||
|
if (d->processRunner) {
|
||||||
|
disconnect(d->processRunner, 0, this, 0);
|
||||||
|
d->processRunner->cancel();
|
||||||
|
delete d->processRunner;
|
||||||
|
d->processRunner = 0;
|
||||||
|
}
|
||||||
|
d->processOutput.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace RemoteLinux
|
@@ -0,0 +1,71 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
||||||
|
** Please review the following information to ensure the GNU Lesser General
|
||||||
|
** Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** If you have questions regarding the use of this file, please contact
|
||||||
|
** Nokia at qt-info@nokia.com.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
#ifndef REMOTELINUXCHECKFORFREEDISKSPACESERVICE_H
|
||||||
|
#define REMOTELINUXCHECKFORFREEDISKSPACESERVICE_H
|
||||||
|
|
||||||
|
#include "abstractremotelinuxdeployservice.h"
|
||||||
|
|
||||||
|
namespace RemoteLinux {
|
||||||
|
namespace Internal { class RemoteLinuxCheckForFreeDiskSpaceServicePrivate; }
|
||||||
|
|
||||||
|
class REMOTELINUX_EXPORT RemoteLinuxCheckForFreeDiskSpaceService : public AbstractRemoteLinuxDeployService
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
RemoteLinuxCheckForFreeDiskSpaceService(QObject *parent = 0);
|
||||||
|
~RemoteLinuxCheckForFreeDiskSpaceService();
|
||||||
|
|
||||||
|
void setPathToCheck(const QString &path);
|
||||||
|
void setRequiredSpaceInBytes(quint64 sizeInBytes);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void handleStdOut(const QByteArray &output);
|
||||||
|
void handleStdErr(const QByteArray &output);
|
||||||
|
void handleProcessFinished();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isDeploymentNecessary() const { return true; }
|
||||||
|
void doDeviceSetup() { handleDeviceSetupDone(true); }
|
||||||
|
void stopDeviceSetup() { handleDeviceSetupDone(false); }
|
||||||
|
|
||||||
|
bool isDeploymentPossible(QString *whyNot) const;
|
||||||
|
void doDeploy();
|
||||||
|
void stopDeployment();
|
||||||
|
|
||||||
|
void cleanup();
|
||||||
|
|
||||||
|
Internal::RemoteLinuxCheckForFreeDiskSpaceServicePrivate * const d;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace RemoteLinux
|
||||||
|
|
||||||
|
#endif // REMOTELINUXCHECKFORFREEDISKSPACESERVICE_H
|
190
src/plugins/remotelinux/remotelinuxcheckforfreediskspacestep.cpp
Normal file
190
src/plugins/remotelinux/remotelinuxcheckforfreediskspacestep.cpp
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
||||||
|
** Please review the following information to ensure the GNU Lesser General
|
||||||
|
** Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** If you have questions regarding the use of this file, please contact
|
||||||
|
** Nokia at qt-info@nokia.com.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
#include "remotelinuxcheckforfreediskspacestep.h"
|
||||||
|
#include "ui_remotelinuxcheckforfreediskspacestepwidget.h"
|
||||||
|
|
||||||
|
#include "remotelinuxcheckforfreediskspaceservice.h"
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
|
||||||
|
namespace RemoteLinux {
|
||||||
|
namespace Internal {
|
||||||
|
namespace {
|
||||||
|
class RemoteLinuxCheckForFreeDiskSpaceStepWidget : public BuildStepConfigWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit RemoteLinuxCheckForFreeDiskSpaceStepWidget(RemoteLinuxCheckForFreeDiskSpaceStep &step)
|
||||||
|
: m_step(step)
|
||||||
|
{
|
||||||
|
m_ui.setupUi(this);
|
||||||
|
m_ui.requiredSpaceSpinBox->setSuffix(tr("MB"));
|
||||||
|
m_ui.requiredSpaceSpinBox->setMinimum(1);
|
||||||
|
m_ui.requiredSpaceSpinBox->setMaximum(std::numeric_limits<int>::max());
|
||||||
|
|
||||||
|
m_ui.pathLineEdit->setText(m_step.pathToCheck());
|
||||||
|
m_ui.requiredSpaceSpinBox->setValue(m_step.requiredSpaceInBytes()/multiplier);
|
||||||
|
|
||||||
|
connect(m_ui.pathLineEdit, SIGNAL(textChanged(QString)), SLOT(handlePathChanged()));
|
||||||
|
connect(m_ui.requiredSpaceSpinBox, SIGNAL(valueChanged(int)),
|
||||||
|
SLOT(handleRequiredSpaceChanged()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Q_SLOT void handlePathChanged() { m_step.setPathToCheck(m_ui.pathLineEdit->text().trimmed()); }
|
||||||
|
Q_SLOT void handleRequiredSpaceChanged() {
|
||||||
|
m_step.setRequiredSpaceInBytes(quint64(m_ui.requiredSpaceSpinBox->value())*multiplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString displayName() const { return QLatin1String("<b>") + m_step.displayName()
|
||||||
|
+ QLatin1String("</b>"); }
|
||||||
|
QString summaryText() const { return displayName(); }
|
||||||
|
|
||||||
|
static const int multiplier = 1024*1024;
|
||||||
|
|
||||||
|
Ui::RemoteLinuxCheckForFreeDiskSpaceStepWidget m_ui;
|
||||||
|
RemoteLinuxCheckForFreeDiskSpaceStep &m_step;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
const char PathToCheckKey[] = "RemoteLinux.CheckForFreeDiskSpaceStep.PathToCheck";
|
||||||
|
const char RequiredSpaceKey[] = "RemoteLinux.CheckForFreeDiskSpaceStep.RequiredSpace";
|
||||||
|
|
||||||
|
class RemoteLinuxCheckForFreeDiskSpaceStepPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RemoteLinuxCheckForFreeDiskSpaceService deployService;
|
||||||
|
QString pathToCheck;
|
||||||
|
quint64 requiredSpaceInBytes;
|
||||||
|
};
|
||||||
|
} // namespace Internal
|
||||||
|
|
||||||
|
|
||||||
|
RemoteLinuxCheckForFreeDiskSpaceStep::RemoteLinuxCheckForFreeDiskSpaceStep(BuildStepList *bsl)
|
||||||
|
: AbstractRemoteLinuxDeployStep(bsl, stepId())
|
||||||
|
{
|
||||||
|
ctor();
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoteLinuxCheckForFreeDiskSpaceStep::RemoteLinuxCheckForFreeDiskSpaceStep(BuildStepList *bsl,
|
||||||
|
RemoteLinuxCheckForFreeDiskSpaceStep *other) : AbstractRemoteLinuxDeployStep(bsl, other)
|
||||||
|
{
|
||||||
|
ctor();
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoteLinuxCheckForFreeDiskSpaceStep::~RemoteLinuxCheckForFreeDiskSpaceStep()
|
||||||
|
{
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteLinuxCheckForFreeDiskSpaceStep::ctor()
|
||||||
|
{
|
||||||
|
d = new Internal::RemoteLinuxCheckForFreeDiskSpaceStepPrivate;
|
||||||
|
setDefaultDisplayName(stepDisplayName());
|
||||||
|
d->pathToCheck = QLatin1String("/");
|
||||||
|
d->requiredSpaceInBytes = 5*1024*1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteLinuxCheckForFreeDiskSpaceStep::setPathToCheck(const QString &path)
|
||||||
|
{
|
||||||
|
d->pathToCheck = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString RemoteLinuxCheckForFreeDiskSpaceStep::pathToCheck() const
|
||||||
|
{
|
||||||
|
return d->pathToCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteLinuxCheckForFreeDiskSpaceStep::setRequiredSpaceInBytes(quint64 space)
|
||||||
|
{
|
||||||
|
d->requiredSpaceInBytes = space;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 RemoteLinuxCheckForFreeDiskSpaceStep::requiredSpaceInBytes() const
|
||||||
|
{
|
||||||
|
return d->requiredSpaceInBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RemoteLinuxCheckForFreeDiskSpaceStep::fromMap(const QVariantMap &map)
|
||||||
|
{
|
||||||
|
if (!AbstractRemoteLinuxDeployStep::fromMap(map))
|
||||||
|
return false;
|
||||||
|
d->pathToCheck = map.value(QLatin1String(Internal::PathToCheckKey)).toString();
|
||||||
|
d->requiredSpaceInBytes = map.value(QLatin1String(Internal::RequiredSpaceKey)).toULongLong();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap RemoteLinuxCheckForFreeDiskSpaceStep::toMap() const
|
||||||
|
{
|
||||||
|
QVariantMap map = AbstractRemoteLinuxDeployStep::toMap();
|
||||||
|
map.insert(QLatin1String(Internal::PathToCheckKey), d->pathToCheck);
|
||||||
|
map.insert(QLatin1String(Internal::RequiredSpaceKey), d->requiredSpaceInBytes);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildStepConfigWidget *RemoteLinuxCheckForFreeDiskSpaceStep::createConfigWidget()
|
||||||
|
{
|
||||||
|
return new Internal::RemoteLinuxCheckForFreeDiskSpaceStepWidget(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RemoteLinuxCheckForFreeDiskSpaceStep::initInternal(QString *error)
|
||||||
|
{
|
||||||
|
Q_UNUSED(error);
|
||||||
|
d->deployService.setPathToCheck(d->pathToCheck);
|
||||||
|
d->deployService.setRequiredSpaceInBytes(d->requiredSpaceInBytes);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractRemoteLinuxDeployService *RemoteLinuxCheckForFreeDiskSpaceStep::deployService() const
|
||||||
|
{
|
||||||
|
return &d->deployService;
|
||||||
|
}
|
||||||
|
|
||||||
|
Core::Id RemoteLinuxCheckForFreeDiskSpaceStep::stepId()
|
||||||
|
{
|
||||||
|
return Core::Id("RemoteLinux.CheckForFreeDiskSpaceStep");
|
||||||
|
}
|
||||||
|
|
||||||
|
QString RemoteLinuxCheckForFreeDiskSpaceStep::stepDisplayName()
|
||||||
|
{
|
||||||
|
return tr("Check for free disk space");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace RemoteLinux
|
||||||
|
|
||||||
|
#include "remotelinuxcheckforfreediskspacestep.moc"
|
@@ -0,0 +1,73 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
||||||
|
** Please review the following information to ensure the GNU Lesser General
|
||||||
|
** Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** If you have questions regarding the use of this file, please contact
|
||||||
|
** Nokia at qt-info@nokia.com.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
#ifndef REMOTELINUXCHECKFORFREEDISKSPACESTEP_H
|
||||||
|
#define REMOTELINUXCHECKFORFREEDISKSPACESTEP_H
|
||||||
|
|
||||||
|
#include "abstractremotelinuxdeploystep.h"
|
||||||
|
|
||||||
|
namespace RemoteLinux {
|
||||||
|
namespace Internal { class RemoteLinuxCheckForFreeDiskSpaceStepPrivate; }
|
||||||
|
|
||||||
|
class REMOTELINUX_EXPORT RemoteLinuxCheckForFreeDiskSpaceStep : public AbstractRemoteLinuxDeployStep
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit RemoteLinuxCheckForFreeDiskSpaceStep(ProjectExplorer::BuildStepList *bsl);
|
||||||
|
RemoteLinuxCheckForFreeDiskSpaceStep(ProjectExplorer::BuildStepList *bsl,
|
||||||
|
RemoteLinuxCheckForFreeDiskSpaceStep *other);
|
||||||
|
~RemoteLinuxCheckForFreeDiskSpaceStep();
|
||||||
|
|
||||||
|
void setPathToCheck(const QString &path);
|
||||||
|
QString pathToCheck() const;
|
||||||
|
|
||||||
|
void setRequiredSpaceInBytes(quint64 space);
|
||||||
|
quint64 requiredSpaceInBytes() const;
|
||||||
|
|
||||||
|
static Core::Id stepId();
|
||||||
|
static QString stepDisplayName();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool fromMap(const QVariantMap &map);
|
||||||
|
QVariantMap toMap() const;
|
||||||
|
ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
|
||||||
|
|
||||||
|
bool initInternal(QString *error);
|
||||||
|
AbstractRemoteLinuxDeployService *deployService() const;
|
||||||
|
|
||||||
|
void ctor();
|
||||||
|
|
||||||
|
Internal::RemoteLinuxCheckForFreeDiskSpaceStepPrivate *d;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace RemoteLinux
|
||||||
|
|
||||||
|
#endif // REMOTELINUXCHECKFORFREEDISKSPACESTEP_H
|
@@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>RemoteLinuxCheckForFreeDiskSpaceStepWidget</class>
|
||||||
|
<widget class="QWidget" name="RemoteLinuxCheckForFreeDiskSpaceStepWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>420</width>
|
||||||
|
<height>74</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="pathLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Remote path to check for free space:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="pathLineEdit"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="requiredSpaceLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Required disk space:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QSpinBox" name="requiredSpaceSpinBox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="suffix">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
@@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include "genericembeddedlinuxtarget.h"
|
#include "genericembeddedlinuxtarget.h"
|
||||||
#include "genericdirectuploadstep.h"
|
#include "genericdirectuploadstep.h"
|
||||||
|
#include "remotelinuxcheckforfreediskspacestep.h"
|
||||||
#include "remotelinuxdeployconfiguration.h"
|
#include "remotelinuxdeployconfiguration.h"
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
@@ -78,7 +79,8 @@ DeployConfiguration *RemoteLinuxDeployConfigurationFactory::create(Target *paren
|
|||||||
|
|
||||||
DeployConfiguration * const dc = new RemoteLinuxDeployConfiguration(parent, id,
|
DeployConfiguration * const dc = new RemoteLinuxDeployConfiguration(parent, id,
|
||||||
genericLinuxDisplayName());
|
genericLinuxDisplayName());
|
||||||
dc->stepList()->insertStep(0, new GenericDirectUploadStep(dc->stepList(),
|
dc->stepList()->insertStep(0, new RemoteLinuxCheckForFreeDiskSpaceStep(dc->stepList()));
|
||||||
|
dc->stepList()->insertStep(1, new GenericDirectUploadStep(dc->stepList(),
|
||||||
GenericDirectUploadStep::stepId()));
|
GenericDirectUploadStep::stepId()));
|
||||||
return dc;
|
return dc;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user