Commit f3d5fd83 authored by Christian Kandeler's avatar Christian Kandeler
Browse files

Maemo: Add publishing support for Extras-devel repository.

parent 70d6fda3
......@@ -33,6 +33,7 @@
#include "maemodeploystepfactory.h"
#include "maemodeviceconfigurations.h"
#include "maemopackagecreationfactory.h"
#include "maemopublishingwizardfactories.h"
#include "maemoqemumanager.h"
#include "maemorunfactories.h"
#include "maemosettingspage.h"
......@@ -61,6 +62,7 @@ MaemoManager::MaemoManager()
, m_packageCreationFactory(new MaemoPackageCreationFactory(this))
, m_deployStepFactory(new MaemoDeployStepFactory(this))
, m_settingsPage(new MaemoSettingsPage(this))
, m_publishingFactoryFremantleFree(new MaemoPublishingWizardFactoryFremantleFree(this))
{
Q_ASSERT(!m_instance);
......@@ -75,6 +77,7 @@ MaemoManager::MaemoManager()
pluginManager->addObject(m_packageCreationFactory);
pluginManager->addObject(m_deployStepFactory);
pluginManager->addObject(m_settingsPage);
pluginManager->addObject(m_publishingFactoryFremantleFree);
}
MaemoManager::~MaemoManager()
......@@ -85,6 +88,7 @@ MaemoManager::~MaemoManager()
pluginManager->removeObject(m_deployStepFactory);
pluginManager->removeObject(m_packageCreationFactory);
pluginManager->removeObject(m_settingsPage);
pluginManager->removeObject(m_publishingFactoryFremantleFree);
m_instance = 0;
}
......
......@@ -43,6 +43,7 @@ namespace Internal {
class MaemoDeployStepFactory;
class MaemoPackageCreationFactory;
class MaemoPublishingWizardFactoryFremantleFree;
class MaemoRunControlFactory;
class MaemoRunConfigurationFactory;
class MaemoSettingsPage;
......@@ -71,6 +72,7 @@ private:
MaemoDeployStepFactory *m_deployStepFactory;
MaemoSettingsPage *m_settingsPage;
MaemoQemuManager *m_qemuRuntimeManager;
MaemoPublishingWizardFactoryFremantleFree *m_publishingFactoryFremantleFree;
};
} // namespace Internal
......
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of Qt Creator.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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.
**
** 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "maemopublishedprojectmodel.h"
namespace Qt4ProjectManager {
namespace Internal {
namespace {
const int IncludeColumn = 2;
} // anonymous namespace
MaemoPublishedProjectModel::MaemoPublishedProjectModel(QObject *parent)
: QFileSystemModel(parent)
{
}
int MaemoPublishedProjectModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return IncludeColumn + 1;
}
int MaemoPublishedProjectModel::rowCount(const QModelIndex &parent) const
{
if (isDir(parent) && m_filesToExclude.contains(filePath(parent)))
return 0;
return QFileSystemModel::rowCount(parent);
}
QVariant MaemoPublishedProjectModel::headerData(int section,
Qt::Orientation orientation, int role) const
{
if (orientation != Qt::Horizontal || section != IncludeColumn)
return QFileSystemModel::headerData(section, orientation, role);
return tr("Include in package");
}
Qt::ItemFlags MaemoPublishedProjectModel::flags(const QModelIndex &index) const
{
if (index.column() != IncludeColumn)
return QFileSystemModel::flags(index);
return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable;
}
QVariant MaemoPublishedProjectModel::data(const QModelIndex &index,
int role) const
{
if (index.column() != IncludeColumn)
return QFileSystemModel::data(index, role);
const bool include = !m_filesToExclude.contains(filePath(index));
if (role == Qt::DisplayRole)
return include ? tr("Include") : tr("Don't include");
else if (role == Qt::CheckStateRole)
return include ? Qt::Checked : Qt::Unchecked;
else
return QVariant();
}
bool MaemoPublishedProjectModel::setData(const QModelIndex &index,
const QVariant &value, int role)
{
if (index.column() != IncludeColumn)
return QFileSystemModel::setData(index, value, role);
if (role == Qt::CheckStateRole) {
if (value == Qt::Checked) {
m_filesToExclude.remove(filePath(index));
} else {
m_filesToExclude.insert(filePath(index));
}
if (isDir(index))
emit layoutChanged();
return true;
}
return false;
}
} // namespace Internal
} // namespace Qt4ProjectManager
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of Qt Creator.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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.
**
** 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef MAEMOPUBLISHEDPROJECTMODEL_H
#define MAEMOPUBLISHEDPROJECTMODEL_H
#include <QtCore/QPersistentModelIndex>
#include <QtCore/QSet>
#include <QtCore/QStringList>
#include <QtGui/QFileSystemModel>
namespace Qt4ProjectManager {
namespace Internal {
class MaemoPublishedProjectModel : public QFileSystemModel
{
Q_OBJECT
public:
explicit MaemoPublishedProjectModel(QObject *parent = 0);
QStringList filesToExclude() const { return m_filesToExclude.toList(); }
private:
virtual int columnCount(const QModelIndex &parent) const;
virtual int rowCount(const QModelIndex &parent) const;
virtual QVariant headerData(int section, Qt::Orientation orientation,
int role) const;
virtual QVariant data(const QModelIndex &index, int role) const;
virtual bool setData(const QModelIndex &index, const QVariant &value,
int role);
virtual Qt::ItemFlags flags(const QModelIndex &index) const;
QSet<QString> m_filesToExclude;
QPersistentModelIndex m_rootIndex;
};
} // namespace Internal
} // namespace Qt4ProjectManager
#endif // MAEMOPUBLISHEDPROJECTMODEL_H
/**************************************************************************
**
** 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 http://qt.nokia.com/contact.
**
**************************************************************************/
#include "maemopublisherfremantlefree.h"
#include "maemoglobal.h"
#include "maemopackagecreationstep.h"
#include "maemopublishingfileselectiondialog.h"
#include "maemotoolchain.h"
#include <coreplugin/ifile.h>
#include <projectexplorer/project.h>
#include <qt4projectmanager/qmakestep.h>
#include <qt4projectmanager/qt4buildconfiguration.h>
#include <QtCore/QCoreApplication>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QStringList>
#define ASSERT_STATE(state) ASSERT_STATE_GENERIC(State, state, m_state)
using namespace Core;
namespace Qt4ProjectManager {
namespace Internal {
MaemoPublisherFremantleFree::MaemoPublisherFremantleFree(const ProjectExplorer::Project *project,
QObject *parent) :
QObject(parent),
m_project(project),
m_state(Inactive),
m_sshParams(SshConnectionParameters::DefaultProxy)
{
m_sshParams.authType = SshConnectionParameters::AuthByKey;
m_sshParams.timeout = 30;
m_sshParams.port = 22;
m_process = new QProcess(this);
connect(m_process, SIGNAL(finished(int,QProcess::ExitStatus)),
SLOT(handleProcessFinished()));
connect(m_process, SIGNAL(error(QProcess::ProcessError)),
SLOT(handleProcessError(QProcess::ProcessError)));
connect(m_process, SIGNAL(readyReadStandardOutput()),
SLOT(handleProcessStdOut()));
connect(m_process, SIGNAL(readyReadStandardError()),
SLOT(handleProcessStdErr()));
}
MaemoPublisherFremantleFree::~MaemoPublisherFremantleFree()
{
ASSERT_STATE(Inactive);
m_process->kill();
}
void MaemoPublisherFremantleFree::publish()
{
createPackage();
}
void MaemoPublisherFremantleFree::setSshParams(const QString &hostName,
const QString &userName, const QString &keyFile, const QString &remoteDir)
{
Q_ASSERT(m_doUpload);
m_sshParams.host = hostName;
m_sshParams.uname = userName;
m_sshParams.privateKeyFile = keyFile;
m_remoteDir = remoteDir;
}
void MaemoPublisherFremantleFree::cancel()
{
finishWithFailure(tr("Canceled."), tr("Publishing canceled by user."));
}
void MaemoPublisherFremantleFree::createPackage()
{
// Step 1: Copy project directory.
setState(CopyingProjectDir);
m_tmpProjectDir = tmpDirContainer() + QLatin1Char('/')
+ m_project->displayName();
if (QFileInfo(tmpDirContainer()).exists()) {
emit progressReport(tr("Removing left-over temporary directory ..."));
if (!removeRecursively(tmpDirContainer())) {
finishWithFailure(tr("Error: Could not remove temporary directory."),
tr("Publishing failed: Could not create source package."));
return;
}
}
emit progressReport(tr("Setting up temporary directory ..."));
if (!QDir::temp().mkdir(QFileInfo(tmpDirContainer()).fileName())) {
finishWithFailure(tr("Error: Could not create temporary directory."),
tr("Publishing failed: Could not create source package."));
return;
}
if (!copyRecursively(m_project->projectDirectory(), m_tmpProjectDir)) {
finishWithFailure(tr("Error: Could not copy project directory"),
tr("Publishing failed: Could not create source package."));
return;
}
emit progressReport(tr("Cleaning up temporary directory ..."));
QString error;
if (!MaemoPackageCreationStep::preparePackagingProcess(m_process,
m_buildConfig, m_tmpProjectDir, &error)) {
finishWithFailure(tr("Error preparing packaging process: %1").arg(error),
tr("Publishing failed: Could not create package."));
return;
}
setState(RunningQmake);
const ProjectExplorer::ProcessParameters * const pp
= m_buildConfig->qmakeStep()->processParameters();
m_process->start(pp->effectiveCommand() + QLatin1String(" ")
+ pp->effectiveArguments());
}
// TODO: The same exists in packaging step. Move to MaemoGlobal.
bool MaemoPublisherFremantleFree::removeRecursively(const QString &filePath)
{
QFileInfo fileInfo(filePath);
if (fileInfo.isDir()) {
QDir dir(filePath);
QStringList fileNames = dir.entryList(QDir::Files | QDir::Hidden
| QDir::System | QDir::Dirs | QDir::NoDotAndDotDot);
foreach (const QString &fileName, fileNames) {
if (!removeRecursively(filePath + QLatin1Char('/') + fileName))
return false;
}
dir.cdUp();
if (!dir.rmdir(fileInfo.fileName())) {
emit progressReport(tr("Failed to remove directory '%1'.")
.arg(QDir::toNativeSeparators(filePath)));
return false;
}
} else {
if (!QFile::remove(filePath)) {
emit progressReport(tr("Failed to remove file '%1'.")
.arg(QDir::toNativeSeparators(filePath)), ErrorOutput);
return false;
}
}
return true;
}
bool MaemoPublisherFremantleFree::copyRecursively(const QString &srcFilePath,
const QString &tgtFilePath)
{
if (m_state == Inactive)
return true;
QFileInfo srcFileInfo(srcFilePath);
if (srcFileInfo.isDir()) {
if (srcFileInfo == QFileInfo(m_project->projectDirectory()
+ QLatin1String("/debian")))
return true;
QString actualSourcePath = srcFilePath;
QString actualTargetPath = tgtFilePath;
if (srcFileInfo.fileName() == QLatin1String("qtc_packaging")) {
actualSourcePath += QLatin1String("/debian_fremantle");
actualTargetPath.replace(QRegExp(QLatin1String("qtc_packaging$")),
QLatin1String("debian"));
}
QDir targetDir(actualTargetPath);
targetDir.cdUp();
if (!targetDir.mkdir(QFileInfo(actualTargetPath).fileName())) {
emit progressReport(tr("Failed to create directory '%1'.")
.arg(QDir::toNativeSeparators(actualTargetPath)), ErrorOutput);
return false;
}
QDir sourceDir(actualSourcePath);
QStringList fileNames = sourceDir.entryList(QDir::Files | QDir::Hidden
| QDir::System | QDir::Dirs | QDir::NoDotAndDotDot);
foreach (const QString &fileName, fileNames) {
if (!copyRecursively(actualSourcePath + QLatin1Char('/') + fileName,
actualTargetPath + QLatin1Char('/') + fileName))
return false;
}
} else {
if (!QFile::copy(srcFilePath, tgtFilePath)) {
emit progressReport(tr("Could not copy file '%1' to '%2'.")
.arg(QDir::toNativeSeparators(srcFilePath),
QDir::toNativeSeparators(tgtFilePath)));
return false;
}
if (tgtFilePath == m_tmpProjectDir + QLatin1String("/debian/rules")) {
QFile rulesFile(tgtFilePath);
if (!rulesFile.open(QIODevice::ReadWrite)) {
emit progressReport(tr("Error: Cannot open file '%1'.")
.arg(QDir::toNativeSeparators(tgtFilePath)));
return false;
}
QByteArray rulesContents = rulesFile.readAll();
rulesContents.replace("$(MAKE) clean", "# $(MAKE) clean");
rulesContents.replace("# Add here commands to configure the package.",
"qmake " + QFileInfo(m_project->file()->fileName()).fileName().toLocal8Bit());
rulesFile.resize(0);
rulesFile.write(rulesContents);
}
}
return true;
}
void MaemoPublisherFremantleFree::handleProcessError(QProcess::ProcessError error)
{
if (error == QProcess::FailedToStart)
handleProcessFinished(true);
}
void MaemoPublisherFremantleFree::handleProcessFinished()
{
handleProcessFinished(false);
}
void MaemoPublisherFremantleFree::handleProcessStdOut()
{
if (m_state == RunningQmake || m_state == RunningMakeDistclean
|| m_state == BuildingPackage) {
emit progressReport(QString::fromLocal8Bit(m_process->readAllStandardOutput()),
ToolStatusOutput);
}
}
void MaemoPublisherFremantleFree::handleProcessStdErr()
{
if (m_state == RunningQmake || m_state == RunningMakeDistclean
|| m_state == BuildingPackage) {
emit progressReport(QString::fromLocal8Bit(m_process->readAllStandardError()),
ToolErrorOutput);
}
}
void MaemoPublisherFremantleFree::handleProcessFinished(bool failedToStart)
{
ASSERT_STATE(QList<State>() << RunningQmake << RunningMakeDistclean
<< BuildingPackage << Inactive);
switch (m_state) {
case RunningQmake:
if (failedToStart || m_process->exitStatus() != QProcess::NormalExit
||m_process->exitCode() != 0) {
runDpkgBuildPackage();
} else {
setState(RunningMakeDistclean);
m_process->start(m_buildConfig->makeCommand(),
QStringList() << QLatin1String("distclean"));
}
break;
case RunningMakeDistclean:
runDpkgBuildPackage();
break;
case BuildingPackage: {
QString error;
if (failedToStart) {
error = tr("Error: Failed to start dpkg-buildpackage.");
} else if (m_process->exitStatus() != QProcess::NormalExit
|| m_process->exitCode() != 0) {
error = tr("Error: dpkg-buildpackage did not succeed.");
}
if (!error.isEmpty()) {
finishWithFailure(error, tr("Package creation failed."));
return;
}
QDir dir(tmpDirContainer());
const QStringList &fileNames = dir.entryList(QDir::Files);
foreach (const QString &fileName, fileNames) {
const QString filePath
= tmpDirContainer() + QLatin1Char('/') + fileName;
if (fileName.endsWith(QLatin1String(".dsc")))
m_filesToUpload.append(filePath);
else
m_filesToUpload.prepend(filePath);
}
if (!m_doUpload) {
emit progressReport(tr("Done."));
QStringList nativeFilePaths;
foreach (const QString &filePath, m_filesToUpload)
nativeFilePaths << QDir::toNativeSeparators(filePath);
m_resultString = tr("Packaging finished successfully. "
"The following files were created:\n")
+ nativeFilePaths.join(QLatin1String("\n"));
setState(Inactive);
} else {
uploadPackage();
}
break;
}
default:
break;
}
}
void MaemoPublisherFremantleFree::runDpkgBuildPackage()
{
MaemoPublishingFileSelectionDialog d(m_tmpProjectDir);
if (d.exec() == QDialog::Rejected) {
cancel();
return;
}
foreach (const QString &filePath, d.filesToExclude()) {
if (!removeRecursively(filePath))
finishWithFailure(QString(),
tr("Publishing failed: Could not create package."));
}
if (m_state == Inactive)
return;
setState(BuildingPackage);
emit progressReport(tr("Building source package..."));
const MaemoToolChain * const tc
= dynamic_cast<MaemoToolChain *>(m_buildConfig->toolChain());
QStringList args