From 1bcdb33fb1d2eb8756b8d08cdd6167a8f19e053d Mon Sep 17 00:00:00 2001 From: ck <qt-info@nokia.com> Date: Tue, 3 Aug 2010 16:27:34 +0200 Subject: [PATCH] Maemo: Create packaging templates in project directory. Reviewed-by: kh1 --- .../qt-maemo/maemomanager.cpp | 2 + .../qt-maemo/maemopackagecreationstep.cpp | 273 ++++++++++-------- .../qt-maemo/maemopackagecreationstep.h | 17 +- .../qt-maemo/maemopackagecreationwidget.cpp | 34 ++- .../qt-maemo/maemopackagecreationwidget.h | 1 + .../qt-maemo/maemotemplatesmanager.cpp | 248 ++++++++++++++++ .../qt-maemo/maemotemplatesmanager.h | 72 +++++ .../qt4projectmanager/qt-maemo/qt-maemo.pri | 6 +- 8 files changed, 524 insertions(+), 129 deletions(-) create mode 100644 src/plugins/qt4projectmanager/qt-maemo/maemotemplatesmanager.cpp create mode 100644 src/plugins/qt4projectmanager/qt-maemo/maemotemplatesmanager.h diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemomanager.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemomanager.cpp index b47b096a0d3..8d0a941c0f2 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemomanager.cpp +++ b/src/plugins/qt4projectmanager/qt-maemo/maemomanager.cpp @@ -36,6 +36,7 @@ #include "maemoqemumanager.h" #include "maemorunfactories.h" #include "maemosettingspage.h" +#include "maemotemplatesmanager.h" #include "maemotoolchain.h" #include <extensionsystem/pluginmanager.h> @@ -66,6 +67,7 @@ MaemoManager::MaemoManager() m_instance = this; MaemoQemuManager::instance(this); MaemoDeviceConfigurations::instance(this); + MaemoTemplatesManager::instance(this); PluginManager *pluginManager = PluginManager::instance(); pluginManager->addObject(m_runControlFactory); diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.cpp index 6769d6de2f1..54aa6fa1fe5 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.cpp +++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.cpp @@ -47,6 +47,7 @@ #include "maemoglobal.h" #include "maemopackagecreationwidget.h" #include "maemoprofilewrapper.h" +#include "maemotemplatesmanager.h" #include "maemotoolchain.h" #include <projectexplorer/buildsteplist.h> @@ -62,8 +63,6 @@ namespace { const QLatin1String PackagingEnabledKey("Packaging Enabled"); - const QLatin1String DefaultVersionNumber("0.0.1"); - const QLatin1String VersionNumberKey("Version Number"); } using namespace ProjectExplorer::Constants; @@ -74,10 +73,11 @@ using ProjectExplorer::Task; namespace Qt4ProjectManager { namespace Internal { +const QLatin1String MaemoPackageCreationStep::DefaultVersionNumber("0.0.1"); + MaemoPackageCreationStep::MaemoPackageCreationStep(BuildStepList *bsl) : ProjectExplorer::BuildStep(bsl, CreatePackageId), - m_packagingEnabled(true), - m_versionString(DefaultVersionNumber) + m_packagingEnabled(true) { ctor(); } @@ -85,8 +85,7 @@ MaemoPackageCreationStep::MaemoPackageCreationStep(BuildStepList *bsl) MaemoPackageCreationStep::MaemoPackageCreationStep(BuildStepList *bsl, MaemoPackageCreationStep *other) : BuildStep(bsl, other), - m_packagingEnabled(other->m_packagingEnabled), - m_versionString(other->m_versionString) + m_packagingEnabled(other->m_packagingEnabled) { ctor(); } @@ -110,14 +109,12 @@ QVariantMap MaemoPackageCreationStep::toMap() const { QVariantMap map(ProjectExplorer::BuildStep::toMap()); map.insert(PackagingEnabledKey, m_packagingEnabled); - map.insert(VersionNumberKey, m_versionString); return map; } bool MaemoPackageCreationStep::fromMap(const QVariantMap &map) { m_packagingEnabled = map.value(PackagingEnabledKey, true).toBool(); - m_versionString = map.value(VersionNumberKey, DefaultVersionNumber).toString(); return ProjectExplorer::BuildStep::fromMap(map); } @@ -137,99 +134,47 @@ bool MaemoPackageCreationStep::createPackage() return true; emit addOutput(tr("Creating package file ..."), BuildStep::MessageOutput); - QFile configFile(targetRoot() % QLatin1String("/config.sh")); - if (!configFile.open(QIODevice::ReadOnly)) { - raiseError(tr("Cannot open MADDE config file '%1'.") - .arg(nativePath(configFile))); + m_buildProc.reset(new QProcess); + QString error; + if (!preparePackagingProcess(m_buildProc.data(), maemoToolChain(), + buildDirectory(), &error)) { + raiseError(error); return false; } - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - const QString &path = QDir::toNativeSeparators(maddeRoot() + QLatin1Char('/')); - - const QLatin1String key("PATH"); - QString colon = QLatin1String(":"); -#ifdef Q_OS_WIN - colon = QLatin1String(";"); - env.insert(key, path % QLatin1String("bin") % colon % env.value(key)); -#endif - - env.insert(key, targetRoot() % "/bin" % colon % env.value(key)); - env.insert(key, path % QLatin1String("madbin") % colon % env.value(key)); - - QString perlLib = QDir::fromNativeSeparators(path % QLatin1String("madlib/perl5")); -#ifdef Q_OS_WIN - perlLib = perlLib.remove(QLatin1Char(':')); - perlLib = perlLib.prepend(QLatin1Char('/')); -#endif - env.insert(QLatin1String("PERL5LIB"), perlLib); - - const QString buildDir = buildDirectory(); - env.insert(QLatin1String("PWD"), buildDir); - - const QRegExp envPattern(QLatin1String("([^=]+)=[\"']?([^;\"']+)[\"']? ;.*")); - QByteArray line; - do { - line = configFile.readLine(200); - if (envPattern.exactMatch(line)) - env.insert(envPattern.cap(1), envPattern.cap(2)); - } while (!line.isEmpty()); - - - m_buildProc.reset(new QProcess); connect(m_buildProc.data(), SIGNAL(readyReadStandardOutput()), this, SLOT(handleBuildOutput())); connect(m_buildProc.data(), SIGNAL(readyReadStandardError()), this, SLOT(handleBuildOutput())); - m_buildProc->setProcessEnvironment(env); - m_buildProc->setWorkingDirectory(buildDir); - m_buildProc->start("cd " + buildDir); - m_buildProc->waitForFinished(); - - // cache those two since we can change the version number during packaging - // and might fail later to modify, copy, remove etc. the generated package - const QString version = versionString(); - const QString pkgFilePath = packageFilePath(); - - if (!QFileInfo(buildDir + QLatin1String("/debian")).exists()) { - const QString command = QLatin1String("dh_make -s -n -p ") - % projectName() % QLatin1Char('_') % versionString(); - if (!runCommand(command)) - return false; - QFile rulesFile(buildDir + QLatin1String("/debian/rules")); - if (!rulesFile.open(QIODevice::ReadWrite)) { - raiseError(tr("Packaging Error: Cannot open file '%1'.") - .arg(nativePath(rulesFile))); - return false; - } - - QByteArray rulesContents = rulesFile.readAll(); - rulesContents.replace("DESTDIR", "INSTALL_ROOT"); - rulesContents.replace("dh_shlibdeps", "# dh_shlibdeps"); - - // Would be the right solution, but does not work (on Windows), - // because dpkg-genchanges doesn't know about it (and can't be told). - // rulesContents.replace("dh_builddeb", "dh_builddeb --destdir=."); - - rulesFile.resize(0); - rulesFile.write(rulesContents); - if (rulesFile.error() != QFile::NoError) { - raiseError(tr("Packaging Error: Cannot write file '%1'.") - .arg(nativePath(rulesFile))); - return false; - } + const QString debianDirPath = buildDirectory() + QLatin1String("/debian"); + if (!removeDirectory(debianDirPath)) { + raiseError(tr("Packaging failed."), + tr("Could not remove directory '%1'.").arg(debianDirPath)); + return false; } - - { - QFile::remove(buildDir + QLatin1String("/debian/files")); - QFile changeLog(buildDir + QLatin1String("/debian/changelog")); - if (changeLog.open(QIODevice::ReadWrite)) { - QString content = QString::fromUtf8(changeLog.readAll()); - content.replace(QRegExp("\\([a-zA-Z0-9_\\.]+\\)"), - QLatin1Char('(') % version % QLatin1Char(')')); - changeLog.resize(0); - changeLog.write(content.toUtf8()); + QDir buildDir(buildDirectory()); + if (!buildDir.mkdir("debian")) { + raiseError(tr("Could not create debian directory '%1'.") + .arg(debianDirPath)); + return false; + } + const QString templatesDirPath + = buildConfiguration()->target()->project()->projectDirectory() + + QLatin1Char('/') + MaemoTemplatesManager::PackagingDirName + + QLatin1String("/debian"); + QDir templatesDir(templatesDirPath); + const QStringList &files = templatesDir.entryList(QDir::Files); + foreach (const QString &fileName, files) { + const QString srcFile + = templatesDirPath + QLatin1Char('/') + fileName; + const QString destFile + = debianDirPath + QLatin1Char('/') + fileName; + if (!QFile::copy(srcFile, destFile)) { + raiseError(tr("Could not copy file '%1' to '%2'") + .arg(QDir::toNativeSeparators(srcFile), + QDir::toNativeSeparators(destFile))); + return false; } } @@ -237,24 +182,30 @@ bool MaemoPackageCreationStep::createPackage() return false; // Workaround for non-working dh_builddeb --destdir=. - if (!QDir(buildDir).isRoot()) { - const QString packageFileName = QFileInfo(pkgFilePath).fileName(); - const QString changesFileName = QFileInfo(packageFileName) + if (!QDir(buildDirectory()).isRoot()) { + const ProjectExplorer::Project * const project + = buildConfiguration()->target()->project(); + QString error; + const QString pkgFileName = packageFileName(project, + MaemoTemplatesManager::instance()->version(project, &error)); + if (!error.isEmpty()) + raiseError(tr("Packaging failed."), error); + const QString changesFileName = QFileInfo(pkgFileName) .completeBaseName() + QLatin1String(".changes"); - const QString packageSourceDir = buildDir + QLatin1String("/../"); + const QString packageSourceDir = buildDirectory() + QLatin1String("/../"); const QString packageSourceFilePath - = packageSourceDir + packageFileName; + = packageSourceDir + pkgFileName; const QString changesSourceFilePath = packageSourceDir + changesFileName; const QString changesTargetFilePath - = buildDir + QLatin1Char('/') + changesFileName; - QFile::remove(pkgFilePath); + = buildDirectory() + QLatin1Char('/') + changesFileName; + QFile::remove(packageFilePath()); QFile::remove(changesTargetFilePath); - if (!QFile::rename(packageSourceFilePath, pkgFilePath) + if (!QFile::rename(packageSourceFilePath, packageFilePath()) || !QFile::rename(changesSourceFilePath, changesTargetFilePath)) { raiseError(tr("Packaging failed."), tr("Could not move package files from %1 to %2.") - .arg(packageSourceDir, buildDir)); + .arg(packageSourceDir, buildDirectory())); return false; } } @@ -264,21 +215,38 @@ bool MaemoPackageCreationStep::createPackage() return true; } +bool MaemoPackageCreationStep::removeDirectory(const QString &dirPath) +{ + QDir dir(dirPath); + if (!dir.exists()) + return true; + + const QStringList &files = dir.entryList(QDir::Files); + foreach (const QString &fileName, files) { + if (!dir.remove(fileName)) + return false; + } + + const QStringList &subDirs + = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); + foreach (const QString &subDirName, subDirs) { + if (!removeDirectory(dirPath + QLatin1Char('/') + subDirName)) + return false; + } + + return dir.rmdir(dirPath); +} + bool MaemoPackageCreationStep::runCommand(const QString &command) { emit addOutput(tr("Package Creation: Running command '%1'.").arg(command), BuildStep::MessageOutput); - QString perl; -#ifdef Q_OS_WIN - perl = maddeRoot() + QLatin1String("/bin/perl.exe "); -#endif - m_buildProc->start(perl + maddeRoot() % QLatin1String("/madbin/") % command); + m_buildProc->start(packagingCommand(maemoToolChain(), command)); if (!m_buildProc->waitForStarted()) { raiseError(tr("Packaging failed."), tr("Packaging error: Could not start command '%1'. Reason: %2") .arg(command).arg(m_buildProc->errorString())); return false; } - m_buildProc->write("\n"); // For dh_make m_buildProc->waitForFinished(-1); if (m_buildProc->error() != QProcess::UnknownError || m_buildProc->exitCode() != 0) { QString mainMessage = tr("Packaging Error: Command '%1' failed.") @@ -364,22 +332,32 @@ bool MaemoPackageCreationStep::packagingNeeded() const QString MaemoPackageCreationStep::packageFilePath() const { - return buildDirectory() % '/' % projectName() - % QLatin1Char('_') % versionString() % QLatin1String("_armel.deb"); + QString error; + const QString &version = versionString(&error); + if (version.isEmpty()) + return QString(); + return buildDirectory() % '/' + % packageFileName(buildConfiguration()->target()->project(), version); } -QString MaemoPackageCreationStep::versionString() const +QString MaemoPackageCreationStep::versionString(QString *error) const { - return m_versionString; + return MaemoTemplatesManager::instance() + ->version(buildConfiguration()->target()->project(), error); + } -void MaemoPackageCreationStep::setVersionString(const QString &version) +bool MaemoPackageCreationStep::setVersionString(const QString &version, + QString *error) { - m_versionString = version; - emit packageFilePathChanged(); + const bool success = MaemoTemplatesManager::instance() + ->setVersion(buildConfiguration()->target()->project(), version, error); + if (success) + emit packageFilePathChanged(); + return success; } -QString MaemoPackageCreationStep::nativePath(const QFile &file) const +QString MaemoPackageCreationStep::nativePath(const QFile &file) { return QDir::toNativeSeparators(QFileInfo(file).filePath()); } @@ -392,6 +370,71 @@ void MaemoPackageCreationStep::raiseError(const QString &shortMsg, TASK_CATEGORY_BUILDSYSTEM)); } +bool MaemoPackageCreationStep::preparePackagingProcess(QProcess *proc, + const MaemoToolChain *tc, const QString &workingDir, QString *error) +{ + QFile configFile(tc->targetRoot() % QLatin1String("/config.sh")); + if (!configFile.open(QIODevice::ReadOnly)) { + *error = tr("Cannot open MADDE config file '%1'.") + .arg(nativePath(configFile)); + return false; + } + + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + const QString &path + = QDir::toNativeSeparators(tc->maddeRoot() + QLatin1Char('/')); + + const QLatin1String key("PATH"); + QString colon = QLatin1String(":"); +#ifdef Q_OS_WIN + colon = QLatin1String(";"); + env.insert(key, path % QLatin1String("bin") % colon % env.value(key)); +#endif + + env.insert(key, tc->targetRoot() % "/bin" % colon % env.value(key)); + env.insert(key, path % QLatin1String("madbin") % colon % env.value(key)); + + QString perlLib + = QDir::fromNativeSeparators(path % QLatin1String("madlib/perl5")); +#ifdef Q_OS_WIN + perlLib = perlLib.remove(QLatin1Char(':')); + perlLib = perlLib.prepend(QLatin1Char('/')); +#endif + env.insert(QLatin1String("PERL5LIB"), perlLib); + env.insert(QLatin1String("PWD"), workingDir); + + const QRegExp envPattern(QLatin1String("([^=]+)=[\"']?([^;\"']+)[\"']? ;.*")); + QByteArray line; + do { + line = configFile.readLine(200); + if (envPattern.exactMatch(line)) + env.insert(envPattern.cap(1), envPattern.cap(2)); + } while (!line.isEmpty()); + + proc->setProcessEnvironment(env); + proc->setWorkingDirectory(workingDir); + proc->start("cd " + workingDir); + proc->waitForFinished(); + return true; +} + +QString MaemoPackageCreationStep::packagingCommand(const MaemoToolChain *tc, + const QString &commandName) +{ + QString perl; +#ifdef Q_OS_WIN + perl = tc->maddeRoot() + QLatin1String("/bin/perl.exe "); +#endif + return perl + tc->maddeRoot() % QLatin1String("/madbin/") % commandName; +} + +QString MaemoPackageCreationStep::packageFileName(const ProjectExplorer::Project *project, + const QString &version) +{ + return project->displayName() % QLatin1Char('_') % version + % QLatin1String("_armel.deb"); +} + const QLatin1String MaemoPackageCreationStep::CreatePackageId("Qt4ProjectManager.MaemoPackageCreationStep"); } // namespace Internal diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.h b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.h index a569136a0f3..86b3f2e4eeb 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.h +++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.h @@ -72,8 +72,17 @@ public: bool isPackagingEnabled() const { return m_packagingEnabled; } void setPackagingEnabled(bool enabled) { m_packagingEnabled = enabled; } - QString versionString() const; - void setVersionString(const QString &version); + QString versionString(QString *error) const; + bool setVersionString(const QString &version, QString *error); + + static bool preparePackagingProcess(QProcess *proc, const MaemoToolChain *tc, + const QString &workingDir, QString *error); + static QString packagingCommand(const MaemoToolChain *tc, + const QString &commandName); + static QString packageFileName(const ProjectExplorer::Project *project, + const QString &version); + + static const QLatin1String DefaultVersionNumber; signals: void packageFilePathChanged(); @@ -94,10 +103,11 @@ private: virtual bool fromMap(const QVariantMap &map); bool createPackage(); + bool removeDirectory(const QString &dirPath); bool runCommand(const QString &command); QString maddeRoot() const; QString targetRoot() const; - QString nativePath(const QFile &file) const; + static QString nativePath(const QFile &file); bool packagingNeeded() const; void raiseError(const QString &shortMsg, const QString &detailedMsg = QString()); @@ -110,7 +120,6 @@ private: static const QLatin1String CreatePackageId; bool m_packagingEnabled; - QString m_versionString; QScopedPointer<QProcess> m_buildProc; }; diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.cpp index 834e20c4f1b..81dc6e77b76 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.cpp +++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.cpp @@ -49,6 +49,9 @@ #include <projectexplorer/target.h> #include <qt4projectmanager/qt4buildconfiguration.h> +#include <QtCore/QTimer> +#include <QtGui/QMessageBox> + namespace Qt4ProjectManager { namespace Internal { @@ -60,18 +63,29 @@ MaemoPackageCreationWidget::MaemoPackageCreationWidget(MaemoPackageCreationStep m_ui->setupUi(this); m_ui->skipCheckBox->setChecked(!m_step->isPackagingEnabled()); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - const QStringList list = m_step->versionString().split(QLatin1Char('.'), + QTimer::singleShot(0, this, SLOT(initVersion())); +} + +void MaemoPackageCreationWidget::init() +{ +} + +void MaemoPackageCreationWidget::initVersion() +{ + QString error; + QString versionString = m_step->versionString(&error); + if (versionString.isEmpty()) { + QMessageBox::critical(this, tr("No version available."), error); + versionString = MaemoPackageCreationStep::DefaultVersionNumber; + } + const QStringList list = versionString.split(QLatin1Char('.'), QString::SkipEmptyParts); m_ui->major->setValue(list.value(0, QLatin1String("0")).toInt()); m_ui->minor->setValue(list.value(1, QLatin1String("0")).toInt()); m_ui->patch->setValue(list.value(2, QLatin1String("0")).toInt()); - versionInfoChanged(); connect(m_step, SIGNAL(packageFilePathChanged()), this, SIGNAL(updateSummary())); -} - -void MaemoPackageCreationWidget::init() -{ + versionInfoChanged(); } QString MaemoPackageCreationWidget::summaryText() const @@ -94,8 +108,12 @@ void MaemoPackageCreationWidget::handleSkipButtonToggled(bool checked) void MaemoPackageCreationWidget::versionInfoChanged() { - m_step->setVersionString(m_ui->major->text() + QLatin1Char('.') - + m_ui->minor->text() + QLatin1Char('.') + m_ui->patch->text()); + QString error; + const bool success = m_step->setVersionString(m_ui->major->text() + + QLatin1Char('.') + m_ui->minor->text() + QLatin1Char('.') + + m_ui->patch->text(), &error); + if (!success) + QMessageBox::critical(this, tr("Could not set version number"), error); } } // namespace Internal diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.h b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.h index 6f01bdeaa76..f73ac9a0eb3 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.h +++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.h @@ -66,6 +66,7 @@ public: private slots: void handleSkipButtonToggled(bool checked); void versionInfoChanged(); + void initVersion(); private: MaemoPackageCreationStep * const m_step; diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemotemplatesmanager.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemotemplatesmanager.cpp new file mode 100644 index 00000000000..b7d9d9da153 --- /dev/null +++ b/src/plugins/qt4projectmanager/qt-maemo/maemotemplatesmanager.cpp @@ -0,0 +1,248 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +**************************************************************************/ + +#include "maemotemplatesmanager.h" + +#include "maemopackagecreationstep.h" +#include "maemotoolchain.h" + +#include <projectexplorer/project.h> +#include <projectexplorer/projectexplorer.h> +#include <projectexplorer/session.h> +#include <projectexplorer/target.h> +#include <qt4projectmanager/qt4projectmanagerconstants.h> +#include <qt4projectmanager/qt4target.h> + +#include <QtCore/QDir> +#include <QtCore/QFile> +#include <QtCore/QList> +#include <QtCore/QProcess> +#include <QtGui/QMessageBox> + +using namespace ProjectExplorer; + +namespace Qt4ProjectManager { +namespace Internal { + +const QLatin1String MaemoTemplatesManager::PackagingDirName("packaging"); + +MaemoTemplatesManager *MaemoTemplatesManager::m_instance = 0; + +MaemoTemplatesManager *MaemoTemplatesManager::instance(QObject *parent) +{ + Q_ASSERT(!m_instance != !parent); + if (!m_instance) + m_instance = new MaemoTemplatesManager(parent); + return m_instance; +} + +MaemoTemplatesManager::MaemoTemplatesManager(QObject *parent) : + QObject(parent), m_activeProject(0) +{ + SessionManager * const session + = ProjectExplorerPlugin::instance()->session(); + connect(session, SIGNAL(startupProjectChanged(ProjectExplorer::Project*)), + this, SLOT(handleActiveProjectChanged(ProjectExplorer::Project*))); + handleActiveProjectChanged(session->startupProject()); +} + +void MaemoTemplatesManager::handleActiveProjectChanged(ProjectExplorer::Project *project) +{ + if (m_activeProject) + disconnect(m_activeProject, 0, this, 0); + m_activeProject= project; + if (m_activeProject) { + connect(m_activeProject, SIGNAL(addedTarget(ProjectExplorer::Target*)), + this, SLOT(createTemplatesIfNecessary(ProjectExplorer::Target*))); + connect(m_activeProject, + SIGNAL(activeTargetChanged(ProjectExplorer::Target*)), this, + SLOT(createTemplatesIfNecessary(ProjectExplorer::Target*))); + const QList<Target *> &targets = m_activeProject->targets(); + foreach (Target * const target, targets) + createTemplatesIfNecessary(target); + } +} + +void MaemoTemplatesManager::createTemplatesIfNecessary(ProjectExplorer::Target *target) +{ + Q_ASSERT_X(m_activeProject, Q_FUNC_INFO, + "Impossible: Received signal from unknown project"); + + if (!target + || target->id() != QLatin1String(Constants::MAEMO_DEVICE_TARGET_ID)) + return; + + QDir projectDir(m_activeProject->projectDirectory()); + if (projectDir.exists(PackagingDirName)) + return; + const QString packagingTemplatesDir + = projectDir.path() + QLatin1Char('/') + PackagingDirName; + if (!projectDir.mkdir(PackagingDirName)) { + raiseError(tr("Could not create directory '%1'.") + .arg(QDir::toNativeSeparators(packagingTemplatesDir))); + return; + } + + QProcess dh_makeProc; + QString error; + const Qt4Target * const qt4Target = qobject_cast<Qt4Target *>(target); + Q_ASSERT_X(qt4Target, Q_FUNC_INFO, "Target ID does not match actual type."); + const MaemoToolChain * const tc + = dynamic_cast<MaemoToolChain *>(qt4Target->activeBuildConfiguration()->toolChain()); + Q_ASSERT_X(tc, Q_FUNC_INFO, "Maemo target has no maemo toolchain."); + if (!MaemoPackageCreationStep::preparePackagingProcess(&dh_makeProc, tc, + packagingTemplatesDir, &error)) { + raiseError(error); + return; + } + + const QString command = QLatin1String("dh_make -s -n -p ") + + m_activeProject->displayName() + QLatin1Char('_') + + MaemoPackageCreationStep::DefaultVersionNumber; + dh_makeProc.start(MaemoPackageCreationStep::packagingCommand(tc, command)); + if (!dh_makeProc.waitForStarted()) { + raiseError(tr("Unable to create debian templates: dh_make failed (%1)") + .arg(dh_makeProc.errorString())); + return; + } + dh_makeProc.write("\n"); // Needs user input. + dh_makeProc.waitForFinished(-1); + if (dh_makeProc.error() != QProcess::UnknownError + || dh_makeProc.exitCode() != 0) { + raiseError(tr("Unable to create debian templates: dh_make failed (%1)") + .arg(dh_makeProc.errorString())); + return; + } + + QDir debianDir(packagingTemplatesDir + QLatin1String("/debian")); + const QStringList &files + = debianDir.entryList(QStringList() << QLatin1String("*.??"), + QDir::Files); + foreach (const QString &fileName, files) + debianDir.remove(fileName); + + const QString rulesFilePath + = packagingTemplatesDir + QLatin1String("/debian/rules"); + QFile rulesFile(rulesFilePath); + if (!rulesFile.open(QIODevice::ReadWrite)) { + raiseError(tr("Packaging Error: Cannot open file '%1'.") + .arg(QDir::toNativeSeparators(rulesFilePath))); + return; + } + + QByteArray rulesContents = rulesFile.readAll(); + rulesContents.replace("DESTDIR", "INSTALL_ROOT"); + rulesContents.replace("dh_shlibdeps", "# dh_shlibdeps"); + + // Would be the right solution, but does not work (on Windows), + // because dpkg-genchanges doesn't know about it (and can't be told). + // rulesContents.replace("dh_builddeb", "dh_builddeb --destdir=."); + + rulesFile.resize(0); + rulesFile.write(rulesContents); + if (rulesFile.error() != QFile::NoError) { + raiseError(tr("Packaging Error: Cannot write file '%1'.") + .arg(QDir::toNativeSeparators(rulesFilePath))); + return; + } +} + +QString MaemoTemplatesManager::version(const Project *project, + QString *error) const +{ + const QString changeLogFilePath + = project->projectDirectory() + QLatin1Char('/') + PackagingDirName + + QLatin1String("/debian/changelog"); + const QString nativePath = QDir::toNativeSeparators(changeLogFilePath); + QFile changeLog(changeLogFilePath); + if (!changeLog.exists()) { + *error = tr("File '%1' does not exist").arg(nativePath); + return QString(); + } + if (!changeLog.open(QIODevice::ReadOnly)) { + *error = tr("Cannot open Debian changelog file '%1': %2") + .arg(nativePath, changeLog.errorString()); + return QString(); + } + const QByteArray &firstLine = changeLog.readLine(); + const int openParenPos = firstLine.indexOf('('); + if (openParenPos == -1) { + *error = tr("Debian changelog file '%1' has unexpected format.") + .arg(nativePath); + return QString(); + } + const int closeParenPos = firstLine.indexOf(')', openParenPos); + if (closeParenPos == -1) { + *error = tr("Debian changelog file '%1' has unexpected format.") + .arg(nativePath); + return QString(); + } + return QString::fromUtf8(firstLine.mid(openParenPos + 1, + closeParenPos - openParenPos - 1).data()); +} + +bool MaemoTemplatesManager::setVersion(const Project *project, + const QString &version, QString *error) const +{ + const QString debianDir = project->projectDirectory() + QLatin1Char('/') + + PackagingDirName + QLatin1String("/debian/"); + const QString changeLogFilePath = debianDir + QLatin1String("changelog"); + const QString nativePath = QDir::toNativeSeparators(changeLogFilePath); + QFile changeLog(changeLogFilePath); + if (!changeLog.exists()) { + *error = tr("File '%1' does not exist").arg(nativePath); + return false; + } + if (!changeLog.open(QIODevice::ReadWrite)) { + *error = tr("Cannot open Debian changelog file '%1': %2") + .arg(nativePath , changeLog.errorString()); + return false; + } + + QString content = QString::fromUtf8(changeLog.readAll()); + content.replace(QRegExp(QLatin1String("\\([a-zA-Z0-9_\\.]+\\)")), + QLatin1Char('(') % version % QLatin1Char(')')); + changeLog.resize(0); + changeLog.write(content.toUtf8()); + changeLog.close(); + if (changeLog.error() != QFile::NoError) { + *error = tr("Error writing Debian changelog file '%1': %2") + .arg(nativePath , changeLog.errorString()); + return false; + } + return true; +} + +void MaemoTemplatesManager::raiseError(const QString &reason) +{ + QMessageBox::critical(0, tr("Error creating Maemo templates"), reason); +} + +} // namespace Internal +} // namespace Qt4ProjectManager diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemotemplatesmanager.h b/src/plugins/qt4projectmanager/qt-maemo/maemotemplatesmanager.h new file mode 100644 index 00000000000..15af028cd29 --- /dev/null +++ b/src/plugins/qt4projectmanager/qt-maemo/maemotemplatesmanager.h @@ -0,0 +1,72 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +**************************************************************************/ + +#ifndef MAEMOTEMPLATESCREATOR_H +#define MAEMOTEMPLATESCREATOR_H + +#include <QtCore/QObject> + +namespace ProjectExplorer { +class Project; +class Target; +} + +namespace Qt4ProjectManager { +namespace Internal { + +class MaemoTemplatesManager : public QObject +{ + Q_OBJECT + +public: + static MaemoTemplatesManager *instance(QObject *parent = 0); + + QString version(const ProjectExplorer::Project *project, + QString *error) const; + bool setVersion(const ProjectExplorer::Project *project, + const QString &version, QString *error) const; + + static const QLatin1String PackagingDirName; + +private slots: + void handleActiveProjectChanged(ProjectExplorer::Project *project); + void createTemplatesIfNecessary(ProjectExplorer::Target *target); + +private: + explicit MaemoTemplatesManager(QObject *parent); + void raiseError(const QString &reason); + + static MaemoTemplatesManager *m_instance; + ProjectExplorer::Project *m_activeProject; +}; + +} // namespace Internal +} // namespace Qt4ProjectManager + +#endif // MAEMOTEMPLATESCREATOR_H diff --git a/src/plugins/qt4projectmanager/qt-maemo/qt-maemo.pri b/src/plugins/qt4projectmanager/qt-maemo/qt-maemo.pri index 22542222fae..53b7fc4c835 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/qt-maemo.pri +++ b/src/plugins/qt4projectmanager/qt-maemo/qt-maemo.pri @@ -28,7 +28,8 @@ HEADERS += \ $$PWD/maemodebugsupport.h \ $$PWD/maemodeviceconfiglistmodel.h \ $$PWD/maemoremotemountsmodel.h \ - $$PWD/maemodeviceenvreader.h + $$PWD/maemodeviceenvreader.h \ + $$PWD/maemotemplatesmanager.h SOURCES += \ $$PWD/maemoconfigtestdialog.cpp \ @@ -58,7 +59,8 @@ SOURCES += \ $$PWD/maemodebugsupport.cpp \ $$PWD/maemodeviceconfiglistmodel.cpp \ $$PWD/maemoremotemountsmodel.cpp \ - $$PWD/maemodeviceenvreader.cpp + $$PWD/maemodeviceenvreader.cpp \ + $$PWD/maemotemplatesmanager.cpp FORMS += \ $$PWD/maemoconfigtestdialog.ui \ -- GitLab