Commit 487b56b0 authored by Daniel Teske's avatar Daniel Teske
Browse files

Make AbstractPackagingStep and derived classes thread safe



Change-Id: I30d412dde2484b756dd2f06ed0a7b5030c14c9eb
Reviewed-by: default avatarChristian Kandeler <christian.kandeler@nokia.com>
parent 2c2a8a78
......@@ -77,9 +77,38 @@ AbstractMaemoPackageCreationStep::~AbstractMaemoPackageCreationStep()
{
}
bool AbstractMaemoPackageCreationStep::init()
{
if (!AbstractPackagingStep::init())
return false;
m_packagingNeeded = isPackagingNeeded();
if (!isPackagingNeeded())
return true;
if (!qt4BuildConfiguration()) {
raiseError(tr("No Qt4 build configuration"));
return false;
}
m_environment = qt4BuildConfiguration()->environment();
if (qt4BuildConfiguration()->qmakeBuildConfiguration() & QtSupport::BaseQtVersion::DebugBuild) {
m_environment.appendOrSet(QLatin1String("DEB_BUILD_OPTIONS"),
QLatin1String("nostrip"), QLatin1String(" "));
}
if (!qt4BuildConfiguration()->qtVersion()) {
raiseError(tr("Packaging failed: No Qt version."));
return false;
}
m_qmakeCommand = qt4BuildConfiguration()->qtVersion()->qmakeCommand();
return true;
}
void AbstractMaemoPackageCreationStep::run(QFutureInterface<bool> &fi)
{
if (!isPackagingNeeded()) {
if (!m_packagingNeeded) {
emit addOutput(tr("Package up to date."), MessageOutput);
fi.reportResult(true);
return;
......@@ -145,12 +174,6 @@ AbstractRpmBasedQt4MaemoTarget *AbstractMaemoPackageCreationStep::rpmBasedMaemoT
return qobject_cast<AbstractRpmBasedQt4MaemoTarget*>(buildConfiguration()->target());
}
QString AbstractMaemoPackageCreationStep::projectName() const
{
return qt4BuildConfiguration()->qt4Target()->qt4Project()
->rootProjectNode()->displayName().toLower();
}
bool AbstractMaemoPackageCreationStep::isPackagingNeeded() const
{
if (AbstractPackagingStep::isPackagingNeeded())
......@@ -190,18 +213,15 @@ QString AbstractMaemoPackageCreationStep::nativePath(const QFile &file)
bool AbstractMaemoPackageCreationStep::callPackagingCommand(QProcess *proc,
const QStringList &arguments)
{
preparePackagingProcess(proc, qt4BuildConfiguration(), packageDirectory());
const QtSupport::BaseQtVersion * const qtVersion = qt4BuildConfiguration()->qtVersion();
if (!qtVersion) {
raiseError(tr("Packaging failed: No Qt version."));
return false;
}
const QString madCommand = MaemoGlobal::madCommand(qtVersion->qmakeCommand());
proc->setEnvironment(m_environment.toStringList());
proc->setWorkingDirectory(cachedPackageDirectory());
const QString madCommand = MaemoGlobal::madCommand(m_qmakeCommand);
const QString cmdLine = madCommand + QLatin1Char(' ')
+ arguments.join(QLatin1String(" "));
emit addOutput(tr("Package Creation: Running command '%1'.").arg(cmdLine),
BuildStep::MessageOutput);
MaemoGlobal::callMad(*proc, arguments, qtVersion->qmakeCommand(), true);
MaemoGlobal::callMad(*proc, arguments, m_qmakeCommand, true);
if (!proc->waitForStarted()) {
raiseError(tr("Packaging failed: Could not start command '%1'. Reason: %2")
.arg(cmdLine, proc->errorString()));
......@@ -221,7 +241,6 @@ bool AbstractMaemoPackageCreationStep::callPackagingCommand(QProcess *proc,
return true;
}
void AbstractMaemoPackageCreationStep::preparePackagingProcess(QProcess *proc,
const Qt4BuildConfiguration *bc, const QString &workingDir)
{
......@@ -244,6 +263,9 @@ QString AbstractMaemoPackageCreationStep::replaceDots(const QString &name) const
return name;
}
////////////////
// MaemoDebianPackageCreationStep
////////////////
MaemoDebianPackageCreationStep::MaemoDebianPackageCreationStep(BuildStepList *bsl)
: AbstractMaemoPackageCreationStep(bsl, CreatePackageId)
......@@ -266,13 +288,25 @@ void MaemoDebianPackageCreationStep::ctor()
setDefaultDisplayName(tr("Create Debian Package"));
}
bool MaemoDebianPackageCreationStep::init()
{
if (!AbstractMaemoPackageCreationStep::init())
return false;
m_maddeRoot = MaemoGlobal::maddeRoot(qt4BuildConfiguration()->qtVersion()->qmakeCommand());
m_projectDirectory = buildConfiguration()->target()->project()->projectDirectory();
m_pkgFileName = maemoTarget()->packageFileName();
m_packageName = maemoTarget()->packageName();
m_templatesDirPath = debBasedMaemoTarget()->debianDirPath();
m_debugBuild = qt4BuildConfiguration()->qmakeBuildConfiguration() & QtSupport::BaseQtVersion::DebugBuild;
checkProjectName();
return true;
}
bool MaemoDebianPackageCreationStep::createPackage(QProcess *buildProc,
const QFutureInterface<bool> &fi)
{
Q_UNUSED(fi);
checkProjectName();
const QString projectDir = buildConfiguration()->target()->project()->projectDirectory();
const bool inSourceBuild = QFileInfo(packageDirectory()) == QFileInfo(projectDir);
const bool inSourceBuild = QFileInfo(cachedPackageDirectory()) == QFileInfo(m_projectDirectory);
if (!copyDebianFiles(inSourceBuild))
return false;
const QStringList args = QStringList() << QLatin1String("dpkg-buildpackage")
......@@ -280,35 +314,33 @@ bool MaemoDebianPackageCreationStep::createPackage(QProcess *buildProc,
if (!callPackagingCommand(buildProc, args))
return false;
QFile::remove(packageFilePath());
QFile::remove(cachedPackageFilePath());
// Workaround for non-working dh_builddeb --destdir=.
if (!QDir(packageDirectory()).isRoot()) {
const AbstractQt4MaemoTarget * const target = maemoTarget();
if (!QDir(cachedPackageDirectory()).isRoot()) {
QString error;
const QString pkgFileName = target->packageFileName();
if (!error.isEmpty())
raiseError(tr("Packaging failed: Could not get package name."));
const QString changesSourceFileName = QFileInfo(pkgFileName).completeBaseName()
const QString changesSourceFileName = QFileInfo(m_pkgFileName).completeBaseName()
+ QLatin1String(".changes");
const QString changesTargetFileName = replaceDots(QFileInfo(pkgFileName).completeBaseName())
const QString changesTargetFileName = replaceDots(QFileInfo(m_pkgFileName).completeBaseName())
+ QLatin1String(".changes");
const QString packageSourceDir = packageDirectory() + QLatin1String("/../");
const QString packageSourceFilePath = packageSourceDir + pkgFileName;
const QString packageSourceDir = cachedPackageDirectory() + QLatin1String("/../");
const QString packageSourceFilePath = packageSourceDir + m_pkgFileName;
const QString changesSourceFilePath = packageSourceDir + changesSourceFileName;
const QString changesTargetFilePath
= packageDirectory() + QLatin1Char('/') + changesTargetFileName;
= cachedPackageDirectory() + QLatin1Char('/') + changesTargetFileName;
QFile::remove(changesTargetFilePath);
if (!QFile::rename(packageSourceFilePath, packageFilePath())
if (!QFile::rename(packageSourceFilePath, cachedPackageFilePath())
|| !QFile::rename(changesSourceFilePath, changesTargetFilePath)) {
raiseError(tr("Packaging failed: Could not move package files from '%1' to '%2'.")
.arg(packageSourceDir, packageDirectory()));
.arg(packageSourceDir, cachedPackageDirectory()));
return false;
}
}
if (inSourceBuild) {
buildProc->start(packagingCommand(qt4BuildConfiguration(), QLatin1String("dh_clean")));
buildProc->start(packagingCommand(m_maddeRoot, QLatin1String("dh_clean")));
buildProc->waitForFinished();
buildProc->terminate();
}
......@@ -344,7 +376,7 @@ void MaemoDebianPackageCreationStep::checkProjectName()
bool MaemoDebianPackageCreationStep::copyDebianFiles(bool inSourceBuild)
{
const QString debianDirPath = packageDirectory() + QLatin1String("/debian");
const QString debianDirPath = cachedPackageDirectory() + QLatin1String("/debian");
const QString magicFilePath
= debianDirPath + QLatin1Char('/') + MagicFileName;
if (inSourceBuild && QFileInfo(debianDirPath).isDir()
......@@ -362,16 +394,15 @@ bool MaemoDebianPackageCreationStep::copyDebianFiles(bool inSourceBuild)
.arg(debianDirPath, error));
return false;
}
QDir buildDir(packageDirectory());
QDir buildDir(cachedPackageDirectory());
if (!buildDir.mkdir("debian")) {
raiseError(tr("Could not create Debian directory '%1'.").arg(debianDirPath));
return false;
}
const QString templatesDirPath = debBasedMaemoTarget()->debianDirPath();
QDir templatesDir(templatesDirPath);
QDir templatesDir(m_templatesDirPath);
const QStringList &files = templatesDir.entryList(QDir::Files);
foreach (const QString &fileName, files) {
const QString srcFile = templatesDirPath + QLatin1Char('/') + fileName;
const QString srcFile = m_templatesDirPath + QLatin1Char('/') + fileName;
QString newFileName = fileName;
if (newFileName == Qt4HarmattanTarget::aegisManifestFileName()) {
// If the user has touched the Aegis manifest file, we copy it for use
......@@ -379,7 +410,7 @@ bool MaemoDebianPackageCreationStep::copyDebianFiles(bool inSourceBuild)
// unless the user explicitly requests that no manifest should be created.
if (QFileInfo(srcFile).size() == 0)
continue;
newFileName = maemoTarget()->packageName() + QLatin1String(".aegis");
newFileName = m_packageName + QLatin1String(".aegis");
}
const QString destFile = debianDirPath + QLatin1Char('/') + newFileName;
......@@ -424,12 +455,9 @@ bool MaemoDebianPackageCreationStep::copyDebianFiles(bool inSourceBuild)
return true;
}
QString MaemoDebianPackageCreationStep::packagingCommand(const Qt4BuildConfiguration *bc,
const QString &commandName)
QString MaemoDebianPackageCreationStep::packagingCommand(const QString &maddeRoot, const QString &commandName)
{
QString perl;
QtSupport::BaseQtVersion *v = bc->qtVersion();
const QString maddeRoot = MaemoGlobal::maddeRoot(v->qmakeCommand());
#ifdef Q_OS_WIN
perl = maddeRoot + QLatin1String("/bin/perl.exe ");
#endif
......@@ -457,10 +485,8 @@ bool MaemoDebianPackageCreationStep::adaptRulesFile(
return false;
}
QByteArray content = reader.data();
const Qt4BuildConfiguration * const bc = qt4BuildConfiguration();
// Always check for dependencies in release builds.
if (!(bc->qmakeBuildConfiguration() & QtSupport::BaseQtVersion::DebugBuild))
if (!m_debugBuild)
ensureShlibdeps(content);
Utils::FileSaver saver(rulesFilePath);
......@@ -474,6 +500,9 @@ bool MaemoDebianPackageCreationStep::adaptRulesFile(
return true;
}
/////////////////
// MaemoRpmPackageCreationStep
/////////////////
MaemoRpmPackageCreationStep::MaemoRpmPackageCreationStep(BuildStepList *bsl)
: AbstractMaemoPackageCreationStep(bsl, CreatePackageId)
......@@ -493,22 +522,27 @@ void MaemoRpmPackageCreationStep::ctor()
setDefaultDisplayName(tr("Create RPM Package"));
}
bool MaemoRpmPackageCreationStep::init()
{
m_specFile = rpmBasedMaemoTarget()->specFilePath();
m_packageFileName = rpmBasedMaemoTarget()->packageFileName();
return AbstractMaemoPackageCreationStep::init();
}
bool MaemoRpmPackageCreationStep::createPackage(QProcess *buildProc,
const QFutureInterface<bool> &fi)
{
setPackagingStarted();
Q_UNUSED(fi);
const QStringList args = QStringList() << QLatin1String("rrpmbuild")
<< QLatin1String("-bb") << rpmBasedMaemoTarget()->specFilePath();
<< QLatin1String("-bb") << m_specFile;
if (!callPackagingCommand(buildProc, args))
return false;
QFile::remove(packageFilePath());
QFile::remove(cachedPackageFilePath());
const QString packageSourceFilePath = rpmBuildDir() + QLatin1Char('/')
+ rpmBasedMaemoTarget()->packageFileName();
if (!QFile::rename(packageSourceFilePath, packageFilePath())) {
+ m_packageFileName;
if (!QFile::rename(packageSourceFilePath, cachedPackageFilePath())) {
raiseError(tr("Packaging failed: Could not move package file from %1 to %2.")
.arg(packageSourceFilePath, packageFilePath()));
.arg(packageSourceFilePath, cachedPackageFilePath()));
return false;
}
......@@ -524,7 +558,7 @@ bool MaemoRpmPackageCreationStep::isMetaDataNewerThan(const QDateTime &packageDa
QString MaemoRpmPackageCreationStep::rpmBuildDir() const
{
return packageDirectory() + QLatin1String("/rrpmbuild");
return cachedPackageDirectory() + QLatin1String("/rrpmbuild");
}
const QString MaemoRpmPackageCreationStep::CreatePackageId
......
......@@ -32,7 +32,8 @@
#ifndef MAEMOPACKAGECREATIONSTEP_H
#define MAEMOPACKAGECREATIONSTEP_H
#include<remotelinux/abstractpackagingstep.h>
#include <remotelinux/abstractpackagingstep.h>
#include <utils/environment.h>
QT_BEGIN_NAMESPACE
class QDateTime;
......@@ -81,6 +82,7 @@ protected:
bool callPackagingCommand(QProcess *proc, const QStringList &arguments);
QString replaceDots(const QString &name) const;
virtual bool init();
private slots:
void handleBuildOutput();
......@@ -94,11 +96,13 @@ private:
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 isPackagingNeeded() const;
const Qt4ProjectManager::Qt4BuildConfiguration *m_lastBuildConfig;
bool m_packagingNeeded;
Utils::Environment m_environment;
QString m_qmakeCommand;
};
......@@ -115,16 +119,23 @@ private:
MaemoDebianPackageCreationStep(ProjectExplorer::BuildStepList *buildConfig,
MaemoDebianPackageCreationStep *other);
virtual bool init();
virtual bool createPackage(QProcess *buildProc, const QFutureInterface<bool> &fi);
virtual bool isMetaDataNewerThan(const QDateTime &packageDate) const;
void ctor();
static QString packagingCommand(const Qt4ProjectManager::Qt4BuildConfiguration *bc,
const QString &commandName);
static QString packagingCommand(const QString &maddeRoot, const QString &commandName);
bool copyDebianFiles(bool inSourceBuild);
void checkProjectName();
bool adaptRulesFile(const QString &templatePath, const QString &rulesFilePath);
QString m_maddeRoot;
QString m_projectDirectory;
QString m_pkgFileName;
QString m_packageName;
QString m_templatesDirPath;
bool m_debugBuild;
static const QString CreatePackageId;
};
......@@ -136,6 +147,7 @@ public:
MaemoRpmPackageCreationStep(ProjectExplorer::BuildStepList *bsl);
private:
bool init();
virtual bool createPackage(QProcess *buildProc, const QFutureInterface<bool> &fi);
virtual bool isMetaDataNewerThan(const QDateTime &packageDate) const;
......@@ -145,6 +157,9 @@ private:
void ctor();
QString rpmBuildDir() const;
QString m_specFile;
QString m_packageFileName;
static const QString CreatePackageId;
};
......
......@@ -51,10 +51,10 @@ namespace Internal {
class AbstractPackagingStepPrivate
{
public:
AbstractPackagingStepPrivate() : currentBuildConfiguration(0), running(false) { }
AbstractPackagingStepPrivate() : currentBuildConfiguration(0) { }
BuildConfiguration *currentBuildConfiguration;
bool running;
QString cachedPackageFilePath;
QString cachedPackageDirectory;
};
......@@ -78,6 +78,9 @@ void AbstractPackagingStep::ctor()
connect(target(), SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
SLOT(handleBuildConfigurationChanged()));
handleBuildConfigurationChanged();
connect(this, SIGNAL(unmodifyDeploymentInfo()),
this, SLOT(setDeploymentInfoUnmodified()));
}
AbstractPackagingStep::~AbstractPackagingStep()
......@@ -97,6 +100,11 @@ void AbstractPackagingStep::handleBuildConfigurationChanged()
emit packageFilePathChanged();
}
QString AbstractPackagingStep::cachedPackageFilePath() const
{
return d->cachedPackageFilePath;
}
QString AbstractPackagingStep::packageFilePath() const
{
if (packageDirectory().isEmpty())
......@@ -104,10 +112,13 @@ QString AbstractPackagingStep::packageFilePath() const
return packageDirectory() + QLatin1Char('/') + packageFileName();
}
QString AbstractPackagingStep::cachedPackageDirectory() const
{
return d->cachedPackageDirectory;
}
QString AbstractPackagingStep::packageDirectory() const
{
if (d->running)
return d->cachedPackageDirectory;
return d->currentBuildConfiguration
? d->currentBuildConfiguration->buildDirectory() : QString();
}
......@@ -137,19 +148,25 @@ bool AbstractPackagingStep::isPackagingNeeded() const
bool AbstractPackagingStep::init()
{
d->cachedPackageDirectory = packageDirectory();
d->cachedPackageFilePath = packageFilePath();
return true;
}
void AbstractPackagingStep::setPackagingStarted()
{
d->running = true;
}
// called in ::run thread
void AbstractPackagingStep::setPackagingFinished(bool success)
{
d->running = false;
if (success)
deployConfiguration()->deploymentInfo()->setUnmodified();
emit unmodifyDeploymentInfo();
}
// called in gui thread
void AbstractPackagingStep::setDeploymentInfoUnmodified()
{
deployConfiguration()->deploymentInfo()->setUnmodified();
}
void AbstractPackagingStep::raiseError(const QString &errorMessage)
......
......@@ -36,7 +36,8 @@
#include <projectexplorer/buildstep.h>
namespace RemoteLinux {
class RemoteLinuxDeployConfiguration;
class RemoteLinuxDeployConfiguration;
class DeploymentInfo;
namespace Internal {
class AbstractPackagingStepPrivate;
......@@ -52,10 +53,12 @@ public:
~AbstractPackagingStep();
QString packageFilePath() const;
QString cachedPackageFilePath() const;
bool init();
signals:
void packageFilePathChanged();
void unmodifyDeploymentInfo();
protected:
void setPackagingStarted();
......@@ -63,12 +66,14 @@ protected:
void raiseError(const QString &errorMessage);
RemoteLinuxDeployConfiguration *deployConfiguration() const;
QString cachedPackageDirectory() const;
QString packageDirectory() const;
virtual bool isPackagingNeeded() const;
private slots:
void handleBuildConfigurationChanged();
void setDeploymentInfoUnmodified();
private:
virtual QString packageFileName() const = 0;
......
......@@ -114,6 +114,22 @@ void TarPackageCreationStep::ctor()
setDefaultDisplayName(displayName());
}
bool TarPackageCreationStep::init()
{
if (!AbstractPackagingStep::init())
return false;
m_packagingNeeded = isPackagingNeeded();
if (!m_packagingNeeded)
return true;
const QSharedPointer<DeploymentInfo> deploymentInfo = deployConfiguration()->deploymentInfo();
for (int i = 0; i < deploymentInfo->deployableCount(); ++i) {
m_files.append(deploymentInfo->deployableAt(i));
}
return true;
}
void TarPackageCreationStep::run(QFutureInterface<bool> &fi)
{
setPackagingStarted();
......@@ -129,23 +145,21 @@ void TarPackageCreationStep::run(QFutureInterface<bool> &fi)
bool TarPackageCreationStep::doPackage(QFutureInterface<bool> &fi)
{
emit addOutput(tr("Creating tarball..."), MessageOutput);
if (!isPackagingNeeded()) {
if (!m_packagingNeeded) {
emit addOutput(tr("Tarball up to date, skipping packaging."), MessageOutput);
return true;
}
// TODO: Optimization: Only package changed files
QFile tarFile(packageFilePath());
QFile tarFile(cachedPackageFilePath());
if (!tarFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
raiseError(tr("Error: tar file %1 cannot be opened (%2).")
.arg(QDir::toNativeSeparators(packageFilePath()), tarFile.errorString()));
.arg(QDir::toNativeSeparators(cachedPackageFilePath()), tarFile.errorString()));
return false;
}
const QSharedPointer<DeploymentInfo> deploymentInfo = deployConfiguration()->deploymentInfo();
for (int i = 0; i < deploymentInfo->deployableCount(); ++i) {
const DeployableFile &d = deploymentInfo->deployableAt(i);
foreach (const DeployableFile &d, m_files) {
QFileInfo fileInfo(d.localFilePath);
if (!appendFile(tarFile, fileInfo, d.remoteDir + QLatin1Char('/')
+ fileInfo.fileName(), fi)) {
......@@ -275,7 +289,7 @@ bool TarPackageCreationStep::writeHeader(QFile &tarFile, const QFileInfo &fileIn
header.chksum[sizeof header.chksum-1] = 0;
if (!tarFile.write(reinterpret_cast<char *>(&header), sizeof header)) {
raiseError(tr("Error writing tar file '%1': %2")
.arg(QDir::toNativeSeparators(packageFilePath()), tarFile.errorString()));
.arg(QDir::toNativeSeparators(cachedPackageFilePath()), tarFile.errorString()));
return false;
}
return true;
......
......@@ -33,6 +33,7 @@
#include "abstractpackagingstep.h"
#include "remotelinux_export.h"
#include "deployablefile.h"
QT_BEGIN_NAMESPACE
class QFile;
......@@ -51,6 +52,7 @@ public:
static QString stepId();
static QString displayName();
bool init();
void run(QFutureInterface<bool> &fi);
private:
ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
......@@ -63,6 +65,9 @@ private:
const QString &remoteFilePath, const QFutureInterface<bool> &fi);
bool writeHeader(QFile &tarFile, const QFileInfo &fileInfo,
const QString &remoteFilePath);
bool m_packagingNeeded;
QList<DeployableFile> m_files;
};
} // namespace RemoteLinux
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment