Commit 076064ce authored by Christian Kandeler's avatar Christian Kandeler
Browse files

RemoteLinux: Introduce abstract packaging step.

This removes the dependency of the tar packaging step on Maemo-specific code.

Change-Id: I863b13e643a5028edaf2f571f63b1a52d229812b
Reviewed-on: http://codereview.qt.nokia.com/1709

Reviewed-by: default avatarChristian Kandeler <christian.kandeler@nokia.com>
parent 89ac110a
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.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 info@qt.nokia.com.
**
**************************************************************************/
#include "abstractpackagingstep.h"
#include "deploymentinfo.h"
#include "remotelinuxdeployconfiguration.h"
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/target.h>
#include <utils/fileutils.h>
#include <QtCore/QFileInfo>
using namespace ProjectExplorer;
namespace RemoteLinux {
namespace Internal {
class AbstractPackagingStepPrivate
{
public:
AbstractPackagingStepPrivate() : currentBuildConfiguration(0), running(false) { }
BuildConfiguration *currentBuildConfiguration;
bool running;
QString cachedPackageDirectory;
};
} // namespace Internal
AbstractPackagingStep::AbstractPackagingStep(BuildStepList *bsl, const QString &id)
: BuildStep(bsl, id)
{
ctor();
}
AbstractPackagingStep::AbstractPackagingStep(BuildStepList *bsl, AbstractPackagingStep *other)
: BuildStep(bsl, other)
{
ctor();
}
void AbstractPackagingStep::ctor()
{
m_d = new Internal::AbstractPackagingStepPrivate;
connect(target(), SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
SLOT(handleBuildConfigurationChanged()));
handleBuildConfigurationChanged();
}
AbstractPackagingStep::~AbstractPackagingStep()
{
delete m_d;
}
void AbstractPackagingStep::handleBuildConfigurationChanged()
{
if (m_d->currentBuildConfiguration)
disconnect(m_d->currentBuildConfiguration, 0, this, 0);
m_d->currentBuildConfiguration = target()->activeBuildConfiguration();
if (m_d->currentBuildConfiguration) {
connect(m_d->currentBuildConfiguration, SIGNAL(buildDirectoryChanged()), this,
SIGNAL(packageFilePathChanged()));
}
emit packageFilePathChanged();
}
QString AbstractPackagingStep::packageFilePath() const
{
if (packageDirectory().isEmpty())
return QString();
return packageDirectory() + QLatin1Char('/') + packageFileName();
}
QString AbstractPackagingStep::packageDirectory() const
{
if (m_d->running)
return m_d->cachedPackageDirectory;
return m_d->currentBuildConfiguration
? m_d->currentBuildConfiguration->buildDirectory() : QString();
}
RemoteLinuxDeployConfiguration *AbstractPackagingStep::deployConfiguration() const
{
return qobject_cast<RemoteLinuxDeployConfiguration *>(parent()->parent());
}
bool AbstractPackagingStep::isPackagingNeeded() const
{
const QSharedPointer<DeploymentInfo> &deploymentInfo = deployConfiguration()->deploymentInfo();
QFileInfo packageInfo(packageFilePath());
if (!packageInfo.exists() || deploymentInfo->isModified())
return true;
const int deployableCount = deploymentInfo->deployableCount();
for (int i = 0; i < deployableCount; ++i) {
if (Utils::FileUtils::isFileNewerThan(deploymentInfo->deployableAt(i).localFilePath,
packageInfo.lastModified()))
return true;
}
return false;
}
bool AbstractPackagingStep::init()
{
m_d->cachedPackageDirectory = packageDirectory();
return true;
}
void AbstractPackagingStep::setPackagingStarted()
{
m_d->running = true;
}
void AbstractPackagingStep::setPackagingFinished(bool success)
{
m_d->running = false;
if (success)
deployConfiguration()->deploymentInfo()->setUnmodified();
}
void AbstractPackagingStep::raiseError(const QString &errorMessage)
{
emit addOutput(errorMessage, BuildStep::ErrorOutput);
emit addTask(Task(Task::Error, errorMessage, QString(), -1,
Constants::TASK_CATEGORY_BUILDSYSTEM));
}
} // namespace RemoteLinux
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.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 info@qt.nokia.com.
**
**************************************************************************/
#ifndef ABSTRACTPACKAGINGSTEP_H
#define ABSTRACTPACKAGINGSTEP_H
#include "remotelinux_export.h"
#include <projectexplorer/buildstep.h>
namespace RemoteLinux {
class RemoteLinuxDeployConfiguration;
namespace Internal {
class AbstractPackagingStepPrivate;
}
class REMOTELINUX_EXPORT AbstractPackagingStep : public ProjectExplorer::BuildStep
{
Q_OBJECT
public:
AbstractPackagingStep(ProjectExplorer::BuildStepList *bsl, const QString &id);
AbstractPackagingStep(ProjectExplorer::BuildStepList *bsl, AbstractPackagingStep *other);
~AbstractPackagingStep();
QString packageFilePath() const;
bool init();
signals:
void packageFilePathChanged();
protected:
void setPackagingStarted();
void setPackagingFinished(bool success);
void raiseError(const QString &errorMessage);
RemoteLinuxDeployConfiguration *deployConfiguration() const;
QString packageDirectory() const;
virtual bool isPackagingNeeded() const;
private slots:
void handleBuildConfigurationChanged();
private:
virtual QString packageFileName() const=0;
void ctor();
Internal::AbstractPackagingStepPrivate *m_d;
};
} // namespace RemoteLinux
#endif // ABSTRACTPACKAGINGSTEP_H
......@@ -33,7 +33,7 @@
#include "abstractremotelinuxdeployservice.h"
#include "maemodeploystepwidget.h"
#include "qt4maemodeployconfiguration.h"
#include "remotelinuxdeployconfiguration.h"
#include <projectexplorer/projectexplorerconstants.h>
#include <qt4projectmanager/qt4buildconfiguration.h>
......
......@@ -37,7 +37,6 @@
namespace RemoteLinux {
namespace Internal {
class AbstractMaemoPackageCreationStep;
class AbstractMaemoPackageInstaller;
class AbstractUploadAndInstallPackageServicePrivate;
}
......
......@@ -32,8 +32,8 @@
#include "genericremotelinuxdeploystepfactory.h"
#include "genericdirectuploadstep.h"
#include "maemopackagecreationstep.h"
#include "remotelinuxdeployconfigurationfactory.h"
#include "tarpackagecreationstep.h"
#include "uploadandinstalltarpackagestep.h"
#include <projectexplorer/buildsteplist.h>
......@@ -55,15 +55,15 @@ QStringList GenericRemoteLinuxDeployStepFactory::availableCreationIds(BuildStepL
const DeployConfiguration * const dc = qobject_cast<DeployConfiguration *>(parent->parent());
if (!dc || dc->id() != RemoteLinuxDeployConfigurationFactory::genericDeployConfigurationId())
return ids;
ids << MaemoTarPackageCreationStep::CreatePackageId << UploadAndInstallTarPackageStep::stepId()
ids << TarPackageCreationStep::stepId() << UploadAndInstallTarPackageStep::stepId()
<< GenericDirectUploadStep::stepId();
return ids;
}
QString GenericRemoteLinuxDeployStepFactory::displayNameForId(const QString &id) const
{
if (id == MaemoTarPackageCreationStep::CreatePackageId)
return tr("Create tarball");
if (id == TarPackageCreationStep::stepId())
return TarPackageCreationStep::displayName();
if (id == UploadAndInstallTarPackageStep::stepId())
return UploadAndInstallTarPackageStep::displayName();
if (id == GenericDirectUploadStep::stepId())
......@@ -80,8 +80,8 @@ BuildStep *GenericRemoteLinuxDeployStepFactory::create(BuildStepList *parent, co
{
Q_ASSERT(canCreate(parent, id));
if (id == MaemoTarPackageCreationStep::CreatePackageId)
return new MaemoTarPackageCreationStep(parent);
if (id == TarPackageCreationStep::stepId())
return new TarPackageCreationStep(parent);
if (id == UploadAndInstallTarPackageStep::stepId())
return new UploadAndInstallTarPackageStep(parent);
if (id == GenericDirectUploadStep::stepId())
......@@ -115,8 +115,8 @@ bool GenericRemoteLinuxDeployStepFactory::canClone(BuildStepList *parent, BuildS
BuildStep *GenericRemoteLinuxDeployStepFactory::clone(BuildStepList *parent, BuildStep *product)
{
if (MaemoTarPackageCreationStep * const other = qobject_cast<MaemoTarPackageCreationStep *>(product))
return new MaemoTarPackageCreationStep(parent, other);
if (TarPackageCreationStep * const other = qobject_cast<TarPackageCreationStep *>(product))
return new TarPackageCreationStep(parent, other);
if (UploadAndInstallTarPackageStep * const other = qobject_cast<UploadAndInstallTarPackageStep*>(product))
return new UploadAndInstallTarPackageStep(parent, other);
if (GenericDirectUploadStep * const other = qobject_cast<GenericDirectUploadStep *>(product))
......
......@@ -32,12 +32,11 @@
#ifndef MAEMOPACKAGECREATIONSTEP_H
#define MAEMOPACKAGECREATIONSTEP_H
#include <projectexplorer/buildstep.h>
#include<remotelinux/abstractpackagingstep.h>
QT_BEGIN_NAMESPACE
class QDateTime;
class QFile;
class QFileInfo;
class QProcess;
QT_END_NAMESPACE
......@@ -51,14 +50,12 @@ class AbstractQt4MaemoTarget;
class AbstractDebBasedQt4MaemoTarget;
class AbstractRpmBasedQt4MaemoTarget;
class AbstractMaemoPackageCreationStep : public ProjectExplorer::BuildStep
class AbstractMaemoPackageCreationStep : public RemoteLinux::AbstractPackagingStep
{
Q_OBJECT
public:
virtual ~AbstractMaemoPackageCreationStep();
virtual QString packageFilePath() const;
QString versionString(QString *error) const;
bool setVersionString(const QString &version, QString *error);
......@@ -66,18 +63,13 @@ public:
const Qt4ProjectManager::Qt4BuildConfiguration *bc,
const QString &workingDir);
QString projectName() const;
const Qt4ProjectManager::Qt4BuildConfiguration *qt4BuildConfiguration() const;
AbstractQt4MaemoTarget *maemoTarget() const;
AbstractDebBasedQt4MaemoTarget *debBasedMaemoTarget() const;
AbstractRpmBasedQt4MaemoTarget *rpmBasedMaemoTarget() const;
RemoteLinuxDeployConfiguration *deployConfig() const;
static const QLatin1String DefaultVersionNumber;
signals:
void packageFilePathChanged();
void qtVersionChanged();
protected:
AbstractMaemoPackageCreationStep(ProjectExplorer::BuildStepList *bsl,
......@@ -85,27 +77,24 @@ protected:
AbstractMaemoPackageCreationStep(ProjectExplorer::BuildStepList *buildConfig,
AbstractMaemoPackageCreationStep *other);
void raiseError(const QString &shortMsg,
const QString &detailedMsg = QString());
bool callPackagingCommand(QProcess *proc, const QStringList &arguments);
static QString replaceDots(const QString &name);
QString buildDirectory() const;
private slots:
void handleBuildOutput();
void handleBuildConfigChanged();
private:
void ctor();
virtual bool init();
virtual void run(QFutureInterface<bool> &fi);
virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
virtual QString packageFileName() const;
virtual bool createPackage(QProcess *buildProc, const QFutureInterface<bool> &fi)=0;
virtual bool isMetaDataNewerThan(const QDateTime &packageDate) const=0;
QString projectName() const;
static QString nativePath(const QFile &file);
bool packagingNeeded() const;
bool isPackagingNeeded() const;
const Qt4ProjectManager::Qt4BuildConfiguration *m_lastBuildConfig;
};
......@@ -152,34 +141,11 @@ private:
MaemoRpmPackageCreationStep *other);
void ctor();
static QString rpmBuildDir(const Qt4ProjectManager::Qt4BuildConfiguration *bc);
QString rpmBuildDir() const;
static const QString CreatePackageId;
};
class MaemoTarPackageCreationStep : public AbstractMaemoPackageCreationStep
{
Q_OBJECT
public:
MaemoTarPackageCreationStep(ProjectExplorer::BuildStepList *bsl);
MaemoTarPackageCreationStep(ProjectExplorer::BuildStepList *buildConfig,
MaemoTarPackageCreationStep *other);
virtual QString packageFilePath() const;
static const QString CreatePackageId;
private:
virtual bool createPackage(QProcess *buildProc, const QFutureInterface<bool> &fi);
virtual bool isMetaDataNewerThan(const QDateTime &packageDate) const;
virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
void ctor();
bool appendFile(QFile &tarFile, const QFileInfo &fileInfo,
const QString &remoteFilePath, const QFutureInterface<bool> &fi);
bool writeHeader(QFile &tarFile, const QFileInfo &fileInfo,
const QString &remoteFilePath);
};
} // namespace Internal
} // namespace RemoteLinux
......
......@@ -89,7 +89,9 @@ HEADERS += \
genericdirectuploadservice.h \
remotelinuxdeployconfiguration.h \
remotelinuxdeployconfigurationfactory.h \
genericremotelinuxdeploystepfactory.h
genericremotelinuxdeploystepfactory.h \
abstractpackagingstep.h \
tarpackagecreationstep.h
SOURCES += \
remotelinuxplugin.cpp \
......@@ -172,7 +174,9 @@ SOURCES += \
genericdirectuploadservice.cpp \
remotelinuxdeployconfiguration.cpp \
remotelinuxdeployconfigurationfactory.cpp \
genericremotelinuxdeploystepfactory.cpp
genericremotelinuxdeploystepfactory.cpp \
abstractpackagingstep.cpp \
tarpackagecreationstep.cpp
FORMS += \
maemoconfigtestdialog.ui \
......
......@@ -33,8 +33,8 @@
#include "linuxdeviceconfiguration.h"
#include "maemoglobal.h"
#include "maemopackagecreationstep.h"
#include "remotelinuxdeployconfiguration.h"
#include "tarpackagecreationstep.h"
#include "uploadandinstalltarpackagestep.h"
using namespace ProjectExplorer;
......@@ -78,7 +78,7 @@ DeployConfiguration *RemoteLinuxDeployConfigurationFactory::create(Target *paren
DeployConfiguration * const dc = new RemoteLinuxDeployConfiguration(parent, id,
genericLinuxDisplayName(), LinuxDeviceConfiguration::GenericLinuxOsType);
dc->stepList()->insertStep(0, new MaemoTarPackageCreationStep(dc->stepList()));
dc->stepList()->insertStep(0, new TarPackageCreationStep(dc->stepList()));
dc->stepList()->insertStep(1, new UploadAndInstallTarPackageStep(dc->stepList()));
return dc;
}
......
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.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 info@qt.nokia.com.
**
**************************************************************************/
#include "tarpackagecreationstep.h"
#include "deployablefile.h"
#include "deploymentinfo.h"
#include "remotelinuxdeployconfiguration.h"
#include <projectexplorer/project.h>
#include <projectexplorer/target.h>
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
using namespace ProjectExplorer;
namespace RemoteLinux {
namespace {
class CreateTarStepWidget : public BuildStepConfigWidget
{
Q_OBJECT
public:
CreateTarStepWidget(TarPackageCreationStep *step) : m_step(step)
{
connect(m_step, SIGNAL(packageFilePathChanged()), SIGNAL(updateSummary()));
}
QString summaryText() const
{
if (m_step->packageFilePath().isEmpty()) {
return QLatin1String("<font color=\"red\">")
+ tr("Tarball creation not possible.") + QLatin1String("</font>");
}
return QLatin1String("<b>") + tr("Create tarball:") + QLatin1String("</b> ")
+ m_step->packageFilePath();
}
QString displayName() const { return QString(); }
private:
const TarPackageCreationStep * const m_step;
};
const int TarBlockSize = 512;
struct TarFileHeader {
char fileName[100];
char fileMode[8];
char uid[8];
char gid[8];
char length[12];
char mtime[12];
char chksum[8];
char typeflag;
char linkname[100];
char magic[6];
char version[2];
char uname[32];
char gname[32];
char devmajor[8];
char devminor[8];
char fileNamePrefix[155];
char padding[12];
};
} // Anonymous namespace.
TarPackageCreationStep::TarPackageCreationStep(BuildStepList *bsl)
: AbstractPackagingStep(bsl, stepId())
{
ctor();
}
TarPackageCreationStep::TarPackageCreationStep(BuildStepList *bsl, TarPackageCreationStep *other)
: AbstractPackagingStep(bsl, other)
{
ctor();
}
void TarPackageCreationStep::ctor()
{
setDefaultDisplayName(displayName());
}
void TarPackageCreationStep::run(QFutureInterface<bool> &fi)
{
setPackagingStarted();
const bool success = doPackage(fi);
setPackagingFinished(success);
if (success)
emit addOutput(tr("Packaging finished successfully."), MessageOutput);
else
emit addOutput(tr("Packaging failed."), ErrorMessageOutput);
fi.reportResult(success);
}
bool TarPackageCreationStep::doPackage(QFutureInterface<bool> &fi)
{
emit addOutput(tr("Creating tarball..."), MessageOutput);
if (!isPackagingNeeded()) {
emit addOutput(tr("Tarball up to date, skipping packaging."), MessageOutput);