summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libs/installer/binarycontent.cpp311
-rw-r--r--src/libs/installer/binarycontent.h24
-rw-r--r--src/libs/installer/packagemanagercore.cpp4
-rw-r--r--src/libs/installer/packagemanagercore.h5
-rw-r--r--src/libs/installer/packagemanagercore_p.cpp19
-rw-r--r--src/libs/installer/packagemanagercore_p.h2
-rw-r--r--src/libs/installer/productkeycheck.cpp4
-rw-r--r--src/libs/installer/productkeycheck.h15
-rw-r--r--src/sdk/installerbase.cpp546
-rw-r--r--src/sdk/installerbase.h70
-rw-r--r--src/sdk/main.cpp193
-rw-r--r--src/sdk/sdk.pro14
-rw-r--r--src/sdk/sdkapp.h87
-rw-r--r--src/sdk/updatechecker.cpp114
-rw-r--r--src/sdk/updatechecker.h11
-rw-r--r--tests/auto/installer/packagemanagercore/tst_packagemanagercore.cpp6
-rw-r--r--tools/devtool/main.cpp15
-rw-r--r--tools/devtool/operationrunner.cpp3
-rw-r--r--tools/devtool/operationrunner.h5
19 files changed, 666 insertions, 782 deletions
diff --git a/src/libs/installer/binarycontent.cpp b/src/libs/installer/binarycontent.cpp
index 6280134d9..25032177b 100644
--- a/src/libs/installer/binarycontent.cpp
+++ b/src/libs/installer/binarycontent.cpp
@@ -41,16 +41,9 @@
#include "binarycontent.h"
-#include "binaryformat.h"
-#include "binaryformatenginehandler.h"
#include "errors.h"
#include "fileio.h"
#include "fileutils.h"
-#include "kdupdaterupdateoperationfactory.h"
-#include "utils.h"
-
-#include <QFile>
-#include <QResource>
namespace QInstaller {
@@ -101,124 +94,6 @@ qint64 BinaryContent::findMagicCookie(QFile *in, quint64 magicCookie)
}
/*!
- \internal
- Registers the resource found at \a segment within \a file into the Qt resource system.
-*/
-static QByteArray addResourceFromBinary(QFile* file, const Range<qint64> &segment)
-{
- if (segment.length() <= 0)
- return 0;
-
- if (!file->seek(segment.start())) {
- throw Error(QCoreApplication::translate("BinaryContent",
- "Could not seek to in-binary resource. (offset: %1, length: %2)")
- .arg(QString::number(segment.start()), QString::number(segment.length())));
- }
-
- QByteArray ba = QInstaller::retrieveData(file, segment.length());
- if (!QResource::registerResource((const uchar*) ba.constData(), QLatin1String(":/metadata"))) {
- throw Error(QCoreApplication::translate("BinaryContent",
- "Could not register in-binary resource."));
- }
- return ba;
-}
-
-
-// -- Private
-
-class BinaryContent::Private : public QSharedData
-{
-public:
- Private();
- explicit Private(const QString &path);
- Private(const Private &other);
- ~Private();
-
- qint64 m_magicMarker;
- qint64 m_dataBlockStart;
-
- QSharedPointer<QFile> m_appBinary;
- QSharedPointer<QFile> m_binaryDataFile;
-
- QList<Operation *> m_performedOperations;
- QList<QPair<QString, QString> > m_performedOperationsData;
-
- QVector<QByteArray> m_resourceMappings;
- QVector<Range<qint64> > m_metadataResourceSegments;
-};
-
-
-BinaryContent::Private::Private()
- : m_magicMarker(Q_INT64_C(0))
- , m_dataBlockStart(Q_INT64_C(0))
- , m_appBinary(0)
- , m_binaryDataFile(0)
-{}
-
-BinaryContent::Private::Private(const QString &path)
- : m_magicMarker(Q_INT64_C(0))
- , m_dataBlockStart(Q_INT64_C(0))
- , m_appBinary(new QFile(path))
- , m_binaryDataFile(0)
-{}
-
-BinaryContent::Private::Private(const Private &other)
- : QSharedData(other)
- , m_magicMarker(other.m_magicMarker)
- , m_dataBlockStart(other.m_dataBlockStart)
- , m_appBinary(other.m_appBinary)
- , m_binaryDataFile(other.m_binaryDataFile)
- , m_performedOperations(other.m_performedOperations)
- , m_performedOperationsData(other.m_performedOperationsData)
- , m_resourceMappings(other.m_resourceMappings)
- , m_metadataResourceSegments(other.m_metadataResourceSegments)
-{}
-
-BinaryContent::Private::~Private()
-{
- foreach (const QByteArray &rccData, m_resourceMappings)
- QResource::unregisterResource((const uchar*) rccData.constData(), QLatin1String(":/metadata"));
- m_resourceMappings.clear();
-}
-
-
-// -- BinaryContent
-
-BinaryContent::BinaryContent()
- : d(new Private)
-{}
-
-BinaryContent::~BinaryContent()
-{}
-
-BinaryContent::BinaryContent(const QString &path)
- : d(new Private(path))
-{}
-
-BinaryContent::BinaryContent(const BinaryContent &rhs)
- : d(rhs.d)
-{}
-
-BinaryContent &BinaryContent::operator=(const BinaryContent &rhs)
-{
- if (this != &rhs)
- d = rhs.d;
- return *this;
-}
-
-/*!
- Reads binary content stored in the passed application binary. Maps the embedded resources into
- memory and instantiates performed operations if available.
-*/
-BinaryContent BinaryContent::readAndRegisterFromBinary(const QString &path)
-{
- BinaryContent c = BinaryContent::readFromBinary(path);
- c.registerEmbeddedQResources();
- c.registerPerformedOperations();
- return c;
-}
-
-/*!
* \class QInstaller::BinaryContent
*
* BinaryContent handles binary information embedded into executables.
@@ -288,41 +163,6 @@ BinaryContent BinaryContent::readAndRegisterFromBinary(const QString &path)
* \endverbatim
*/
-BinaryContent BinaryContent::readFromBinary(const QString &path)
-{
- BinaryContent c(path);
-
- // Try to read the binary layout of the calling application. We need to figure out
- // if we are in installer or an unistaller (maintenance, package manager, updater) binary.
- QInstaller::openForRead(c.d->m_appBinary.data());
- quint64 cookiePos = findMagicCookie(c.d->m_appBinary.data(), BinaryContent::MagicCookie);
- if (!c.d->m_appBinary->seek(cookiePos - sizeof(qint64))) { // seek to read the marker
- throw Error(QCoreApplication::translate("BinaryContent",
- "Could not seek to %1 to read the magic marker.").arg(cookiePos - sizeof(qint64)));
- }
- const qint64 magicMarker = QInstaller::retrieveInt64(c.d->m_appBinary.data());
-
- if (magicMarker != MagicInstallerMarker) {
- // We are not an installer, so we need to read the data from the .dat file.
-
- QFileInfo fi(path);
- QString bundlePath; // On OSX it's not inside the bundle, deserves TODO.
- if (QInstaller::isInBundle(fi.absoluteFilePath(), &bundlePath))
- fi.setFile(bundlePath);
-
- c.d->m_binaryDataFile.reset(new QFile(fi.absolutePath() + QLatin1Char('/') + fi.baseName()
- + QLatin1String(".dat")));
- QInstaller::openForRead(c.d->m_binaryDataFile.data());
- readBinaryData(c, c.d->m_binaryDataFile, binaryLayout(c.d->m_binaryDataFile.data(),
- BinaryContent::MagicCookieDat));
- } else {
- // We are an installer, all data is appended to our binary itself.
- readBinaryData(c, c.d->m_appBinary, binaryLayout(c.d->m_appBinary.data(),
- BinaryContent::MagicCookie));
- }
- return c;
-}
-
/* static */
BinaryLayout BinaryContent::binaryLayout(QFile *file, quint64 magicCookie)
{
@@ -370,157 +210,6 @@ BinaryLayout BinaryContent::binaryLayout(QFile *file, quint64 magicCookie)
return layout;
}
-/* static */
-void BinaryContent::readBinaryData(BinaryContent &content, const QSharedPointer<QFile> &file,
- const BinaryLayout &layout)
-{
- content.d->m_magicMarker = layout.magicMarker;
- content.d->m_metadataResourceSegments = layout.metadataResourceSegments;
-
- const qint64 dataBlockStart = layout.endOfData - layout.dataBlockSize;
- const qint64 operationsStart = layout.operationsStart + dataBlockStart;
- if (!file->seek(operationsStart))
- throw Error(QCoreApplication::translate("BinaryContent", "Could not seek to operation list."));
-
- const qint64 operationsCount = QInstaller::retrieveInt64(file.data());
- qDebug() << "Number of operations:" << operationsCount;
-
- for (int i = 0; i < operationsCount; ++i) {
- const QString name = QInstaller::retrieveString(file.data());
- const QString data = QInstaller::retrieveString(file.data());
- content.d->m_performedOperationsData.append(qMakePair(name, data));
- }
-
- // seek to the position of the resource collections segment info
- const qint64 resourceOffsetAndLengtSize = 2 * sizeof(qint64);
- const qint64 resourceSectionSize = resourceOffsetAndLengtSize * layout.resourceCount;
- qint64 offset = layout.endOfData - layout.indexSize - resourceSectionSize
- - resourceOffsetAndLengtSize;
- if (!file->seek(offset)) {
- throw Error(QCoreApplication::translate("BinaryContent",
- "Could not seek to read the resource collection segment info."));
- }
-
- offset = QInstaller::retrieveInt64(file.data()) + dataBlockStart;
- if (!file->seek(offset)) {
- throw Error(QCoreApplication::translate("BinaryContent", "Could not seek to start "
- "position of resource collection block."));
- }
-
- ResourceCollectionManager collectionManager;
- collectionManager.read(file, dataBlockStart);
- BinaryFormatEngineHandler::instance()->registerResources(collectionManager.collections());
-
- if (!QInstaller::isVerbose())
- return;
-
- const QList<ResourceCollection> collections = collectionManager.collections();
- qDebug() << "Number of resource collections loaded:" << collections.count();
- foreach (const ResourceCollection &collection, collections) {
- const QList<QSharedPointer<Resource> > resources = collection.resources();
- qDebug() << collection.name().data() << "loaded...";
- QStringList resourcesWithSize;
- foreach (const QSharedPointer<Resource> &resource, resources) {
- resourcesWithSize.append(QString::fromLatin1("%1 - %2")
- .arg(QString::fromUtf8(resource->name()), humanReadableSize(resource->size())));
- }
- if (!resourcesWithSize.isEmpty()) {
- qDebug() << " - " << resources.count() << "resources: "
- << qPrintable(resourcesWithSize.join(QLatin1String("; ")));
- }
- }
-}
-
-/*!
- Registers already performed operations.
-*/
-int BinaryContent::registerPerformedOperations()
-{
- if (d->m_performedOperations.count() > 0)
- return d->m_performedOperations.count();
-
- for (int i = 0; i < d->m_performedOperationsData.count(); ++i) {
- const QPair<QString, QString> opPair = d->m_performedOperationsData.at(i);
- QScopedPointer<Operation> op(KDUpdater::UpdateOperationFactory::instance().create(opPair.first));
- if (op.isNull()) {
- qWarning() << QString::fromLatin1("Failed to load unknown operation %1").arg(opPair.first);
- continue;
- }
-
- if (!op->fromXml(opPair.second)) {
- qWarning() << "Failed to load XML for operation:" << opPair.first;
- continue;
- }
- d->m_performedOperations.append(op.take());
- }
- return d->m_performedOperations.count();
-}
-
-/*!
- Returns the operations performed during installation. Returns an empty list if no operations
- are instantiated, performed or the binary is the installer application.
-*/
-OperationList BinaryContent::performedOperations() const
-{
- return d->m_performedOperations;
-}
-
-/*!
- Returns the magic marker found in the binary. Returns 0 if no marker has been found.
-*/
-qint64 BinaryContent::magicMarker() const
-{
- return d->m_magicMarker;
-}
-
-/*!
- Registers the Qt resources embedded in this binary.
-*/
-int BinaryContent::registerEmbeddedQResources()
-{
- if (d->m_resourceMappings.count() > 0)
- return d->m_resourceMappings.count();
-
- const bool hasBinaryDataFile = !d->m_binaryDataFile.isNull();
- QFile *const data = hasBinaryDataFile ? d->m_binaryDataFile.data() : d->m_appBinary.data();
- if (data != 0 && !data->isOpen() && !data->open(QIODevice::ReadOnly)) {
- throw Error(QCoreApplication::translate("BinaryContent", "Could not open binary %1: %2")
- .arg(data->fileName(), data->errorString()));
- }
-
- foreach (const Range<qint64> &i, d->m_metadataResourceSegments)
- d->m_resourceMappings.append(addResourceFromBinary(data, i));
-
- d->m_appBinary.clear();
- if (hasBinaryDataFile)
- d->m_binaryDataFile.clear();
-
- return d->m_resourceMappings.count();
-}
-
-/*!
- Registers the passed file as default resource content. If the embedded resources are already
- mapped into memory, it will replace the first with the new content.
-*/
-void BinaryContent::registerAsDefaultQResource(const QString &path)
-{
- QFile resource(path);
- bool success = resource.open(QIODevice::ReadOnly);
- if (success && (d->m_resourceMappings.count() > 0)) {
- success = QResource::unregisterResource((const uchar*) d->m_resourceMappings.first()
- .constData(), QLatin1String(":/metadata"));
- if (success)
- d->m_resourceMappings.remove(0);
- }
-
- if (success) {
- d->m_resourceMappings.prepend(addResourceFromBinary(&resource,
- Range<qint64>::fromStartAndEnd(0, resource.size())));
- } else {
- qWarning() << QString::fromLatin1("Could not register '%1' as default resource.").arg(path);
- }
-}
-
void BinaryContent::readBinaryContent(const QSharedPointer<QFile> &in,
ResourceCollection *metaResources, QList<OperationBlob> *operations,
ResourceCollectionManager *manager, qint64 *magicMarker, quint64 magicCookie)
diff --git a/src/libs/installer/binarycontent.h b/src/libs/installer/binarycontent.h
index edbf54f07..2efe3d0fc 100644
--- a/src/libs/installer/binarycontent.h
+++ b/src/libs/installer/binarycontent.h
@@ -69,6 +69,7 @@ struct BinaryLayout
class INSTALLER_EXPORT BinaryContent
{
public:
+ // the marker to distinguish what kind of binary
static const qint64 MagicInstallerMarker = 0x12023233UL;
static const qint64 MagicUninstallerMarker = 0x12023234UL;
@@ -79,24 +80,9 @@ public:
static const quint64 MagicCookie = 0xc2630a1c99d668f8LL; // binary
static const quint64 MagicCookieDat = 0xc2630a1c99d668f9LL; // data
- BinaryContent();
- ~BinaryContent();
-
- BinaryContent(const BinaryContent &rhs);
- BinaryContent &operator=(const BinaryContent &rhs);
-
- static BinaryContent readFromBinary(const QString &path);
- static BinaryContent readAndRegisterFromBinary(const QString &path);
static qint64 findMagicCookie(QFile *file, quint64 magicCookie);
static BinaryLayout binaryLayout(QFile *file, quint64 magicCookie);
- int registerPerformedOperations();
- OperationList performedOperations() const;
-
- qint64 magicMarker() const;
- int registerEmbeddedQResources();
- void registerAsDefaultQResource(const QString &path);
-
static void readBinaryContent(const QSharedPointer<QFile> &in,
ResourceCollection *metaResources,
QList<OperationBlob> *operations,
@@ -110,14 +96,6 @@ public:
const ResourceCollectionManager &manager,
qint64 magicMarker,
quint64 magicCookie);
-private:
- explicit BinaryContent(const QString &path);
- static void readBinaryData(BinaryContent &content, const QSharedPointer<QFile> &file,
- const BinaryLayout &layout);
-
-private:
- class Private;
- QSharedDataPointer<Private> d;
};
} // namespace QInstaller
diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp
index ad14a137e..6abfdb81c 100644
--- a/src/libs/installer/packagemanagercore.cpp
+++ b/src/libs/installer/packagemanagercore.cpp
@@ -749,8 +749,8 @@ PackageManagerCore::PackageManagerCore()
qRegisterMetaType<QInstaller::PackageManagerCore::WizardPage>("QInstaller::PackageManagerCore::WizardPage");
}
-PackageManagerCore::PackageManagerCore(qint64 magicmaker, const OperationList &performedOperations)
- : d(new PackageManagerCorePrivate(this, magicmaker, performedOperations))
+PackageManagerCore::PackageManagerCore(qint64 magicmaker, const QList<OperationBlob> &operations)
+ : d(new PackageManagerCorePrivate(this, magicmaker, operations))
{
qRegisterMetaType<QInstaller::PackageManagerCore::Status>("QInstaller::PackageManagerCore::Status");
qRegisterMetaType<QInstaller::PackageManagerCore::WizardPage>("QInstaller::PackageManagerCore::WizardPage");
diff --git a/src/libs/installer/packagemanagercore.h b/src/libs/installer/packagemanagercore.h
index b3c5013cc..d8bcc86a6 100644
--- a/src/libs/installer/packagemanagercore.h
+++ b/src/libs/installer/packagemanagercore.h
@@ -41,6 +41,7 @@
#ifndef PACKAGEMANAGERCORE_H
#define PACKAGEMANAGERCORE_H
+#include "binaryformat.h"
#include "repository.h"
#include "qinstallerglobal.h"
@@ -72,8 +73,8 @@ class INSTALLER_EXPORT PackageManagerCore : public QObject
Q_PROPERTY(int status READ status NOTIFY statusChanged)
public:
- explicit PackageManagerCore();
- explicit PackageManagerCore(qint64 magicmaker, const OperationList &oldOperations = OperationList());
+ PackageManagerCore();
+ PackageManagerCore(qint64 magicmaker, const QList<OperationBlob> &ops);
~PackageManagerCore();
// status
diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp
index b2d7d7d83..c9cd458a6 100644
--- a/src/libs/installer/packagemanagercore_p.cpp
+++ b/src/libs/installer/packagemanagercore_p.cpp
@@ -203,7 +203,7 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core)
}
PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core, qint64 magicInstallerMaker,
- const OperationList &performedOperations)
+ const QList<OperationBlob> &performedOperations)
: m_updateFinder(0)
, m_updaterApplication(new DummyConfigurationInterface)
, m_status(PackageManagerCore::Unfinished)
@@ -212,7 +212,6 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core, q
, m_launchedAsRoot(AdminAuthorization::hasAdminRights())
, m_completeUninstall(false)
, m_needToWriteMaintenanceTool(false)
- , m_performedOperationsOld(performedOperations)
, m_dependsOnLocalInstallerBinary(false)
, m_core(core)
, m_updates(false)
@@ -228,6 +227,22 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core, q
, m_guiObject(0)
, m_remoteFileEngineHandler(new RemoteFileEngineHandler)
{
+ foreach (const OperationBlob &operation, performedOperations) {
+ QScopedPointer<QInstaller::Operation> op(KDUpdater::UpdateOperationFactory::instance()
+ .create(operation.name));
+ if (op.isNull()) {
+ qWarning() << QString::fromLatin1("Failed to load unknown operation %1")
+ .arg(operation.name);
+ continue;
+ }
+
+ if (!op->fromXml(operation.xml)) {
+ qWarning() << "Failed to load XML for operation:" << operation.name;
+ continue;
+ }
+ m_performedOperationsOld.append(op.take());
+ }
+
// Creates and initializes a remote client, makes us get admin rights for QFile, QSettings
// and QProcess operations. Init needs to called before we can get the real authorization key.
int port = 30000 + qrand() % 1000;
diff --git a/src/libs/installer/packagemanagercore_p.h b/src/libs/installer/packagemanagercore_p.h
index 3b2655276..29da8cb54 100644
--- a/src/libs/installer/packagemanagercore_p.h
+++ b/src/libs/installer/packagemanagercore_p.h
@@ -106,7 +106,7 @@ public:
explicit PackageManagerCorePrivate(PackageManagerCore *core);
explicit PackageManagerCorePrivate(PackageManagerCore *core, qint64 magicInstallerMaker,
- const OperationList &performedOperations);
+ const QList<OperationBlob> &performedOperations);
~PackageManagerCorePrivate();
static bool isProcessRunning(const QString &name, const QList<ProcessInfo> &processes);
diff --git a/src/libs/installer/productkeycheck.cpp b/src/libs/installer/productkeycheck.cpp
index 232dbb719..46a568625 100644
--- a/src/libs/installer/productkeycheck.cpp
+++ b/src/libs/installer/productkeycheck.cpp
@@ -30,6 +30,8 @@
#include "productkeycheck.h"
#include "packagemanagercore.h"
+namespace QInstaller {
+
class ProductKeyCheckPrivate
{
};
@@ -91,3 +93,5 @@ QList<int> ProductKeyCheck::registeredPages() const
{
return QList<int>();
}
+
+} // namespace QInstaller
diff --git a/src/libs/installer/productkeycheck.h b/src/libs/installer/productkeycheck.h
index 3df747f37..02e8a76a5 100644
--- a/src/libs/installer/productkeycheck.h
+++ b/src/libs/installer/productkeycheck.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (c) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (c) 2013-2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Installer Framework
@@ -35,18 +35,18 @@
#include <QString>
namespace QInstaller{
- class PackageManagerCore;
- class Repository;
-}
-
+class PackageManagerCore;
class ProductKeyCheckPrivate;
+class Repository;
class INSTALLER_EXPORT ProductKeyCheck
{
+ Q_DISABLE_COPY(ProductKeyCheck)
+
public:
~ProductKeyCheck();
static ProductKeyCheck *instance();
- void init(QInstaller::PackageManagerCore *core);
+ void init(PackageManagerCore *core);
// was validLicense
bool hasValidKey();
@@ -67,7 +67,8 @@ public:
private:
ProductKeyCheck();
ProductKeyCheckPrivate *const d;
- Q_DISABLE_COPY(ProductKeyCheck)
};
+} // namespace QInstaller
+
#endif // PRODUCTKEYCHECK_H
diff --git a/src/sdk/installerbase.cpp b/src/sdk/installerbase.cpp
index 73831bed1..4d13339cd 100644
--- a/src/sdk/installerbase.cpp
+++ b/src/sdk/installerbase.cpp
@@ -39,417 +39,263 @@
**
**************************************************************************/
-#include "console.h"
+#include "constants.h"
+#include "commandlineparser.h"
+#include "installerbase.h"
#include "installerbasecommons.h"
-#include "sdkapp.h"
#include "tabcontroller.h"
-#include "updatechecker.h"
-#include <binarycontent.h>
+#include <binaryformatenginehandler.h>
+#include <copydirectoryoperation.h>
#include <errors.h>
#include <init.h>
+#include <kdupdaterupdateoperations.h>
#include <messageboxhandler.h>
+#include <packagemanagercore.h>
+#include <qprocesswrapper.h>
#include <productkeycheck.h>
-#include <remoteserver.h>
#include <settings.h>
#include <utils.h>
-#include <kdselfrestarter.h>
#include <kdrunoncechecker.h>
#include <kdupdaterfiledownloaderfactory.h>
-#include <QCommandLineParser>
#include <QDirIterator>
-#include <QNetworkProxyFactory>
+#include <QTemporaryFile>
#include <QTranslator>
#include <iostream>
-#define QUOTE_(x) #x
-#define QUOTE(x) QUOTE_(x)
-#define VERSION "IFW Version: \"" QUOTE(IFW_VERSION) "\""
-#define BUILDDATE "Build date: " QUOTE(__DATE__)
-#define SHA "Installer Framework SHA1: \"" QUOTE(_GIT_SHA1_) "\""
-static const char PLACEHOLDER[32] = "MY_InstallerCreateDateTime_MY";
-
-using namespace QInstaller;
-
-static QStringList repositories(const QString &list)
+InstallerBase::InstallerBase(int &argc, char *argv[])
+ : SDKApp<QApplication>(argc, argv)
+ , m_core(0)
{
- const QStringList items = list.split(QLatin1Char(','), QString::SkipEmptyParts);
- foreach (const QString &item, items)
- qDebug() << "Adding custom repository:" << item;
- return items;
+ QInstaller::init(); // register custom operations
}
-// -- main
-
-int main(int argc, char *argv[])
+InstallerBase::~InstallerBase()
{
-// increase maximum numbers of file descriptors
-#if defined (Q_OS_OSX)
- struct rlimit rl;
- getrlimit(RLIMIT_NOFILE, &rl);
- rl.rlim_cur = qMin((rlim_t)OPEN_MAX, rl.rlim_max);
- setrlimit(RLIMIT_NOFILE, &rl);
-#endif
-
- qsrand(QDateTime::currentDateTime().toTime_t());
-
- QCommandLineParser parser;
- QCommandLineOption help = parser.addHelpOption();
-
- QCommandLineOption version(QLatin1String("version"),
- QLatin1String("Displays version information."));
- parser.addOption(version);
-
- QCommandLineOption verbose(QStringList() << QLatin1String("v") << QLatin1String("verbose"),
- QLatin1String("Verbose mode. Prints out more information."));
- parser.addOption(verbose);
-
- QCommandLineOption proxy(QLatin1String("proxy"),
- QLatin1String("Use system proxy on Windows and OS X. This option has no effect on Linux."));
- parser.addOption(proxy);
-
- QCommandLineOption script(QLatin1String("script"),
- QLatin1String("Execute the script given as argument."), QLatin1String("file"));
- parser.addOption(script);
-
- QCommandLineOption checkUpdates(QLatin1String("checkupdates"),
- QLatin1String("Check for updates and return an XML description."));
- parser.addOption(checkUpdates);
-
- QCommandLineOption updater(QLatin1String("updater"),
- QLatin1String("Start application in updater mode."));
- parser.addOption(updater);
-
- QCommandLineOption pkgManager(QLatin1String("manage-packages"),
- QLatin1String("Start application in package manager mode."));
- parser.addOption(pkgManager);
-
- QCommandLineOption noForce(QLatin1String("no-force-installations"),
- QLatin1String("Allow deselection of components that are marked as forced."));
- parser.addOption(noForce);
-
- QCommandLineOption showVirtuals(QLatin1String("show-virtual-components"),
- QLatin1String("Show virtual components in installer and package manager."));
- parser.addOption(showVirtuals);
-
- QCommandLineOption offlineRepo(QLatin1String("create-offline-repository"), QLatin1String(
- "Create a local repository inside the installation directory. This option has no effect "
- "on online installer's"));
- parser.addOption(offlineRepo);
-
- QCommandLineOption addRepo(QLatin1String("addRepository"),
- QLatin1String("Add a local or remote repository to the list of user defined repositories."),
- QLatin1String("URI,..."));
- parser.addOption(addRepo);
-
- QCommandLineOption addTmpRepo(QLatin1String("addTempRepository"), QLatin1String(
- "Add a local or remote repository to the list of temporary available repositories."),
- QLatin1String("URI,..."));
- parser.addOption(addTmpRepo);
-
- QCommandLineOption setTmpRepo(QLatin1String("setTempRepository"),
- QLatin1String("Set a local or remote repository as temporary repository, it is the only "
- "one used during fetch.\nNote: URI must be prefixed with the protocol, i.e. file:///, "
- "https://, http:// or ftp://."), QLatin1String("URI,..."));
- parser.addOption(setTmpRepo);
-
- QCommandLineOption startServer(QLatin1String("startserver"), QLatin1String("Starts the "
- "application as headless process waiting for commands to execute."),
- QLatin1String("port,key"));
- parser.addOption(startServer);
-
- parser.addPositionalArgument(QLatin1String("Key=Value"),
- QLatin1String("Key Value pair to be set."));
-
- // We need to start either a command line application or a GUI application. Since we
- // fail doing so at least on Linux while parsing the argument using a core application
- // object and later starting the GUI application, we now parse the arguments first.
- parser.parse(QInstaller::parseCommandLineArgs(argc, argv));
-
- QStringList mutually;
- if (parser.isSet(checkUpdates))
- mutually << checkUpdates.names();
- if (parser.isSet(updater))
- mutually << updater.names();
- if (parser.isSet(pkgManager))
- mutually << pkgManager.names();
-
- if (parser.isSet(help) || parser.isSet(version) || (mutually.count() > 1)) {
- Console c;
- QCoreApplication app(argc, argv);
-
- if (parser.isSet(version)) {
- std::cout << VERSION << std::endl << BUILDDATE << std::endl << SHA << std::endl;
- const QDateTime dateTime = QDateTime::fromString(QLatin1String(PLACEHOLDER),
- QLatin1String("yyyy-MM-dd - HH:mm:ss"));
- if (dateTime.isValid())
- std::cout << "Installer creation time: " << PLACEHOLDER << std::endl;
- return EXIT_SUCCESS;
- }
-
- if (mutually.count() > 1) {
- std::cerr << qPrintable(QString::fromLatin1("The following options are mutually "
- "exclusive: %1.").arg(mutually.join(QLatin1String(", ")))) << std::endl;
- }
+ delete m_core;
+}
- std::cout << qPrintable(parser.helpText()) << std::endl;
- return parser.isSet(help) ? EXIT_SUCCESS : EXIT_FAILURE;
+int InstallerBase::run()
+{
+ KDRunOnceChecker runCheck(QLatin1String("lockmyApp1234865.lock"));
+ if (runCheck.isRunning(KDRunOnceChecker::ProcessList)
+ || runCheck.isRunning(KDRunOnceChecker::Lockfile)) {
+ QInstaller::MessageBoxHandler::information(0, QLatin1String("AlreadyRunning"),
+ QString::fromLatin1("Waiting for %1").arg(qAppName()),
+ QString::fromLatin1("Another %1 instance is already running. Wait "
+ "until it finishes, close it, or restart your system.").arg(qAppName()));
+ return EXIT_FAILURE;
}
- if (parser.isSet(startServer)) {
- const QString argument = parser.value(startServer);
- const QString port = argument.section(QLatin1Char(','), 0, 0);
- const QString key = argument.section(QLatin1Char(','), 1, 1);
-
- QStringList missing;
- if (port.isEmpty())
- missing << QLatin1String("Port");
- if (key.isEmpty())
- missing << QLatin1String("Key");
-
- SDKApp<QCoreApplication> app(argc, argv);
- if (missing.count()) {
- Console c;
- std::cerr << qPrintable(QString::fromLatin1("Missing argument(s) for option "
- "'startserver': %2").arg(missing.join(QLatin1String(", ")))) << std::endl;
- std::cout << qPrintable(parser.helpText()) << std::endl;
- return EXIT_FAILURE;
- }
-
- RemoteServer *server = new RemoteServer;
- QObject::connect(server, SIGNAL(destroyed()), &app, SLOT(quit()));
- server->init(port.toInt(), QHostAddress::LocalHost, Protocol::Mode::Release);
- server->setAuthorizationKey(key);
- server->start();
- return app.exec();
+ QString fileName = datFile(binaryFile());
+ quint64 cookie = QInstaller::BinaryContent::MagicCookieDat;
+ if (fileName.isEmpty()) {
+ fileName = binaryFile();
+ cookie = QInstaller::BinaryContent::MagicCookie;
}
- try {
- QScopedPointer<Console> console;
- if (parser.isSet(verbose)) {
- console.reset(new Console);
- QInstaller::setVerbose(parser.isSet(verbose));
- }
-
- // On Windows we need the console window from above, we are a GUI application.
- const QStringList unknownOptionNames = parser.unknownOptionNames();
- if (!unknownOptionNames.isEmpty()) {
- const QString options = unknownOptionNames.join(QLatin1String(", "));
- std::cerr << "Unknown option: " << qPrintable(options) << std::endl;
- }
+ QSharedPointer<QFile> binary(new QFile(fileName));
+ QInstaller::openForRead(binary.data());
+
+ qint64 magicMarker;
+ QInstaller::ResourceCollection resources;
+ QInstaller::ResourceCollectionManager manager;
+ QList<QInstaller::OperationBlob> oldOperations;
+ QInstaller::BinaryContent::readBinaryContent(binary, &resources, &oldOperations, &manager,
+ &magicMarker, cookie);
+
+ if (QInstaller::isVerbose()) {
+ using namespace std;
+ cout << "Language:" << QLocale().uiLanguages().value(0,
+ QLatin1String("No UI language set")).constData() << endl;
+ cout << "Arguments: " << arguments().join(QLatin1String(", ")).constData() << endl;
+ }
- if (parser.isSet(proxy)) {
- // Make sure we honor the system's proxy settings
-#if defined(Q_OS_UNIX) && !defined(Q_OS_OSX)
- QUrl proxyUrl(QString::fromLatin1(qgetenv("http_proxy")));
- if (proxyUrl.isValid()) {
- QNetworkProxy proxy(QNetworkProxy::HttpProxy, proxyUrl.host(), proxyUrl.port(),
- proxyUrl.userName(), proxyUrl.password());
- QNetworkProxy::setApplicationProxy(proxy);
- }
-#else
- QNetworkProxyFactory::setUseSystemConfiguration(true);
-#endif
- }
+ registerMetaResources(resources); // the base class will unregister the resources
+ QInstaller::BinaryFormatEngineHandler::instance()->registerResources(manager.collections());
- if (parser.isSet(checkUpdates))
- return UpdateChecker().check(argc, argv);
+ if (QInstaller::isVerbose())
+ dumpResourceTree();
- SDKApp<QApplication> app(argc, argv);
- KDRunOnceChecker runCheck(QLatin1String("lockmyApp1234865.lock"));
+ // instantiate the installer we are actually going to use
+ m_core = new QInstaller::PackageManagerCore(magicMarker, oldOperations);
+ QInstaller::ProductKeyCheck::instance()->init(m_core);
- if (runCheck.isRunning(KDRunOnceChecker::ProcessList)
- || runCheck.isRunning(KDRunOnceChecker::Lockfile)) {
- QInstaller::MessageBoxHandler::information(0, QLatin1String("AlreadyRunning"),
- QString::fromLatin1("Waiting for %1").arg(qAppName()),
- QString::fromLatin1("Another %1 instance is already running. Wait "
- "until it finishes, close it, or restart your system.").arg(qAppName()));
- return EXIT_FAILURE;
- }
+ // We can close the binary file if we are an online installer or no installer at all, cause no
+ // embedded archives exist inside the component index. Keeps the .dat file unlocked on Windows.
+ if ((!m_core->isInstaller()) || (!m_core->isOfflineOnly()))
+ binary->close();
- const KDSelfRestarter restarter(argc, argv);
- QInstaller::init(); // register custom operations
+ CommandLineParser parser;
+ parser.parse(arguments());
- if (QInstaller::isVerbose()) {
- qDebug() << VERSION;
- qDebug() << "Arguments:" << app.arguments();
- qDebug() << "Language: " << QLocale().uiLanguages().value(0,
- QLatin1String("No UI language set"));
- }
+ QString controlScript;
+ if (parser.isSet(QLatin1String(CommandLineOptions::Script))) {
+ controlScript = parser.value(QLatin1String(CommandLineOptions::Script));
+ if (!QFileInfo(controlScript).exists())
+ throw QInstaller::Error(QLatin1String("Script file does not exist."));
+ }
- BinaryContent content = BinaryContent::readAndRegisterFromBinary(app.binaryFile());
+ if (parser.isSet(QLatin1String(CommandLineOptions::Proxy))) {
+ m_core->settings().setProxyType(QInstaller::Settings::SystemProxy);
+ KDUpdater::FileDownloaderFactory::instance().setProxyFactory(m_core->proxyFactory());
+ }
- // instantiate the installer we are actually going to use
- PackageManagerCore core(content.magicMarker(), content.performedOperations());
- ProductKeyCheck::instance()->init(&core);
+ if (parser.isSet(QLatin1String(CommandLineOptions::ShowVirtualComponents))) {
+ QFont f;
+ f.setItalic(true);
+ QInstaller::PackageManagerCore::setVirtualComponentsFont(f);
+ QInstaller::PackageManagerCore::setVirtualComponentsVisible(true);
+ }
- QString controlScript;
- if (parser.isSet(script)) {
- controlScript = parser.value(script);
- if (!QFileInfo(controlScript).exists())
- throw Error(QLatin1String("Script file does not exist."));
- }
+ if (parser.isSet(QLatin1String(CommandLineOptions::Updater))) {
+ if (m_core->isInstaller())
+ throw QInstaller::Error(QLatin1String("Cannot start installer binary as updater."));
+ m_core->setUpdater();
+ }
- if (parser.isSet(proxy)) {
- core.settings().setProxyType(QInstaller::Settings::SystemProxy);
- KDUpdater::FileDownloaderFactory::instance().setProxyFactory(core.proxyFactory());
- }
+ if (parser.isSet(QLatin1String(CommandLineOptions::ManagePackages))) {
+ if (m_core->isInstaller())
+ throw QInstaller::Error(QLatin1String("Cannot start installer binary as package manager."));
+ m_core->setPackageManager();
+ }
- if (parser.isSet(showVirtuals)) {
- QFont f;
- f.setItalic(true);
- PackageManagerCore::setVirtualComponentsFont(f);
- PackageManagerCore::setVirtualComponentsVisible(true);
- }
+ if (parser.isSet(QLatin1String(CommandLineOptions::AddRepository))) {
+ const QStringList repoList = repositories(parser
+ .value(QLatin1String(CommandLineOptions::AddRepository)));
+ if (repoList.isEmpty())
+ throw QInstaller::Error(QLatin1String("Empty repository list for option 'addRepository'."));
+ m_core->addUserRepositories(repoList);
+ }
- if (parser.isSet(updater)) {
- if (core.isInstaller())
- throw Error(QLatin1String("Cannot start installer binary as updater."));
- core.setUpdater();
- }
+ if (parser.isSet(QLatin1String(CommandLineOptions::AddTmpRepository))) {
+ const QStringList repoList = repositories(parser
+ .value(QLatin1String(CommandLineOptions::AddTmpRepository)));
+ if (repoList.isEmpty())
+ throw QInstaller::Error(QLatin1String("Empty repository list for option 'addTempRepository'."));
+ m_core->setTemporaryRepositories(repoList, false);
+ }
- if (parser.isSet(pkgManager)) {
- if (core.isInstaller())
- throw Error(QLatin1String("Cannot start installer binary as package manager."));
- core.setPackageManager();
- }
+ if (parser.isSet(QLatin1String(CommandLineOptions::SetTmpRepository))) {
+ const QStringList repoList = repositories(parser
+ .value(QLatin1String(CommandLineOptions::SetTmpRepository)));
+ if (repoList.isEmpty())
+ throw QInstaller::Error(QLatin1String("Empty repository list for option 'setTempRepository'."));
+ m_core->setTemporaryRepositories(repoList, true);
+ }
- if (parser.isSet(addRepo)) {
- const QStringList repoList = repositories(parser.value(addRepo));
- if (repoList.isEmpty())
- throw Error(QLatin1String("Empty repository list for option 'addRepository'."));
- core.addUserRepositories(repoList);
+ QInstaller::PackageManagerCore::setNoForceInstallation(parser
+ .isSet(QLatin1String(CommandLineOptions::NoForceInstallation)));
+ QInstaller::PackageManagerCore::setCreateLocalRepositoryFromBinary(parser
+ .isSet(QLatin1String(CommandLineOptions::CreateOfflineRepository)));
+
+ QHash<QString, QString> params;
+ const QStringList positionalArguments = parser.positionalArguments();
+ foreach (const QString &argument, positionalArguments) {
+ if (argument.contains(QLatin1Char('='))) {
+ const QString name = argument.section(QLatin1Char('='), 0, 0);
+ const QString value = argument.section(QLatin1Char('='), 1, 1);
+ params.insert(name, value);
+ m_core->setValue(name, value);
}
+ }
- if (parser.isSet(addTmpRepo)) {
- const QStringList repoList = repositories(parser.value(addTmpRepo));
- if (repoList.isEmpty())
- throw Error(QLatin1String("Empty repository list for option 'addTempRepository'."));
- core.setTemporaryRepositories(repoList, false);
+ const QString directory = QLatin1String(":/translations");
+ const QStringList translations = m_core->settings().translations();
+
+ // install the default Qt translator
+ QScopedPointer<QTranslator> translator(new QTranslator(QCoreApplication::instance()));
+ foreach (const QLocale locale, QLocale().uiLanguages()) {
+ // As there is no qt_en.qm, we simply end the search when the next
+ // preferred language is English.
+ if (locale.language() == QLocale::English)
+ break;
+ if (translator->load(locale, QLatin1String("qt"), QString::fromLatin1("_"), directory)) {
+ QCoreApplication::instance()->installTranslator(translator.take());
+ break;
}
+ }
- if (parser.isSet(setTmpRepo)) {
- const QStringList repoList = repositories(parser.value(setTmpRepo));
- if (repoList.isEmpty())
- throw Error(QLatin1String("Empty repository list for option 'setTempRepository'."));
- core.setTemporaryRepositories(repoList, true);
- }
+ translator.reset(new QTranslator(QCoreApplication::instance()));
+ // install English translation as fallback so that correct license button text is used
+ if (translator->load(QLatin1String("en_us"), directory))
+ QCoreApplication::instance()->installTranslator(translator.take());
- PackageManagerCore::setNoForceInstallation(parser.isSet(noForce));
- PackageManagerCore::setCreateLocalRepositoryFromBinary(parser.isSet(offlineRepo));
-
- QHash<QString, QString> params;
- const QStringList positionalArguments = parser.positionalArguments();
- foreach (const QString &argument, positionalArguments) {
- if (argument.contains(QLatin1Char('='))) {
- const QString name = argument.section(QLatin1Char('='), 0, 0);
- const QString value = argument.section(QLatin1Char('='), 1, 1);
- params.insert(name, value);
- core.setValue(name, value);
+ if (translations.isEmpty()) {
+ translator.reset(new QTranslator(QCoreApplication::instance()));
+ foreach (const QLocale locale, QLocale().uiLanguages()) {
+ if (translator->load(locale, QLatin1String(""), QLatin1String(""), directory)) {
+ QCoreApplication::instance()->installTranslator(translator.take());
+ break;
}
}
-
- // this needs to happen after we parse the arguments, but before we use the actual resources
- const QString newDefaultResource = core.value(QString::fromLatin1("DefaultResourceReplacement"));
- if (!newDefaultResource.isEmpty())
- content.registerAsDefaultQResource(newDefaultResource);
-
- if (QInstaller::isVerbose()) {
- qDebug() << "Resource tree:";
- QDirIterator it(QLatin1String(":/"), QDir::NoDotAndDotDot | QDir::AllEntries | QDir::Hidden,
- QDirIterator::Subdirectories);
- while (it.hasNext()) {
- const QString path = it.next();
- if (path.startsWith(QLatin1String(":/trolltech"))
- || path.startsWith(QLatin1String(":/qt-project.org"))) {
- continue;
- }
- qDebug() << " " << path.toUtf8().constData();
- }
+ } else {
+ foreach (const QString &translation, translations) {
+ translator.reset(new QTranslator(QCoreApplication::instance()));
+ if (translator->load(translation, QLatin1String(":/translations")))
+ QCoreApplication::instance()->installTranslator(translator.take());
}
+ }
- const QString directory = QLatin1String(":/translations");
- const QStringList translations = core.settings().translations();
+ //create the wizard GUI
+ TabController controller(0);
+ controller.setManager(m_core);
+ controller.setManagerParams(params);
+ controller.setControlScript(controlScript);
- // install the default Qt translator
- QScopedPointer<QTranslator> translator(new QTranslator(&app));
- foreach (const QLocale locale, QLocale().uiLanguages()) {
- // As there is no qt_en.qm, we simply end the search when the next
- // preferred language is English.
- if (locale.language() == QLocale::English)
- break;
- if (translator->load(locale, QLatin1String("qt"), QString::fromLatin1("_"), directory)) {
- app.installTranslator(translator.take());
- break;
- }
- }
+ if (m_core->isInstaller())
+ controller.setGui(new InstallerGui(m_core));
+ else
+ controller.setGui(new MaintenanceGui(m_core));
- translator.reset(new QTranslator(&app));
- // install English translation as fallback so that correct license button text is used
- if (translator->load(QLatin1String("en_us"), directory))
- app.installTranslator(translator.take());
-
- if (translations.isEmpty()) {
- translator.reset(new QTranslator(&app));
- foreach (const QLocale locale, QLocale().uiLanguages()) {
- if (translator->load(locale, QLatin1String(""), QLatin1String(""), directory)) {
- app.installTranslator(translator.take());
- break;
- }
- }
- } else {
- foreach (const QString &translation, translations) {
- translator.reset(new QTranslator(&app));
- if (translator->load(translation, QLatin1String(":/translations")))
- app.installTranslator(translator.take());
- }
- }
+ QInstaller::PackageManagerCore::Status status =
+ QInstaller::PackageManagerCore::Status(controller.init());
+ if (status != QInstaller::PackageManagerCore::Success)
+ return status;
- //create the wizard GUI
- TabController controller(0);
- controller.setManager(&core);
- controller.setManagerParams(params);
- controller.setControlScript(controlScript);
+ const int result = QCoreApplication::instance()->exec();
+ if (result != 0)
+ return result;
- if (core.isInstaller()) {
- controller.setGui(new InstallerGui(&core));
- } else {
- controller.setGui(new MaintenanceGui(&core));
- }
+ if (m_core->finishedWithSuccess())
+ return QInstaller::PackageManagerCore::Success;
- PackageManagerCore::Status status = PackageManagerCore::Status(controller.init());
- if (status != PackageManagerCore::Success)
+ status = m_core->status();
+ switch (status) {
+ case QInstaller::PackageManagerCore::Success:
return status;
- const int result = app.exec();
- if (result != 0)
- return result;
+ case QInstaller::PackageManagerCore::Canceled:
+ return status;
- if (core.finishedWithSuccess())
- return PackageManagerCore::Success;
+ default:
+ break;
+ }
+ return QInstaller::PackageManagerCore::Failure;
+}
- status = core.status();
- switch (status) {
- case PackageManagerCore::Success:
- return status;
- case PackageManagerCore::Canceled:
- return status;
+// -- private
- default:
- break;
- }
- return PackageManagerCore::Failure;
- } catch(const Error &e) {
- std::cerr << qPrintable(e.message()) << std::endl;
- } catch (const std::exception &e) {
- std::cerr << e.what() << std::endl;
- } catch(...) {
- std::cerr << "Unknown error, aborting." << std::endl;
+void InstallerBase::dumpResourceTree() const
+{
+ std::cout << "Resource tree:" << std::endl;
+ QDirIterator it(QLatin1String(":/"), QDir::NoDotAndDotDot | QDir::AllEntries | QDir::Hidden,
+ QDirIterator::Subdirectories);
+ while (it.hasNext()) {
+ if (it.next().startsWith(QLatin1String(":/qt-project.org")))
+ continue;
+ std::cout << " " << it.filePath().constData() << std::endl;
}
+}
- return PackageManagerCore::Failure;
+QStringList InstallerBase::repositories(const QString &list) const
+{
+ const QStringList items = list.split(QLatin1Char(','), QString::SkipEmptyParts);
+ foreach (const QString &item, items)
+ std::cout << "Adding custom repository:" << item.constData() << std::endl;
+ return items;
}
diff --git a/src/sdk/installerbase.h b/src/sdk/installerbase.h
new file mode 100644
index 000000000..b241d9988
--- /dev/null
+++ b/src/sdk/installerbase.h
@@ -0,0 +1,70 @@
+/**************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#ifndef INSTALLERBASE_H
+#define INSTALLERBASE_H
+
+#include "sdkapp.h"
+
+namespace QInstaller {
+ class PackageManagerCore;
+}
+
+class InstallerBase : public SDKApp<QApplication>
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(InstallerBase)
+
+public:
+ InstallerBase(int &argc, char *argv[]);
+ ~InstallerBase();
+
+ int run();
+
+private:
+ void dumpResourceTree() const;
+ QStringList repositories(const QString &list) const;
+
+private:
+ QInstaller::PackageManagerCore *m_core;
+};
+
+#endif // INSTALLERBASE_H
diff --git a/src/sdk/main.cpp b/src/sdk/main.cpp
new file mode 100644
index 000000000..5dc32b3bc
--- /dev/null
+++ b/src/sdk/main.cpp
@@ -0,0 +1,193 @@
+/**************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#include "console.h"
+#include "constants.h"
+#include "commandlineparser.h"
+#include "installerbase.h"
+#include "sdkapp.h"
+#include "updatechecker.h"
+
+#include <errors.h>
+#include <kdselfrestarter.h>
+#include <remoteserver.h>
+#include <utils.h>
+
+#include <QCommandLineParser>
+#include <QDateTime>
+#include <QHostAddress>
+#include <QNetworkProxyFactory>
+
+#include <iostream>
+
+#define QUOTE_(x) #x
+#define QUOTE(x) QUOTE_(x)
+#define VERSION "IFW Version: \"" QUOTE(IFW_VERSION) "\""
+#define BUILDDATE "Build date: " QUOTE(__DATE__)
+#define SHA "Installer Framework SHA1: \"" QUOTE(_GIT_SHA1_) "\""
+static const char PLACEHOLDER[32] = "MY_InstallerCreateDateTime_MY";
+
+int main(int argc, char *argv[])
+{
+ // increase maximum numbers of file descriptors
+#if defined (Q_OS_OSX)
+ struct rlimit rl;
+ getrlimit(RLIMIT_NOFILE, &rl);
+ rl.rlim_cur = qMin((rlim_t) OPEN_MAX, rl.rlim_max);
+ setrlimit(RLIMIT_NOFILE, &rl);
+#endif
+
+ qsrand(QDateTime::currentDateTime().toTime_t());
+
+ // We need to start either a command line application or a GUI application. Since we
+ // fail doing so at least on Linux while parsing the argument using a core application
+ // object and later starting the GUI application, we now parse the arguments first.
+ CommandLineParser parser;
+ parser.parse(QInstaller::parseCommandLineArgs(argc, argv));
+
+ QStringList mutually;
+ if (parser.isSet(QLatin1String(CommandLineOptions::CheckUpdates)))
+ mutually << QLatin1String(CommandLineOptions::CheckUpdates);
+ if (parser.isSet(QLatin1String(CommandLineOptions::Updater)))
+ mutually << QLatin1String(CommandLineOptions::Updater);
+ if (parser.isSet(QLatin1String(CommandLineOptions::ManagePackages)))
+ mutually << QLatin1String(CommandLineOptions::ManagePackages);
+
+ const bool help = parser.isSet(QLatin1String(CommandLineOptions::HelpShort))
+ || parser.isSet(QLatin1String(CommandLineOptions::HelpLong));
+ if (help || parser.isSet(QLatin1String(CommandLineOptions::Version)) || mutually.count()) {
+ Console c;
+ QCoreApplication app(argc, argv);
+
+ if (parser.isSet(QLatin1String(CommandLineOptions::Version))) {
+ std::cout << VERSION << std::endl << BUILDDATE << std::endl << SHA << std::endl;
+ const QDateTime dateTime = QDateTime::fromString(QLatin1String(PLACEHOLDER),
+ QLatin1String("yyyy-MM-dd - HH:mm:ss"));
+ if (dateTime.isValid())
+ std::cout << "Installer creation time: " << PLACEHOLDER << std::endl;
+ return EXIT_SUCCESS;
+ }
+
+ if (mutually.count() > 1) {
+ std::cerr << qPrintable(QString::fromLatin1("The following options are mutually "
+ "exclusive: %1.").arg(mutually.join(QLatin1String(", ")))) << std::endl;
+ }
+
+ std::cout << qPrintable(parser.helpText()) << std::endl;
+ return help ? EXIT_SUCCESS : EXIT_FAILURE;
+ }
+
+ if (parser.isSet(QLatin1String(CommandLineOptions::StartServer))) {
+ const QString argument = parser.value(QLatin1String(CommandLineOptions::StartServer));
+ const QString port = argument.section(QLatin1Char(','), 0, 0);
+ const QString key = argument.section(QLatin1Char(','), 1, 1);
+
+ QStringList missing;
+ if (port.isEmpty())
+ missing << QLatin1String("Port");
+ if (key.isEmpty())
+ missing << QLatin1String("Key");
+
+ SDKApp<QCoreApplication> app(argc, argv);
+ if (missing.count()) {
+ Console c;
+ std::cerr << qPrintable(QString::fromLatin1("Missing argument(s) for option "
+ "'startserver': %2").arg(missing.join(QLatin1String(", ")))) << std::endl;
+ std::cout << qPrintable(parser.helpText()) << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ QInstaller::RemoteServer *server = new QInstaller::RemoteServer;
+ QObject::connect(server, SIGNAL(destroyed()), &app, SLOT(quit()));
+ server->init(port.toInt(), QHostAddress::LocalHost, QInstaller::Protocol::Mode::Release);
+ server->setAuthorizationKey(key);
+ server->start();
+ return app.exec();
+ }
+
+ try {
+ QScopedPointer<Console> console;
+ if (parser.isSet(QLatin1String(CommandLineOptions::VerboseShort))
+ || parser.isSet(QLatin1String(CommandLineOptions::VerboseLong))) {
+ console.reset(new Console);
+ QInstaller::setVerbose(true);
+ }
+
+ // On Windows we need the console window from above, we are a GUI application.
+ const QStringList unknownOptionNames = parser.unknownOptionNames();
+ if (!unknownOptionNames.isEmpty()) {
+ const QString options = unknownOptionNames.join(QLatin1String(", "));
+ std::cerr << "Unknown option: " << qPrintable(options) << std::endl;
+ }
+
+ if (parser.isSet(QLatin1String(CommandLineOptions::Proxy))) {
+ // Make sure we honor the system's proxy settings
+#if defined(Q_OS_UNIX) && !defined(Q_OS_OSX)
+ QUrl proxyUrl(QString::fromLatin1(qgetenv("http_proxy")));
+ if (proxyUrl.isValid()) {
+ QNetworkProxy proxy(QNetworkProxy::HttpProxy, proxyUrl.host(), proxyUrl.port(),
+ proxyUrl.userName(), proxyUrl.password());
+ QNetworkProxy::setApplicationProxy(proxy);
+ }
+#else
+ QNetworkProxyFactory::setUseSystemConfiguration(true);
+#endif
+ }
+
+ if (parser.isSet(QLatin1String(CommandLineOptions::CheckUpdates)))
+ return UpdateChecker(argc, argv).check();
+
+ if (QInstaller::isVerbose())
+ std::cout << VERSION << std::endl << BUILDDATE << std::endl << SHA << std::endl;
+
+ const KDSelfRestarter restarter(argc, argv);
+ return InstallerBase(argc, argv).run();
+
+ } catch (const QInstaller::Error &e) {
+ std::cerr << qPrintable(e.message()) << std::endl;
+ } catch (const std::exception &e) {
+ std::cerr << e.what() << std::endl;
+ } catch (...) {
+ std::cerr << "Unknown exception caught." << std::endl;
+ }
+
+ return EXIT_FAILURE;
+}
diff --git a/src/sdk/sdk.pro b/src/sdk/sdk.pro
index 25aed1b1a..c13576518 100644
--- a/src/sdk/sdk.pro
+++ b/src/sdk/sdk.pro
@@ -112,13 +112,19 @@ HEADERS += \
settingsdialog.h \
console.h \
sdkapp.h \
- updatechecker.h
-
-SOURCES = installerbase.cpp \
+ updatechecker.h \
+ installerbase.h \
+ constants.h \
+ commandlineparser.h
+
+SOURCES = \
+ main.cpp \
+ installerbase.cpp \
tabcontroller.cpp \
installerbasecommons.cpp \
settingsdialog.cpp \
- updatechecker.cpp
+ updatechecker.cpp \
+ commandlineparser.cpp
win32 {
# Force to overwrite the default manifest file with our own extended version.
diff --git a/src/sdk/sdkapp.h b/src/sdk/sdkapp.h
index f0095e3bf..a00e2d0e8 100644
--- a/src/sdk/sdkapp.h
+++ b/src/sdk/sdkapp.h
@@ -42,12 +42,16 @@
#ifndef SDKAPP_H
#define SDKAPP_H
-#include <QApplication>
+#include <binarycontent.h>
+#include <binaryformat.h>
+#include <fileio.h>
+#include <fileutils.h>
-#ifdef Q_OS_OSX
+#include <QApplication>
+#include <QBuffer>
#include <QDir>
#include <QFileInfo>
-#endif
+#include <QResource>
template<class T>
class SDKApp : public T
@@ -58,8 +62,14 @@ public:
{
}
- ~SDKApp()
+ virtual ~SDKApp()
{
+ using namespace QInstaller;
+ foreach (const QSharedPointer<Resource> &resource, resourceMappings.resources()) {
+ resource->open(); // ignore error here, either we opened it or it is opened
+ QResource::unregisterResource((const uchar *) resource->readAll().constData(),
+ QLatin1String(":/metadata"));
+ }
}
bool notify(QObject *receiver, QEvent *event)
@@ -74,6 +84,15 @@ public:
return false;
}
+ /*!
+ Returns the installer/ maintenance tool binary. In case of an installer this will be the
+ installer binary itself, which contains the binary layout and the binary content. In case
+ of an maintenance tool, it will return a binary that has just a binary layout append.
+
+ Note on OSX: For compatibility reason this function will return the a .dat file located
+ inside the resource folder in the application bundle, as on OSX the binary layout can not
+ be appended to the actual installer/ maintenance tool binary itself because of signing.
+ */
QString binaryFile() const
{
QString binaryFile = QCoreApplication::applicationFilePath();
@@ -84,10 +103,68 @@ public:
QDir resourcePath(QFileInfo(binaryFile).dir());
resourcePath.cdUp();
resourcePath.cd(QLatin1String("Resources"));
- binaryFile = resourcePath.filePath(QLatin1String("installer.dat"));
+ return resourcePath.filePath(QLatin1String("installer.dat"));
#endif
return binaryFile;
}
+
+ /*!
+ Returns the corresponding .dat file for a given installer/ maintenance tool binary or an
+ empty string if it fails to find one.
+ */
+ QString datFile(const QString &binaryFile) const
+ {
+ QFile file(binaryFile);
+ QInstaller::openForRead(&file);
+ const quint64 cookiePos = QInstaller::BinaryContent::findMagicCookie(&file,
+ QInstaller::BinaryContent::MagicCookie);
+ if (!file.seek(cookiePos - sizeof(qint64))) // seek to read the marker
+ return QString(); // ignore error, we will fail later
+
+ const qint64 magicMarker = QInstaller::retrieveInt64(&file);
+ if (magicMarker == QInstaller::BinaryContent::MagicUninstallerMarker) {
+ QFileInfo fi(binaryFile);
+ QString bundlePath;
+ if (QInstaller::isInBundle(fi.absoluteFilePath(), &bundlePath))
+ fi.setFile(bundlePath);
+ return fi.absoluteDir().filePath(fi.baseName() + QLatin1String(".dat"));
+ }
+ return QString();
+ }
+
+ QInstaller::ResourceCollection registeredMetaResources()
+ {
+ return resourceMappings;
+ }
+
+ void registerMetaResources(const QInstaller::ResourceCollection &resources)
+ {
+ foreach (const QSharedPointer<QInstaller::Resource> &resource, resources.resources()) {
+ const bool isOpen = resource->isOpen();
+ if ((!isOpen) && (!resource->open()))
+ continue;
+
+ if (!resource->seek(0))
+ continue;
+
+ const QByteArray ba = resource->readAll();
+ if (ba.isEmpty())
+ continue;
+
+ if (QResource::registerResource((const uchar*) ba.data(), QLatin1String(":/metadata"))) {
+ using namespace QInstaller;
+ QSharedPointer<QBuffer> buffer(new QBuffer);
+ buffer->setData(ba); // set the buffers internal data
+ resourceMappings.appendResource(QSharedPointer<Resource>(new Resource(buffer)));
+ }
+
+ if (!isOpen) // If we reach that point, either the resource was opened already...
+ resource->close(); // or we did open it and have to close it again.
+ }
+ }
+
+private:
+ QInstaller::ResourceCollection resourceMappings;
};
#endif // SDKAPP_H
diff --git a/src/sdk/updatechecker.cpp b/src/sdk/updatechecker.cpp
index 60587942e..2ebe39b92 100644
--- a/src/sdk/updatechecker.cpp
+++ b/src/sdk/updatechecker.cpp
@@ -40,11 +40,9 @@
**************************************************************************/
#include "updatechecker.h"
-#include "sdkapp.h"
-#include <binarycontent.h>
+#include <binaryformatenginehandler.h>
#include <component.h>
-#include <constants.h>
#include <errors.h>
#include <init.h>
#include <kdrunoncechecker.h>
@@ -55,57 +53,65 @@
#include <iostream>
-int UpdateChecker::check(int argc, char *argv[])
+UpdateChecker::UpdateChecker(int &argc, char *argv[])
+ : SDKApp<QCoreApplication>(argc, argv)
{
- try {
- SDKApp<QCoreApplication> app(argc, argv);
-
- KDRunOnceChecker runCheck((QLatin1String("lockmyApp15021976.lock")));
- if (runCheck.isRunning(KDRunOnceChecker::Lockfile))
- throw QInstaller::Error(QLatin1String("An instance is already checking for updates."));
-
- QInstaller::init(); // register custom operations
-
- const QInstaller::BinaryContent content =
- QInstaller::BinaryContent::readAndRegisterFromBinary(app.binaryFile());
- if (content.magicMarker() != QInstaller::BinaryContent::MagicInstallerMarker)
- throw QInstaller::Error(QLatin1String("Installers cannot check for updates."));
-
- QInstaller::PackageManagerCore core(QInstaller::BinaryContent::MagicUpdaterMarker, content
- .performedOperations());
- ProductKeyCheck::instance()->init(&core);
- QInstaller::PackageManagerCore::setVirtualComponentsVisible(true);
-
- if (!core.fetchRemotePackagesTree())
- throw QInstaller::Error(core.error());
-
- const QList<QInstaller::Component *> components = core.updaterComponents();
- if (components.isEmpty())
- throw QInstaller::Error(QLatin1String("There are currently no updates available."));
-
- QDomDocument doc;
- QDomElement root = doc.createElement(QLatin1String("updates"));
- doc.appendChild(root);
-
- foreach (QInstaller::Component *component, components) {
- QDomElement update = doc.createElement(QLatin1String("update"));
- update.setAttribute(QLatin1String("name"),
- component->value(QInstaller::scDisplayName));
- update.setAttribute(QLatin1String("version"),
- component->value(QInstaller::scRemoteVersion));
- update.setAttribute(QLatin1String("size"),
- component->value(QInstaller::scUncompressedSize));
- root.appendChild(update);
- }
-
- std::cout << qPrintable(doc.toString(4)) << std::endl;
- return EXIT_SUCCESS;
- } catch (const QInstaller::Error &e) {
- std::cerr << qPrintable(e.message()) << std::endl;
- } catch (const std::exception &e) {
- std::cerr << e.what() << std::endl;
- } catch (...) {
- std::cerr << "Unknown exception caught." << std::endl;
+ QInstaller::init(); // register custom operations
+}
+
+int UpdateChecker::check()
+{
+ KDRunOnceChecker runCheck((QLatin1String("lockmyApp15021976.lock")));
+ if (runCheck.isRunning(KDRunOnceChecker::Lockfile))
+ throw QInstaller::Error(QLatin1String("An instance is already checking for updates."));
+
+ QString fileName = datFile(binaryFile());
+ quint64 cookie = QInstaller::BinaryContent::MagicCookieDat;
+ if (fileName.isEmpty()) {
+ fileName = binaryFile();
+ cookie = QInstaller::BinaryContent::MagicCookie;
}
- return EXIT_FAILURE;
+
+ QSharedPointer<QFile> binary(new QFile(fileName));
+ QInstaller::openForRead(binary.data());
+
+ qint64 magicMarker;
+ QInstaller::ResourceCollection resources;
+ QList<QInstaller::OperationBlob> operations;
+ QInstaller::ResourceCollectionManager manager;
+ QInstaller::BinaryContent::readBinaryContent(binary, &resources, &operations, &manager,
+ &magicMarker, cookie);
+
+ if (magicMarker != QInstaller::BinaryContent::MagicInstallerMarker)
+ throw QInstaller::Error(QLatin1String("Installers cannot check for updates."));
+
+ registerMetaResources(resources); // the base class will unregister the resources
+
+ // instantiate the installer we are actually going to use
+ QInstaller::PackageManagerCore core(QInstaller::BinaryContent::MagicUpdaterMarker, operations);
+ QInstaller::BinaryFormatEngineHandler::instance()->registerResources(manager.collections());
+ QInstaller::PackageManagerCore::setVirtualComponentsVisible(true);
+ QInstaller::ProductKeyCheck::instance()->init(&core);
+
+ if (!core.fetchRemotePackagesTree())
+ throw QInstaller::Error(core.error());
+
+ const QList<QInstaller::Component *> components = core.updaterComponents();
+ if (components.isEmpty())
+ throw QInstaller::Error(QLatin1String("There are currently no updates available."));
+
+ QDomDocument doc;
+ QDomElement root = doc.createElement(QLatin1String("updates"));
+ doc.appendChild(root);
+
+ foreach (QInstaller::Component *component, components) {
+ QDomElement update = doc.createElement(QLatin1String("update"));
+ update.setAttribute(QLatin1String("name"), component->value(QInstaller::scDisplayName));
+ update.setAttribute(QLatin1String("version"), component->value(QInstaller::scRemoteVersion));
+ update.setAttribute(QLatin1String("size"), component->value(QInstaller::scUncompressedSize));
+ root.appendChild(update);
+ }
+
+ std::cout << qPrintable(doc.toString(4)) << std::endl;
+ return EXIT_SUCCESS;
}
diff --git a/src/sdk/updatechecker.h b/src/sdk/updatechecker.h
index 504e97604..19b34e29b 100644
--- a/src/sdk/updatechecker.h
+++ b/src/sdk/updatechecker.h
@@ -42,11 +42,16 @@
#ifndef UPDATECHECKER_H
#define UPDATECHECKER_H
-class UpdateChecker
+#include "sdkapp.h"
+
+class UpdateChecker : public SDKApp<QCoreApplication>
{
+ Q_OBJECT
+ Q_DISABLE_COPY(UpdateChecker)
+
public:
- UpdateChecker() {}
- int check(int argc, char *argv[]);
+ UpdateChecker(int &argc, char *argv[]);
+ int check();
};
#endif // UPDATECHECKER_H
diff --git a/tests/auto/installer/packagemanagercore/tst_packagemanagercore.cpp b/tests/auto/installer/packagemanagercore/tst_packagemanagercore.cpp
index e82162444..304f6376b 100644
--- a/tests/auto/installer/packagemanagercore/tst_packagemanagercore.cpp
+++ b/tests/auto/installer/packagemanagercore/tst_packagemanagercore.cpp
@@ -104,7 +104,8 @@ private slots:
setIgnoreMessage(testDirectory);
- PackageManagerCore core(QInstaller::BinaryContent::MagicInstallerMarker);
+ PackageManagerCore core(QInstaller::BinaryContent::MagicInstallerMarker,
+ QList<QInstaller::OperationBlob>());
// cancel the installer in error case
core.autoRejectMessageBoxes();
core.appendRootComponent(new DummyComponent(&core));
@@ -132,7 +133,8 @@ private slots:
setIgnoreMessage(testDirectory);
- PackageManagerCore core(QInstaller::BinaryContent::MagicInstallerMarker);
+ PackageManagerCore core(QInstaller::BinaryContent::MagicInstallerMarker,
+ QList<QInstaller::OperationBlob>());
// cancel the installer in error case
core.autoRejectMessageBoxes();
core.appendRootComponent(new DummyComponent(&core));
diff --git a/tools/devtool/main.cpp b/tools/devtool/main.cpp
index d31870e67..0a9c677d2 100644
--- a/tools/devtool/main.cpp
+++ b/tools/devtool/main.cpp
@@ -143,23 +143,12 @@ int main(int argc, char *argv[])
if (!file->seek(operationsStart))
throw QInstaller::Error(QLatin1String("Could not seek to operation list."));
- QList<QInstaller::Operation *> performedOperations;
+ QList<QInstaller::OperationBlob> performedOperations;
const qint64 operationsCount = QInstaller::retrieveInt64(file);
for (int i = 0; i < operationsCount; ++i) {
const QString name = QInstaller::retrieveString(file);
const QString data = QInstaller::retrieveString(file);
-
- QScopedPointer<QInstaller::Operation> op(KDUpdater::UpdateOperationFactory::instance()
- .create(name));
- if (op.isNull()) {
- throw QInstaller::Error(QString::fromLatin1("Could not load unknown operation %1")
- .arg(name));
- }
- if (!op->fromXml(data)) {
- throw QInstaller::Error(QString::fromLatin1("Could not load XML for operation: %1")
- .arg(name));
- }
- performedOperations.append(op.take());
+ performedOperations.append(QInstaller::OperationBlob(name, data));
}
// seek to the position of the resource collections segment info
diff --git a/tools/devtool/operationrunner.cpp b/tools/devtool/operationrunner.cpp
index 55c1160e2..100dcf2cc 100644
--- a/tools/devtool/operationrunner.cpp
+++ b/tools/devtool/operationrunner.cpp
@@ -49,7 +49,8 @@
#include <iostream>
-OperationRunner::OperationRunner(qint64 magicMarker, const QInstaller::OperationList &oldOperations)
+OperationRunner::OperationRunner(qint64 magicMarker,
+ const QList<QInstaller::OperationBlob> &oldOperations)
: m_core(new QInstaller::PackageManagerCore(magicMarker, oldOperations))
{
// We need a package manager core as some operations expect them to be available.
diff --git a/tools/devtool/operationrunner.h b/tools/devtool/operationrunner.h
index 73964c3a5..d4026dadc 100644
--- a/tools/devtool/operationrunner.h
+++ b/tools/devtool/operationrunner.h
@@ -42,11 +42,12 @@
#ifndef OPERATIONRUNNER_H
#define OPERATIONRUNNER_H
-#include <qinstallerglobal.h>
+#include <binaryformat.h>
#include <QObject>
namespace QInstaller {
+ struct OperationBlob;
class PackageManagerCore;
}
@@ -61,7 +62,7 @@ public:
Undo
};
- OperationRunner(qint64 magicMarker, const QInstaller::OperationList &oldOperations);
+ OperationRunner(qint64 magicMarker, const QList<QInstaller::OperationBlob> &oldOperations);
~OperationRunner();
int runOperation(QStringList arguments, RunMode mode);