summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorArttu Tarkiainen <arttu.tarkiainen@qt.io>2020-11-20 17:09:30 +0200
committerArttu Tarkiainen <arttu.tarkiainen@qt.io>2020-12-02 10:25:18 +0000
commit885a41d1667ac8ccf59a4de76cb8449074a466ac (patch)
tree7e0909c5b06754f458c6b6e7d3a77a4ffd994be7 /tools
parentf053b9a627921b03529b4f797a97b582675fbe71 (diff)
Tools: refactor to move general purpose functionality to installer lib
This makes it possible to utilize parts of our existing tooling in the offline installer from online installer generation process. Task-number: QTIFW-2048 Change-Id: I7ee605be75541cc83a3b6909089bda45f0835bcf Reviewed-by: Katja Marttila <katja.marttila@qt.io>
Diffstat (limited to 'tools')
-rw-r--r--tools/archivegen/archivegen.pro6
-rw-r--r--tools/binarycreator/binarycreator.cpp1043
-rw-r--r--tools/binarycreator/binarycreator.pro9
-rw-r--r--tools/binarycreator/binarycreator.qrc7
-rw-r--r--tools/binarycreator/main.cpp210
-rw-r--r--tools/binarycreator/rcc/qcorecmdlineargs_p.h59
-rw-r--r--tools/binarycreator/rcc/rcc.cpp1038
-rw-r--r--tools/binarycreator/rcc/rcc.h140
-rw-r--r--tools/binarycreator/rcc/rccmain.cpp239
-rw-r--r--tools/binarycreator/resources/copylibsintobundle.sh189
-rw-r--r--tools/binarycreator/resources/default_icon_mac.icnsbin118992 -> 0 bytes
-rw-r--r--tools/common/repositorygen.cpp965
-rw-r--r--tools/common/repositorygen.h87
-rw-r--r--tools/repogen/repogen.cpp4
-rw-r--r--tools/repogen/repogen.pri1
-rw-r--r--tools/repogen/repogen.pro5
16 files changed, 217 insertions, 3785 deletions
diff --git a/tools/archivegen/archivegen.pro b/tools/archivegen/archivegen.pro
index 2cb8b6bdc..0a5032d2f 100644
--- a/tools/archivegen/archivegen.pro
+++ b/tools/archivegen/archivegen.pro
@@ -1,6 +1,6 @@
TEMPLATE = app
TARGET = archivegen
-INCLUDEPATH += . .. ../common
+INCLUDEPATH += . ..
include(../../installerfw.pri)
@@ -11,9 +11,7 @@ LIBS += -l7z
CONFIG += console
DESTDIR = $$IFW_APP_PATH
-SOURCES += archive.cpp \
- ../common/repositorygen.cpp
-HEADERS += ../common/repositorygen.h
+SOURCES += archive.cpp
macx:include(../../no_app_bundle.pri)
diff --git a/tools/binarycreator/binarycreator.cpp b/tools/binarycreator/binarycreator.cpp
deleted file mode 100644
index f6662615e..000000000
--- a/tools/binarycreator/binarycreator.cpp
+++ /dev/null
@@ -1,1043 +0,0 @@
-/**************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Installer Framework.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-**************************************************************************/
-#include "common/repositorygen.h"
-
-#include <qtpatch.h>
-
-#include <binarycontent.h>
-#include <binaryformat.h>
-#include <errors.h>
-#include <fileio.h>
-#include <fileutils.h>
-#include <init.h>
-#include <repository.h>
-#include <settings.h>
-#include <utils.h>
-
-#include <QDateTime>
-#include <QDirIterator>
-#include <QDomDocument>
-#include <QProcess>
-#include <QRegExp>
-#include <QSettings>
-#include <QTemporaryFile>
-#include <QTemporaryDir>
-
-#include <iostream>
-
-#ifdef Q_OS_MACOS
-#include <QtCore/QtEndian>
-#include <QtCore/QFile>
-#include <QtCore/QVersionNumber>
-
-#include <mach-o/fat.h>
-#include <mach-o/loader.h>
-#endif
-
-using namespace QInstaller;
-
-struct Input {
- QString outputPath;
- QString installerExePath;
- QInstallerTools::PackageInfoVector packages;
- QInstaller::ResourceCollectionManager manager;
-};
-
-class BundleBackup
-{
-public:
- explicit BundleBackup(const QString &bundle = QString())
- : bundle(bundle)
- {
- if (!bundle.isEmpty() && QFileInfo(bundle).exists()) {
- backup = generateTemporaryFileName(bundle);
- QFile::rename(bundle, backup);
- }
- }
-
- ~BundleBackup()
- {
- if (!backup.isEmpty()) {
- removeDirectory(bundle);
- QFile::rename(backup, bundle);
- }
- }
-
- void release() const
- {
- if (!backup.isEmpty())
- removeDirectory(backup);
- backup.clear();
- }
-
-private:
- const QString bundle;
- mutable QString backup;
-};
-
-#ifndef Q_OS_WIN
-static void chmod755(const QString &absolutFilePath)
-{
- QFile::setPermissions(absolutFilePath, QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner
- | QFile::ReadGroup | QFile::ExeGroup | QFile::ReadOther | QFile::ExeOther);
-}
-#endif
-
-#ifdef Q_OS_MACOS
-template <typename T = uint32_t> T readInt(QIODevice *ioDevice, bool *ok,
- bool swap, bool peek = false) {
- const auto bytes = peek
- ? ioDevice->peek(sizeof(T))
- : ioDevice->read(sizeof(T));
- if (bytes.size() != sizeof(T)) {
- if (ok)
- *ok = false;
- return T();
- }
- if (ok)
- *ok = true;
- T n = *reinterpret_cast<const T *>(bytes.constData());
- return swap ? qbswap(n) : n;
-}
-
-static QVersionNumber readMachOMinimumSystemVersion(QIODevice *device)
-{
- bool ok;
- std::vector<qint64> machoOffsets;
-
- qint64 pos = device->pos();
- uint32_t magic = readInt(device, &ok, false);
- if (magic == FAT_MAGIC || magic == FAT_CIGAM ||
- magic == FAT_MAGIC_64 || magic == FAT_CIGAM_64) {
- bool swap = magic == FAT_CIGAM || magic == FAT_CIGAM_64;
- uint32_t nfat = readInt(device, &ok, swap);
- if (!ok)
- return QVersionNumber();
-
- for (uint32_t n = 0; n < nfat; ++n) {
- const bool is64bit = magic == FAT_MAGIC_64 || magic == FAT_CIGAM_64;
- fat_arch_64 fat_arch;
- fat_arch.cputype = static_cast<cpu_type_t>(readInt(device, &ok, swap));
- if (!ok)
- return QVersionNumber();
-
- fat_arch.cpusubtype = static_cast<cpu_subtype_t>(readInt(device, &ok, swap));
- if (!ok)
- return QVersionNumber();
-
- fat_arch.offset = is64bit
- ? readInt<uint64_t>(device, &ok, swap) : readInt(device, &ok, swap);
- if (!ok)
- return QVersionNumber();
-
- fat_arch.size = is64bit
- ? readInt<uint64_t>(device, &ok, swap) : readInt(device, &ok, swap);
- if (!ok)
- return QVersionNumber();
-
- fat_arch.align = readInt(device, &ok, swap);
- if (!ok)
- return QVersionNumber();
-
- fat_arch.reserved = is64bit ? readInt(device, &ok, swap) : 0;
- if (!ok)
- return QVersionNumber();
-
- machoOffsets.push_back(static_cast<qint64>(fat_arch.offset));
- }
- } else if (!ok) {
- return QVersionNumber();
- }
-
- // Wasn't a fat file, so we just read a thin Mach-O from the original offset
- if (machoOffsets.empty())
- machoOffsets.push_back(pos);
-
- std::vector<QVersionNumber> versions;
-
- for (const auto &offset : machoOffsets) {
- if (!device->seek(offset))
- return QVersionNumber();
-
- bool swap = false;
- mach_header_64 header;
- header.magic = readInt(device, nullptr, swap);
- switch (header.magic) {
- case MH_CIGAM:
- case MH_CIGAM_64:
- swap = true;
- break;
- case MH_MAGIC:
- case MH_MAGIC_64:
- break;
- default:
- return QVersionNumber();
- }
-
- header.cputype = static_cast<cpu_type_t>(readInt(device, &ok, swap));
- if (!ok)
- return QVersionNumber();
-
- header.cpusubtype = static_cast<cpu_subtype_t>(readInt(device, &ok, swap));
- if (!ok)
- return QVersionNumber();
-
- header.filetype = readInt(device, &ok, swap);
- if (!ok)
- return QVersionNumber();
-
- header.ncmds = readInt(device, &ok, swap);
- if (!ok)
- return QVersionNumber();
-
- header.sizeofcmds = readInt(device, &ok, swap);
- if (!ok)
- return QVersionNumber();
-
- header.flags = readInt(device, &ok, swap);
- if (!ok)
- return QVersionNumber();
-
- header.reserved = header.magic == MH_MAGIC_64 || header.magic == MH_CIGAM_64
- ? readInt(device, &ok, swap) : 0;
- if (!ok)
- return QVersionNumber();
-
- for (uint32_t i = 0; i < header.ncmds; ++i) {
- const uint32_t cmd = readInt(device, nullptr, swap);
- const uint32_t cmdsize = readInt(device, nullptr, swap);
- if (cmd == 0 || cmdsize == 0)
- return QVersionNumber();
-
- switch (cmd) {
- case LC_VERSION_MIN_MACOSX:
- case LC_VERSION_MIN_IPHONEOS:
- case LC_VERSION_MIN_TVOS:
- case LC_VERSION_MIN_WATCHOS:
- const uint32_t version = readInt(device, &ok, swap, true);
- if (!ok)
- return QVersionNumber();
-
- versions.push_back(QVersionNumber(
- static_cast<int>(version >> 16),
- static_cast<int>((version >> 8) & 0xff),
- static_cast<int>(version & 0xff)));
- break;
- }
-
- const qint64 remaining = static_cast<qint64>(cmdsize - sizeof(cmd) - sizeof(cmdsize));
- if (device->read(remaining).size() != remaining)
- return QVersionNumber();
- }
- }
-
- std::sort(versions.begin(), versions.end());
- return !versions.empty() ? versions.front() : QVersionNumber();
-}
-#endif
-
-static int assemble(Input input, const QInstaller::Settings &settings, const QString &signingIdentity)
-{
-#ifdef Q_OS_MACOS
- if (QInstaller::isInBundle(input.installerExePath)) {
- const QString bundle = input.installerExePath;
- // if the input file was a bundle
- const QSettings s(QString::fromLatin1("%1/Contents/Info.plist").arg(input.installerExePath),
- QSettings::NativeFormat);
- input.installerExePath = QString::fromLatin1("%1/Contents/MacOS/%2").arg(bundle)
- .arg(s.value(QLatin1String("CFBundleExecutable"),
- QFileInfo(input.installerExePath).completeBaseName()).toString());
- }
-
- const bool createDMG = input.outputPath.endsWith(QLatin1String(".dmg"));
- if (createDMG)
- input.outputPath.replace(input.outputPath.length() - 4, 4, QLatin1String(".app"));
-
- const bool isBundle = input.outputPath.endsWith(QLatin1String(".app"));
- const QString bundle = isBundle ? input.outputPath : QString();
- const BundleBackup bundleBackup(bundle);
-
- if (isBundle) {
- // output should be a bundle
- const QFileInfo fi(input.outputPath);
-
- QString minimumSystemVersion;
- QFile file(input.installerExePath);
- if (file.open(QIODevice::ReadOnly))
- minimumSystemVersion = readMachOMinimumSystemVersion(&file).normalized().toString();
-
- const QString contentsResourcesPath = fi.filePath() + QLatin1String("/Contents/Resources/");
-
- QInstaller::mkpath(fi.filePath() + QLatin1String("/Contents/MacOS"));
- QInstaller::mkpath(contentsResourcesPath);
-
- {
- QFile pkgInfo(fi.filePath() + QLatin1String("/Contents/PkgInfo"));
- pkgInfo.open(QIODevice::WriteOnly);
- QTextStream pkgInfoStream(&pkgInfo);
- pkgInfoStream << QLatin1String("APPL????") << endl;
- }
-
- QString iconFile;
- if (QFile::exists(settings.installerApplicationIcon())) {
- iconFile = settings.installerApplicationIcon();
- } else {
- iconFile = QString::fromLatin1(":/resources/default_icon_mac.icns");
- }
-
- const QString iconTargetFile = fi.completeBaseName() + QLatin1String(".icns");
- QFile::copy(iconFile, contentsResourcesPath + iconTargetFile);
- if (QDir(qApp->applicationDirPath() + QLatin1String("/qt_menu.nib")).exists()) {
- copyDirectoryContents(qApp->applicationDirPath() + QLatin1String("/qt_menu.nib"),
- contentsResourcesPath + QLatin1String("/qt_menu.nib"));
- }
-
- QFile infoPList(fi.filePath() + QLatin1String("/Contents/Info.plist"));
- infoPList.open(QIODevice::WriteOnly);
- QTextStream plistStream(&infoPList);
- plistStream << QLatin1String("<?xml version=\"1.0\" encoding=\"UTF-8\"?>") << endl;
- plistStream << QLatin1String("<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" "
- "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">") << endl;
- plistStream << QLatin1String("<plist version=\"1.0\">") << endl;
- plistStream << QLatin1String("<dict>") << endl;
- plistStream << QLatin1String("\t<key>CFBundleIconFile</key>") << endl;
- plistStream << QLatin1String("\t<string>") << iconTargetFile << QLatin1String("</string>")
- << endl;
- plistStream << QLatin1String("\t<key>CFBundlePackageType</key>") << endl;
- plistStream << QLatin1String("\t<string>APPL</string>") << endl;
-#define QUOTE_(x) #x
-#define QUOTE(x) QUOTE_(x)
- plistStream << QLatin1String("\t<key>CFBundleShortVersionString</key>") << endl;
- plistStream << QLatin1String("\t<string>") << QLatin1String(QUOTE(IFW_VERSION_STR)) << ("</string>")
- << endl;
- plistStream << QLatin1String("\t<key>CFBundleVersion</key>") << endl;
- plistStream << QLatin1String("\t<string>") << QLatin1String(QUOTE(IFW_VERSION_STR)) << ("</string>")
- << endl;
-#undef QUOTE
-#undef QUOTE_
- plistStream << QLatin1String("\t<key>CFBundleSignature</key>") << endl;
- plistStream << QLatin1String("\t<string>\?\?\?\?</string>") << endl;
- plistStream << QLatin1String("\t<key>CFBundleExecutable</key>") << endl;
- plistStream << QLatin1String("\t<string>") << fi.completeBaseName() << QLatin1String("</string>")
- << endl;
- plistStream << QLatin1String("\t<key>CFBundleIdentifier</key>") << endl;
- plistStream << QLatin1String("\t<string>com.yourcompany.installerbase</string>") << endl;
- plistStream << QLatin1String("\t<key>NOTE</key>") << endl;
- plistStream << QLatin1String("\t<string>This file was generated by Qt Installer Framework.</string>")
- << endl;
- plistStream << QLatin1String("\t<key>NSPrincipalClass</key>") << endl;
- plistStream << QLatin1String("\t<string>NSApplication</string>") << endl;
- if (!minimumSystemVersion.isEmpty()) {
- plistStream << QLatin1String("\t<key>LSMinimumSystemVersion</key>") << endl;
- plistStream << QLatin1String("\t<string>") << minimumSystemVersion << QLatin1String("</string>") << endl;
- }
- plistStream << QLatin1String("</dict>") << endl;
- plistStream << QLatin1String("</plist>") << endl;
-
- input.outputPath = QString::fromLatin1("%1/Contents/MacOS/%2").arg(input.outputPath)
- .arg(fi.completeBaseName());
- }
-#elif defined(Q_OS_LINUX)
- Q_UNUSED(settings)
-#endif
-
- QTemporaryFile file(input.outputPath);
- if (!file.open()) {
- throw Error(QString::fromLatin1("Cannot copy %1 to %2: %3").arg(input.installerExePath,
- input.outputPath, file.errorString()));
- }
-
- const QString tempFile = file.fileName();
- file.close();
- file.remove();
-
- QFile instExe(input.installerExePath);
- if (!instExe.copy(tempFile)) {
- throw Error(QString::fromLatin1("Cannot copy %1 to %2: %3").arg(instExe.fileName(),
- tempFile, instExe.errorString()));
- }
-
- QtPatch::patchBinaryFile(tempFile, QByteArray("MY_InstallerCreateDateTime_MY"),
- QDateTime::currentDateTime().toString(QLatin1String("yyyy-MM-dd - HH:mm:ss")).toLatin1());
-
-
- input.installerExePath = tempFile;
-
-#if defined(Q_OS_WIN)
- // setting the windows icon must happen before we append our binary data - otherwise they get lost :-/
- if (QFile::exists(settings.installerApplicationIcon())) {
- // no error handling as this is not fatal
- setApplicationIcon(tempFile, settings.installerApplicationIcon());
- }
-#elif defined(Q_OS_MACOS)
- if (isBundle) {
- // no error handling as this is not fatal
- const QString copyscript = QDir::temp().absoluteFilePath(QLatin1String("copylibsintobundle.sh"));
- QFile::copy(QLatin1String(":/resources/copylibsintobundle.sh"), copyscript);
- QFile::rename(tempFile, input.outputPath);
- chmod755(copyscript);
- QProcess p;
- p.start(copyscript, QStringList() << bundle);
- p.waitForFinished(-1);
- QFile::rename(input.outputPath, tempFile);
- QFile::remove(copyscript);
- }
-#endif
-
- QFile out(generateTemporaryFileName());
-
- QString targetName = input.outputPath;
-#ifdef Q_OS_MACOS
- QDir resourcePath(QFileInfo(input.outputPath).dir());
- resourcePath.cdUp();
- resourcePath.cd(QLatin1String("Resources"));
- targetName = resourcePath.filePath(QLatin1String("installer.dat"));
-#endif
-
- {
- QFile target(targetName);
- if (target.exists() && !target.remove()) {
- qCritical("Cannot remove target %s: %s", qPrintable(target.fileName()),
- qPrintable(target.errorString()));
- QFile::remove(tempFile);
- return EXIT_FAILURE;
- }
- }
-
- try {
- QInstaller::openForWrite(&out);
- QFile exe(input.installerExePath);
-
-#ifdef Q_OS_MACOS
- if (!exe.copy(input.outputPath)) {
- throw Error(QString::fromLatin1("Cannot copy %1 to %2: %3").arg(exe.fileName(),
- input.outputPath, exe.errorString()));
- }
-#else
- QInstaller::openForRead(&exe);
- QInstaller::appendData(&out, &exe, exe.size());
-#endif
-
- foreach (const QInstallerTools::PackageInfo &info, input.packages) {
- QInstaller::ResourceCollection collection;
- collection.setName(info.name.toUtf8());
-
- qDebug() << "Creating resource archive for" << info.name;
- foreach (const QString &file, info.copiedFiles) {
- const QSharedPointer<Resource> resource(new Resource(file));
- qDebug().nospace() << "Appending " << file << " (" << humanReadableSize(resource->size()) << ")";
- collection.appendResource(resource);
- }
- input.manager.insertCollection(collection);
- }
-
- const QList<QInstaller::OperationBlob> operations;
- BinaryContent::writeBinaryContent(&out, operations, input.manager,
- BinaryContent::MagicInstallerMarker, BinaryContent::MagicCookie);
- } catch (const Error &e) {
- qCritical("Error occurred while assembling the installer: %s", qPrintable(e.message()));
- QFile::remove(tempFile);
- return EXIT_FAILURE;
- }
-
- if (!out.rename(targetName)) {
- qCritical("Cannot write installer to %s: %s", targetName.toUtf8().constData(),
- out.errorString().toUtf8().constData());
- QFile::remove(tempFile);
- return EXIT_FAILURE;
- }
-
-#ifndef Q_OS_WIN
- chmod755(out.fileName());
-#endif
- QFile::remove(tempFile);
-
-#ifdef Q_OS_MACOS
- if (isBundle && !signingIdentity.isEmpty()) {
- qDebug() << "Signing .app bundle...";
-
- QProcess p;
- p.start(QLatin1String("codesign"),
- QStringList() << QLatin1String("--force")
- << QLatin1String("--deep")
- << QLatin1String("--sign") << signingIdentity
- << bundle);
-
- if (!p.waitForFinished(-1)) {
- qCritical("Failed to sign app bundle: error while running '%s %s': %s",
- p.program().toUtf8().constData(),
- p.arguments().join(QLatin1Char(' ')).toUtf8().constData(),
- p.errorString().toUtf8().constData());
- return EXIT_FAILURE;
- }
-
- if (p.exitStatus() == QProcess::NormalExit) {
- if (p.exitCode() != 0) {
- qCritical("Failed to sign app bundle: running codesign failed "
- "with exit code %d: %s", p.exitCode(),
- p.readAllStandardError().constData());
- return EXIT_FAILURE;
- }
- }
-
- qDebug() << "done.";
- }
-
- bundleBackup.release();
-
- if (createDMG) {
- qDebug() << "creating a DMG disk image...";
-
- const QString volumeName = QFileInfo(input.outputPath).fileName();
- const QString imagePath = QString::fromLatin1("%1/%2.dmg")
- .arg(QFileInfo(bundle).path())
- .arg(volumeName);
-
- // no error handling as this is not fatal
- QProcess p;
- p.start(QLatin1String("/usr/bin/hdiutil"),
- QStringList() << QLatin1String("create")
- << imagePath
- << QLatin1String("-srcfolder")
- << bundle
- << QLatin1String("-ov")
- << QLatin1String("-volname")
- << volumeName
- << QLatin1String("-fs")
- << QLatin1String("HFS+"));
- qDebug() << "running " << p.program() << p.arguments();
- p.waitForFinished(-1);
- qDebug() << "removing" << bundle;
- QDir(bundle).removeRecursively();
- qDebug() << "done.";
- }
-#else
- Q_UNUSED(signingIdentity)
-#endif
- return EXIT_SUCCESS;
-}
-
-QT_BEGIN_NAMESPACE
-int runRcc(int argc, char *argv[]);
-QT_END_NAMESPACE
-
-static int runRcc(const QStringList &args)
-{
- const int argc = args.count();
- QVector<char*> argv(argc, nullptr);
- for (int i = 0; i < argc; ++i)
- argv[i] = qstrdup(qPrintable(args[i]));
-
- // Note: this does not run the rcc provided by Qt, this one is using the compiled in binarycreator
- // version. If it happens that resource mapping fails, we might need to adapt the code here...
- const int result = runRcc(argc, argv.data());
-
- foreach (char *arg, argv)
- delete [] arg;
-
- return result;
-}
-
-class WorkingDirectoryChange
-{
-public:
- explicit WorkingDirectoryChange(const QString &path)
- : oldPath(QDir::currentPath())
- {
- QDir::setCurrent(path);
- }
-
- virtual ~WorkingDirectoryChange()
- {
- QDir::setCurrent(oldPath);
- }
-
-private:
- const QString oldPath;
-};
-
-static QSharedPointer<QInstaller::Resource> createDefaultResourceFile(const QString &directory,
- const QString &binaryName)
-{
- QTemporaryFile projectFile(directory + QLatin1String("/rccprojectXXXXXX.qrc"));
- if (!projectFile.open())
- throw Error(QString::fromLatin1("Cannot create temporary file for generated rcc project file"));
- projectFile.close();
-
- const WorkingDirectoryChange wd(directory);
- const QString projectFileName = QFileInfo(projectFile.fileName()).absoluteFilePath();
-
- // 1. create the .qrc file
- if (runRcc(QStringList() << QLatin1String("rcc") << QLatin1String("-project") << QLatin1String("-o")
- << projectFileName) != EXIT_SUCCESS) {
- throw Error(QString::fromLatin1("Cannot create rcc project file."));
- }
-
- // 2. create the binary resource file from the .qrc file
- if (runRcc(QStringList() << QLatin1String("rcc") << QLatin1String("-binary") << QLatin1String("-o")
- << binaryName << projectFileName) != EXIT_SUCCESS) {
- throw Error(QString::fromLatin1("Cannot compile rcc project file."));
- }
-
- return QSharedPointer<QInstaller::Resource>(new QInstaller::Resource(binaryName, binaryName
- .toUtf8()));
-}
-
-static
-QList<QSharedPointer<QInstaller::Resource> > createBinaryResourceFiles(const QStringList &resources)
-{
- QList<QSharedPointer<QInstaller::Resource> > result;
- foreach (const QString &resource, resources) {
- QFile file(resource);
- if (file.exists()) {
- const QString binaryName = generateTemporaryFileName();
- const QString fileName = QFileInfo(file.fileName()).absoluteFilePath();
- const int status = runRcc(QStringList() << QLatin1String("rcc")
- << QLatin1String("-binary") << QLatin1String("-o") << binaryName << fileName);
- if (status != EXIT_SUCCESS)
- continue;
-
- result.append(QSharedPointer<QInstaller::Resource> (new QInstaller::Resource(binaryName,
- binaryName.toUtf8())));
- }
- }
- return result;
-}
-
-static void printUsage()
-{
- QString suffix;
-#ifdef Q_OS_WIN
- suffix = QLatin1String(".exe");
-#endif
- const QString appName = QFileInfo(QCoreApplication::applicationFilePath()).fileName();
- std::cout << "Usage: " << appName << " [options] target" << std::endl;
- std::cout << std::endl;
- std::cout << "Options:" << std::endl;
-
- std::cout << " -t|--template file Use file as installer template binary" << std::endl;
- std::cout << " If this parameter is not given, the template used" << std::endl;
- std::cout << " defaults to installerbase." << std::endl;
-
- QInstallerTools::printRepositoryGenOptions();
-
- std::cout << " -c|--config file The file containing the installer configuration" << std::endl;
-
- std::cout << " -n|--online-only Do not add any package into the installer" << std::endl;
- std::cout << " (for online only installers)" << std::endl;
-
- std::cout << " -f|--offline-only Forces the installer to act as an offline installer, " << std::endl;
- std::cout << " i.e. never access online repositories" << std::endl;
-
- std::cout << " -r|--resources r1,.,rn include the given resource files into the binary" << std::endl;
-
- std::cout << " -v|--verbose Verbose output" << std::endl;
- std::cout << " -rcc|--compile-resource Compiles the default resource and outputs the result into"
- << std::endl;
- std::cout << " 'update.rcc' in the current path." << std::endl;
-#ifdef Q_OS_MACOS
- std::cout << " -s|--sign identity Sign generated app bundle using the given code " << std::endl;
- std::cout << " signing identity" << std::endl;
-#endif
- std::cout << std::endl;
- std::cout << "Packages are to be found in the current working directory and get listed as "
- "their names" << std::endl << std::endl;
- std::cout << "Example (offline installer):" << std::endl;
- char sep = QDir::separator().toLatin1();
- std::cout << " " << appName << " --offline-only -c installer-config" << sep << "config.xml -p "
- "packages-directory -t installerbase" << suffix << " SDKInstaller" << suffix << std::endl;
- std::cout << "Creates an offline installer for the SDK, containing all dependencies." << std::endl;
- std::cout << std::endl;
- std::cout << "Example (online installer):" << std::endl;
- std::cout << " " << appName << " -c installer-config" << sep << "config.xml -p packages-directory "
- "-e org.qt-project.sdk.qt,org.qt-project.qtcreator -t installerbase" << suffix << " SDKInstaller"
- << suffix << std::endl;
- std::cout << std::endl;
- std::cout << "Creates an installer for the SDK without qt and qt creator." << std::endl;
- std::cout << std::endl;
- std::cout << "Example update.rcc:" << std::endl;
- std::cout << " " << appName << " -c installer-config" << sep << "config.xml -p packages-directory "
- "-rcc" << std::endl;
-}
-
-void copyConfigData(const QString &configFile, const QString &targetDir)
-{
- qDebug() << "Begin to copy configuration file and data.";
-
- const QString sourceConfigFile = QFileInfo(configFile).absoluteFilePath();
- const QString targetConfigFile = targetDir + QLatin1String("/config.xml");
- QInstallerTools::copyWithException(sourceConfigFile, targetConfigFile, QLatin1String("configuration"));
-
- QFile configXml(targetConfigFile);
- QInstaller::openForRead(&configXml);
-
- QDomDocument dom;
- dom.setContent(&configXml);
- configXml.close();
-
- // iterate over all child elements, searching for relative file names
- const QDomNodeList children = dom.documentElement().childNodes();
- const QString sourceConfigFilePath = QFileInfo(sourceConfigFile).absolutePath();
- for (int i = 0; i < children.count(); ++i) {
- QDomElement domElement = children.at(i).toElement();
- if (domElement.isNull())
- continue;
-
- const QString tagName = domElement.tagName();
- const QString elementText = domElement.text();
- qDebug().noquote() << QString::fromLatin1("Read dom element: <%1>%2</%1>.").arg(tagName, elementText);
-
- if (tagName == QLatin1String("ProductImages")) {
- const QDomNodeList childNodes = domElement.childNodes();
- for (int i = 0; i < childNodes.count(); ++i) {
- const QDomElement childElement = childNodes.at(i).toElement();
- const QString childName = childElement.tagName();
- if (childName != QLatin1String("Image"))
- continue;
-
- const QString targetFile = targetDir + QLatin1Char('/') + childElement.text();
- const QFileInfo childFileInfo = QFileInfo(sourceConfigFilePath, childElement.text());
- QInstallerTools::copyWithException(childFileInfo.absoluteFilePath(), targetFile, childName);
- }
- continue;
- }
-
- QString newName = domElement.text().replace(QRegExp(QLatin1String("\\\\|/|\\.|:")),
- QLatin1String("_"));
-
- QString targetFile;
- QFileInfo elementFileInfo;
- if (tagName == QLatin1String("Icon") || tagName == QLatin1String("InstallerApplicationIcon")) {
-#if defined(Q_OS_MACOS)
- const QString suffix = QLatin1String(".icns");
-#elif defined(Q_OS_WIN)
- const QString suffix = QLatin1String(".ico");
-#else
- const QString suffix = QLatin1String(".png");
-#endif
- elementFileInfo = QFileInfo(sourceConfigFilePath, elementText + suffix);
- targetFile = targetDir + QLatin1Char('/') + newName + suffix;
- } else {
- elementFileInfo = QFileInfo(sourceConfigFilePath, elementText);
- const QString suffix = elementFileInfo.completeSuffix();
- if (!suffix.isEmpty())
- newName.append(QLatin1Char('.') + suffix);
- targetFile = targetDir + QLatin1Char('/') + newName;
- }
- if (!elementFileInfo.exists() || elementFileInfo.isDir())
- continue;
-
- domElement.replaceChild(dom.createTextNode(newName), domElement.firstChild());
- QInstallerTools::copyWithException(elementFileInfo.absoluteFilePath(), targetFile, tagName);
- }
-
- QInstaller::openForWrite(&configXml);
- QTextStream stream(&configXml);
- dom.save(stream, 4);
-
- qDebug() << "done.\n";
-}
-
-static int printErrorAndUsageAndExit(const QString &err)
-{
- std::cerr << qPrintable(err) << std::endl << std::endl;
- printUsage();
- return EXIT_FAILURE;
-}
-
-int main(int argc, char **argv)
-{
-// increase maximum numbers of file descriptors
-#if defined (Q_OS_MACOS)
- struct rlimit rl;
- getrlimit(RLIMIT_NOFILE, &rl);
- rl.rlim_cur = qMin(static_cast<rlim_t>(OPEN_MAX), rl.rlim_max);
- setrlimit(RLIMIT_NOFILE, &rl);
-#endif
- QCoreApplication app(argc, argv);
-
- QInstaller::init();
-
- QString templateBinary = QLatin1String("installerbase");
- QString suffix;
-#ifdef Q_OS_WIN
- suffix = QLatin1String(".exe");
- templateBinary = templateBinary + suffix;
-#endif
- if (!QFileInfo(templateBinary).exists())
- templateBinary = QString::fromLatin1("%1/%2").arg(qApp->applicationDirPath(), templateBinary);
-
- QString target;
- QString configFile;
- QStringList packagesDirectories;
- QStringList repositoryDirectories;
- bool onlineOnly = false;
- bool offlineOnly = false;
- QStringList resources;
- QStringList filteredPackages;
- QInstallerTools::FilterType ftype = QInstallerTools::Exclude;
- bool compileResource = false;
- QString signingIdentity;
-
- const QStringList args = app.arguments().mid(1);
- for (QStringList::const_iterator it = args.begin(); it != args.end(); ++it) {
- if (*it == QLatin1String("-h") || *it == QLatin1String("--help")) {
- printUsage();
- return 0;
- } else if (*it == QLatin1String("-p") || *it == QLatin1String("--packages")) {
- ++it;
- if (it == args.end()) {
- return printErrorAndUsageAndExit(QString::fromLatin1("Error: Packages parameter missing argument."));
- }
- if (!QFileInfo(*it).exists()) {
- return printErrorAndUsageAndExit(QString::fromLatin1("Error: Package directory not found at the "
- "specified location."));
- }
- packagesDirectories.append(*it);
- } else if (*it == QLatin1String("--repository")) {
- ++it;
- if (it == args.end()) {
- return printErrorAndUsageAndExit(QString::fromLatin1("Error: Repository parameter missing argument."));
- }
- if (QFileInfo(*it).exists()) {
- repositoryDirectories.append(*it);
- } else {
- return printErrorAndUsageAndExit(QString::fromLatin1("Error: Only local filesystem repositories now supported."));
- }
- } else if (*it == QLatin1String("-e") || *it == QLatin1String("--exclude")) {
- ++it;
- if (!filteredPackages.isEmpty())
- return printErrorAndUsageAndExit(QString::fromLatin1("Error: --include and --exclude are mutually "
- "exclusive. Use either one or the other."));
- if (it == args.end() || it->startsWith(QLatin1String("-")))
- return printErrorAndUsageAndExit(QString::fromLatin1("Error: Package to exclude missing."));
- filteredPackages = it->split(QLatin1Char(','));
- } else if (*it == QLatin1String("-i") || *it == QLatin1String("--include")) {
- ++it;
- if (!filteredPackages.isEmpty())
- return printErrorAndUsageAndExit(QString::fromLatin1("Error: --include and --exclude are mutually "
- "exclusive. Use either one or the other."));
- if (it == args.end() || it->startsWith(QLatin1String("-")))
- return printErrorAndUsageAndExit(QString::fromLatin1("Error: Package to include missing."));
- filteredPackages = it->split(QLatin1Char(','));
- ftype = QInstallerTools::Include;
- }
- else if (*it == QLatin1String("-v") || *it == QLatin1String("--verbose")) {
- QInstaller::setVerbose(true);
- } else if (*it == QLatin1String("-n") || *it == QLatin1String("--online-only")) {
- if (!filteredPackages.isEmpty()) {
- return printErrorAndUsageAndExit(QString::fromLatin1("Error: 'online-only' option cannot be used "
- "in conjunction with the 'include' or 'exclude' option. An 'online-only' installer will never "
- "contain any components apart from the root component."));
- }
- onlineOnly = true;
- } else if (*it == QLatin1String("-f") || *it == QLatin1String("--offline-only")) {
- offlineOnly = true;
- } else if (*it == QLatin1String("-t") || *it == QLatin1String("--template")) {
- ++it;
- if (it == args.end()) {
- return printErrorAndUsageAndExit(QString::fromLatin1("Error: Template parameter missing argument."));
- }
- templateBinary = *it;
-#ifdef Q_OS_WIN
- if (!templateBinary.endsWith(suffix))
- templateBinary = templateBinary + suffix;
-#endif
- if (!QFileInfo(templateBinary).exists()) {
- return printErrorAndUsageAndExit(QString::fromLatin1("Error: Template not found at the specified "
- "location."));
- }
- } else if (*it == QLatin1String("-c") || *it == QLatin1String("--config")) {
- ++it;
- if (it == args.end())
- return printErrorAndUsageAndExit(QString::fromLatin1("Error: Config parameter missing argument."));
- const QFileInfo fi(*it);
- if (!fi.exists()) {
- return printErrorAndUsageAndExit(QString::fromLatin1("Error: Config file %1 not found at the "
- "specified location.").arg(*it));
- }
- if (!fi.isFile()) {
- return printErrorAndUsageAndExit(QString::fromLatin1("Error: Configuration %1 is not a file.")
- .arg(*it));
- }
- if (!fi.isReadable()) {
- return printErrorAndUsageAndExit(QString::fromLatin1("Error: Config file %1 is not readable.")
- .arg(*it));
- }
- configFile = *it;
- } else if (*it == QLatin1String("-r") || *it == QLatin1String("--resources")) {
- ++it;
- if (it == args.end() || it->startsWith(QLatin1String("-")))
- return printErrorAndUsageAndExit(QString::fromLatin1("Error: Resource files to include are missing."));
- resources = it->split(QLatin1Char(','));
- } else if (*it == QLatin1String("--ignore-translations")
- || *it == QLatin1String("--ignore-invalid-packages")) {
- continue;
- } else if (*it == QLatin1String("-rcc") || *it == QLatin1String("--compile-resource")) {
- compileResource = true;
-#ifdef Q_OS_MACOS
- } else if (*it == QLatin1String("-s") || *it == QLatin1String("--sign")) {
- ++it;
- if (it == args.end() || it->startsWith(QLatin1String("-")))
- return printErrorAndUsageAndExit(QString::fromLatin1("Error: No code signing identity specified."));
- signingIdentity = *it;
-#endif
- } else {
- if (it->startsWith(QLatin1String("-"))) {
- return printErrorAndUsageAndExit(QString::fromLatin1("Error: Unknown option \"%1\" used. Maybe you "
- "are using an old syntax.").arg(*it));
- } else if (target.isEmpty()) {
- target = *it;
-#ifdef Q_OS_WIN
- if (!target.endsWith(suffix))
- target = target + suffix;
-#endif
- } else {
- return printErrorAndUsageAndExit(QString::fromLatin1("Error: You are using an old syntax please add the "
- "component name with the include option")
- .arg(*it));
- }
- }
- }
-
- if (onlineOnly && offlineOnly) {
- return printErrorAndUsageAndExit(QString::fromLatin1("You cannot use --online-only and "
- "--offline-only at the same time."));
- }
-
- if (onlineOnly) {
- filteredPackages.append(QLatin1String("X_fake_filter_component_for_online_only_installer_X"));
- ftype = QInstallerTools::Include;
- }
-
- if (target.isEmpty() && !compileResource)
- return printErrorAndUsageAndExit(QString::fromLatin1("Error: Target parameter missing."));
-
- if (configFile.isEmpty())
- return printErrorAndUsageAndExit(QString::fromLatin1("Error: No configuration file selected."));
-
- if (packagesDirectories.isEmpty() && repositoryDirectories.isEmpty())
- return printErrorAndUsageAndExit(QString::fromLatin1("Error: Both Package directory and Repository parameters missing."));
-
- qDebug() << "Parsed arguments, ok.";
-
- Input input;
- int exitCode = EXIT_FAILURE;
- QTemporaryDir tmp;
- tmp.setAutoRemove(false);
- const QString tmpMetaDir = tmp.path();
- QTemporaryDir tmp2;
- tmp2.setAutoRemove(false);
- const QString tmpRepoDir = tmp2.path();
- try {
- const Settings settings = Settings::fromFileAndPrefix(configFile, QFileInfo(configFile)
- .absolutePath());
-
- // Note: the order here is important
-
- QInstallerTools::PackageInfoVector packages;
-
- // 1; update the list of available compressed packages
- if (!repositoryDirectories.isEmpty()) {
- // 1.1; search packages
- QInstallerTools::PackageInfoVector precompressedPackages = QInstallerTools::createListOfRepositoryPackages(repositoryDirectories,
- &filteredPackages, ftype);
- // 1.2; add to common vector
- packages.append(precompressedPackages);
- }
-
- // 2; update the list of available prepared packages
- if (!packagesDirectories.isEmpty()) {
- // 2.1; search packages
- QInstallerTools::PackageInfoVector preparedPackages = QInstallerTools::createListOfPackages(packagesDirectories,
- &filteredPackages, ftype);
- // 2.2; copy the packages data and setup the packages vector with the files we copied,
- // must happen before copying meta data because files will be compressed if
- // needed and meta data generation relies on this
- QInstallerTools::copyComponentData(packagesDirectories, tmpRepoDir, &preparedPackages);
- // 2.3; add to common vector
- packages.append(preparedPackages);
- }
-
- // 3; copy the meta data of the available packages, generate Updates.xml
- QInstallerTools::copyMetaData(tmpMetaDir, tmpRepoDir, packages, settings
- .applicationName(), settings.version(), QStringList());
-
- // 4; copy the configuration file and and icons etc.
- copyConfigData(configFile, tmpMetaDir + QLatin1String("/installer-config"));
- {
- QSettings confInternal(tmpMetaDir + QLatin1String("/config/config-internal.ini")
- , QSettings::IniFormat);
- // assume offline installer if there are no repositories and no
- //--online-only not set
- offlineOnly = offlineOnly | settings.repositories().isEmpty();
- if (onlineOnly)
- offlineOnly = !onlineOnly;
- confInternal.setValue(QLatin1String("offlineOnly"), offlineOnly);
- }
-
-#ifdef Q_OS_MACOS
- // on mac, we enforce building a bundle
- if (!target.endsWith(QLatin1String(".app")) && !target.endsWith(QLatin1String(".dmg")))
- target += QLatin1String(".app");
-#endif
- if (!compileResource) {
- // 5; put the copied resources into a resource file
- QInstaller::ResourceCollection metaCollection("QResources");
- metaCollection.appendResource(createDefaultResourceFile(tmpMetaDir,
- generateTemporaryFileName()));
- metaCollection.appendResources(createBinaryResourceFiles(resources));
- input.manager.insertCollection(metaCollection);
-
- input.packages = packages;
- input.outputPath = target;
- input.installerExePath = templateBinary;
-
- qDebug() << "Creating the binary";
- exitCode = assemble(input, settings, signingIdentity);
- } else {
- createDefaultResourceFile(tmpMetaDir, QDir::currentPath() + QLatin1String("/update.rcc"));
- exitCode = EXIT_SUCCESS;
- }
- } catch (const Error &e) {
- QFile::remove(input.outputPath);
- std::cerr << "Caught exception: " << e.message() << std::endl;
- } catch (...) {
- QFile::remove(input.outputPath);
- std::cerr << "Unknown exception caught" << std::endl;
- }
-
- qDebug() << "Cleaning up...";
- const QInstaller::ResourceCollection collection = input.manager.collectionByName("QResources");
- foreach (const QSharedPointer<QInstaller::Resource> &resource, collection.resources())
- QFile::remove(QString::fromUtf8(resource->name()));
- QInstaller::removeDirectory(tmpMetaDir, true);
- QInstaller::removeDirectory(tmpRepoDir, true);
-
- return exitCode;
-}
diff --git a/tools/binarycreator/binarycreator.pro b/tools/binarycreator/binarycreator.pro
index ddde5e984..994de83c1 100644
--- a/tools/binarycreator/binarycreator.pro
+++ b/tools/binarycreator/binarycreator.pro
@@ -1,6 +1,6 @@
TEMPLATE = app
TARGET = binarycreator
-INCLUDEPATH += . .. rcc ../common
+INCLUDEPATH += . ..
include(../../installerfw.pri)
@@ -9,12 +9,7 @@ QT += qml xml
CONFIG += console
DESTDIR = $$IFW_APP_PATH
-SOURCES = binarycreator.cpp \
- rcc/rcc.cpp \
- rcc/rccmain.cpp \
- ../common/repositorygen.cpp
-HEADERS = rcc/rcc.h
-RESOURCES += binarycreator.qrc
+SOURCES = main.cpp
macx:include(../../no_app_bundle.pri)
diff --git a/tools/binarycreator/binarycreator.qrc b/tools/binarycreator/binarycreator.qrc
deleted file mode 100644
index b64e3a21a..000000000
--- a/tools/binarycreator/binarycreator.qrc
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE RCC><RCC version="1.0">
-<qresource>
- <file>resources/default_icon_mac.icns</file>
- <file>resources/copylibsintobundle.sh</file>
- <file alias="resources/installerbase.ico">../../src/sdk/installerbase.ico</file>
-</qresource>
-</RCC>
diff --git a/tools/binarycreator/main.cpp b/tools/binarycreator/main.cpp
new file mode 100644
index 000000000..b5a0ae4f7
--- /dev/null
+++ b/tools/binarycreator/main.cpp
@@ -0,0 +1,210 @@
+/**************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#include <binarycreator.h>
+#include <init.h>
+#include <utils.h>
+
+#include <QtCore/QDebug>
+
+#include <iostream>
+
+using namespace QInstaller;
+
+static void printUsage()
+{
+ QString suffix;
+#ifdef Q_OS_WIN
+ suffix = QLatin1String(".exe");
+#endif
+ const QString appName = QFileInfo(QCoreApplication::applicationFilePath()).fileName();
+ std::cout << "Usage: " << appName << " [options] target" << std::endl;
+ std::cout << std::endl;
+ std::cout << "Options:" << std::endl;
+
+ std::cout << " -t|--template file Use file as installer template binary" << std::endl;
+ std::cout << " If this parameter is not given, the template used" << std::endl;
+ std::cout << " defaults to installerbase." << std::endl;
+
+ QInstallerTools::printRepositoryGenOptions();
+
+ std::cout << " -c|--config file The file containing the installer configuration" << std::endl;
+
+ std::cout << " -n|--online-only Do not add any package into the installer" << std::endl;
+ std::cout << " (for online only installers)" << std::endl;
+
+ std::cout << " -f|--offline-only Forces the installer to act as an offline installer, " << std::endl;
+ std::cout << " i.e. never access online repositories" << std::endl;
+
+ std::cout << " -r|--resources r1,.,rn include the given resource files into the binary" << std::endl;
+
+ std::cout << " -v|--verbose Verbose output" << std::endl;
+ std::cout << " -rcc|--compile-resource Compiles the default resource and outputs the result into"
+ << std::endl;
+ std::cout << " 'update.rcc' in the current path." << std::endl;
+#ifdef Q_OS_MACOS
+ std::cout << " -s|--sign identity Sign generated app bundle using the given code " << std::endl;
+ std::cout << " signing identity" << std::endl;
+#endif
+ std::cout << std::endl;
+ std::cout << "Packages are to be found in the current working directory and get listed as "
+ "their names" << std::endl << std::endl;
+ std::cout << "Example (offline installer):" << std::endl;
+ char sep = QDir::separator().toLatin1();
+ std::cout << " " << appName << " --offline-only -c installer-config" << sep << "config.xml -p "
+ "packages-directory -t installerbase" << suffix << " SDKInstaller" << suffix << std::endl;
+ std::cout << "Creates an offline installer for the SDK, containing all dependencies." << std::endl;
+ std::cout << std::endl;
+ std::cout << "Example (online installer):" << std::endl;
+ std::cout << " " << appName << " -c installer-config" << sep << "config.xml -p packages-directory "
+ "-e org.qt-project.sdk.qt,org.qt-project.qtcreator -t installerbase" << suffix << " SDKInstaller"
+ << suffix << std::endl;
+ std::cout << std::endl;
+ std::cout << "Creates an installer for the SDK without qt and qt creator." << std::endl;
+ std::cout << std::endl;
+ std::cout << "Example update.rcc:" << std::endl;
+ std::cout << " " << appName << " -c installer-config" << sep << "config.xml -p packages-directory "
+ "-rcc" << std::endl;
+}
+
+static int printErrorAndUsageAndExit(const QString &err)
+{
+ std::cerr << qPrintable(err) << std::endl << std::endl;
+ printUsage();
+ return EXIT_FAILURE;
+}
+
+int main(int argc, char **argv)
+{
+ QCoreApplication app(argc, argv);
+
+ QInstaller::init();
+
+ QInstallerTools::BinaryCreatorArgs parsedArgs;
+
+ parsedArgs.templateBinary = QLatin1String("installerbase");
+ QString suffix;
+#ifdef Q_OS_WIN
+ suffix = QLatin1String(".exe");
+ parsedArgs.templateBinary = parsedArgs.templateBinary + suffix;
+#endif
+ if (!QFileInfo(parsedArgs.templateBinary).exists())
+ parsedArgs.templateBinary = QString::fromLatin1("%1/%2").arg(qApp->applicationDirPath(), parsedArgs.templateBinary);
+
+ const QStringList args = app.arguments().mid(1);
+ for (QStringList::const_iterator it = args.begin(); it != args.end(); ++it) {
+ if (*it == QLatin1String("-h") || *it == QLatin1String("--help")) {
+ printUsage();
+ return 0;
+ } else if (*it == QLatin1String("-p") || *it == QLatin1String("--packages")) {
+ ++it;
+ if (it == args.end()) {
+ return printErrorAndUsageAndExit(QString::fromLatin1("Error: Packages parameter missing argument."));
+ }
+ parsedArgs.packagesDirectories.append(*it);
+ } else if (*it == QLatin1String("--repository")) {
+ ++it;
+ if (it == args.end()) {
+ return printErrorAndUsageAndExit(QString::fromLatin1("Error: Repository parameter missing argument."));
+ }
+ parsedArgs.repositoryDirectories.append(*it);
+ } else if (*it == QLatin1String("-e") || *it == QLatin1String("--exclude")) {
+ ++it;
+ if (!parsedArgs.filteredPackages.isEmpty())
+ return printErrorAndUsageAndExit(QString::fromLatin1("Error: --include and --exclude are mutually "
+ "exclusive. Use either one or the other."));
+ if (it == args.end() || it->startsWith(QLatin1String("-")))
+ return printErrorAndUsageAndExit(QString::fromLatin1("Error: Package to exclude missing."));
+ parsedArgs.filteredPackages = it->split(QLatin1Char(','));
+ } else if (*it == QLatin1String("-i") || *it == QLatin1String("--include")) {
+ ++it;
+ if (!parsedArgs.filteredPackages.isEmpty())
+ return printErrorAndUsageAndExit(QString::fromLatin1("Error: --include and --exclude are mutually "
+ "exclusive. Use either one or the other."));
+ if (it == args.end() || it->startsWith(QLatin1String("-")))
+ return printErrorAndUsageAndExit(QString::fromLatin1("Error: Package to include missing."));
+ parsedArgs.filteredPackages = it->split(QLatin1Char(','));
+ parsedArgs.ftype = QInstallerTools::Include;
+ }
+ else if (*it == QLatin1String("-v") || *it == QLatin1String("--verbose")) {
+ QInstaller::setVerbose(true);
+ } else if (*it == QLatin1String("-n") || *it == QLatin1String("--online-only")) {
+ parsedArgs.onlineOnly = true;
+ } else if (*it == QLatin1String("-f") || *it == QLatin1String("--offline-only")) {
+ parsedArgs.offlineOnly = true;
+ } else if (*it == QLatin1String("-t") || *it == QLatin1String("--template")) {
+ ++it;
+ if (it == args.end()) {
+ return printErrorAndUsageAndExit(QString::fromLatin1("Error: Template parameter missing argument."));
+ }
+ parsedArgs.templateBinary = *it;
+ } else if (*it == QLatin1String("-c") || *it == QLatin1String("--config")) {
+ ++it;
+ if (it == args.end())
+ return printErrorAndUsageAndExit(QString::fromLatin1("Error: Config parameter missing argument."));
+ parsedArgs.configFile = *it;
+ } else if (*it == QLatin1String("-r") || *it == QLatin1String("--resources")) {
+ ++it;
+ if (it == args.end() || it->startsWith(QLatin1String("-")))
+ return printErrorAndUsageAndExit(QString::fromLatin1("Error: Resource files to include are missing."));
+ parsedArgs.resources = it->split(QLatin1Char(','));
+ } else if (*it == QLatin1String("--ignore-translations")
+ || *it == QLatin1String("--ignore-invalid-packages")) {
+ continue;
+ } else if (*it == QLatin1String("-rcc") || *it == QLatin1String("--compile-resource")) {
+ parsedArgs.compileResource = true;
+#ifdef Q_OS_MACOS
+ } else if (*it == QLatin1String("-s") || *it == QLatin1String("--sign")) {
+ ++it;
+ if (it == args.end() || it->startsWith(QLatin1String("-")))
+ return printErrorAndUsageAndExit(QString::fromLatin1("Error: No code signing identity specified."));
+ parsedArgs.signingIdentity = *it;
+#endif
+ } else {
+ if (it->startsWith(QLatin1String("-"))) {
+ return printErrorAndUsageAndExit(QString::fromLatin1("Error: Unknown option \"%1\" used. Maybe you "
+ "are using an old syntax.").arg(*it));
+ } else if (parsedArgs.target.isEmpty()) {
+ parsedArgs.target = *it;
+ } else {
+ return printErrorAndUsageAndExit(QString::fromLatin1("Error: You are using an old syntax please add the "
+ "component name with the include option")
+ .arg(*it));
+ }
+ }
+ }
+
+ QString errorMsg;
+ if (QInstallerTools::createBinary(parsedArgs, errorMsg) == EXIT_FAILURE) {
+ if (!errorMsg.isEmpty())
+ printErrorAndUsageAndExit(errorMsg);
+
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+}
diff --git a/tools/binarycreator/rcc/qcorecmdlineargs_p.h b/tools/binarycreator/rcc/qcorecmdlineargs_p.h
deleted file mode 100644
index 9ea85de8a..000000000
--- a/tools/binarycreator/rcc/qcorecmdlineargs_p.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QCORECMDLINEARGS_P_H
-#define QCORECMDLINEARGS_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "QtCore/qstring.h"
-#include "QtCore/qstringlist.h"
-
-QT_BEGIN_NAMESPACE
-
-static inline QStringList qCmdLineArgs(int argc, char *argv[])
-{
- QStringList args;
- for (int i = 0; i != argc; ++i)
- args += QString::fromLocal8Bit(argv[i]);
- return args;
-}
-
-
-QT_END_NAMESPACE
-
-#endif // QCORECMDLINEARGS_WIN_P_H
diff --git a/tools/binarycreator/rcc/rcc.cpp b/tools/binarycreator/rcc/rcc.cpp
deleted file mode 100644
index 10b7cbc4f..000000000
--- a/tools/binarycreator/rcc/rcc.cpp
+++ /dev/null
@@ -1,1038 +0,0 @@
-/**************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Installer Framework.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-**************************************************************************/
-
-#include "rcc.h"
-
-#include <QtCore/QByteArray>
-#include <QtCore/QDateTime>
-#include <QtCore/QDebug>
-#include <QtCore/QDir>
-#include <QtCore/QDirIterator>
-#include <QtCore/QFile>
-#include <QtCore/QIODevice>
-#include <QtCore/QLocale>
-#include <QtCore/QRegExp>
-#include <QtCore/QStack>
-
-#include <QXmlStreamReader>
-
-QT_BEGIN_NAMESPACE
-
-enum {
- CONSTANT_USENAMESPACE = 1,
- CONSTANT_COMPRESSLEVEL_DEFAULT = -1,
- CONSTANT_COMPRESSTHRESHOLD_DEFAULT = 70
-};
-
-
-#define writeString(s) write(s, sizeof(s))
-
-void RCCResourceLibrary::write(const char *str, int len)
-{
- --len; // trailing \0 on string literals...
- int n = m_out.size();
- m_out.resize(n + len);
- memcpy(m_out.data() + n, str, len);
-}
-
-void RCCResourceLibrary::writeByteArray(const QByteArray &other)
-{
- m_out.append(other);
-}
-
-static inline QString msgOpenReadFailed(const QString &fname, const QString &why)
-{
- return QString::fromUtf8("Unable to open %1 for reading: %2\n").arg(fname).arg(why);
-}
-
-
-///////////////////////////////////////////////////////////
-//
-// RCCFileInfo
-//
-///////////////////////////////////////////////////////////
-
-class RCCFileInfo
-{
-public:
- enum Flags
- {
- NoFlags = 0x00,
- Compressed = 0x01,
- Directory = 0x02
- };
-
- RCCFileInfo(const QString &name = QString(), const QFileInfo &fileInfo = QFileInfo(),
- QLocale::Language language = QLocale::C,
- QLocale::Country country = QLocale::AnyCountry,
- uint flags = NoFlags,
- int compressLevel = CONSTANT_COMPRESSLEVEL_DEFAULT,
- int compressThreshold = CONSTANT_COMPRESSTHRESHOLD_DEFAULT);
- ~RCCFileInfo();
-
- QString resourceName() const;
-
-public:
- qint64 writeDataBlob(RCCResourceLibrary &lib, qint64 offset, QString *errorMessage);
- qint64 writeDataName(RCCResourceLibrary &, qint64 offset);
- void writeDataInfo(RCCResourceLibrary &lib);
-
- int m_flags;
- QString m_name;
- QLocale::Language m_language;
- QLocale::Country m_country;
- QFileInfo m_fileInfo;
- RCCFileInfo *m_parent;
- QHash<QString, RCCFileInfo*> m_children;
- int m_compressLevel;
- int m_compressThreshold;
-
- qint64 m_nameOffset;
- qint64 m_dataOffset;
- qint64 m_childOffset;
-};
-
-RCCFileInfo::RCCFileInfo(const QString &name, const QFileInfo &fileInfo,
- QLocale::Language language, QLocale::Country country, uint flags,
- int compressLevel, int compressThreshold)
-{
- m_name = name;
- m_fileInfo = fileInfo;
- m_language = language;
- m_country = country;
- m_flags = flags;
- m_parent = nullptr;
- m_nameOffset = 0;
- m_dataOffset = 0;
- m_childOffset = 0;
- m_compressLevel = compressLevel;
- m_compressThreshold = compressThreshold;
-}
-
-RCCFileInfo::~RCCFileInfo()
-{
- qDeleteAll(m_children);
-}
-
-QString RCCFileInfo::resourceName() const
-{
- QString resource = m_name;
- for (RCCFileInfo *p = m_parent; p; p = p->m_parent)
- resource = resource.prepend(p->m_name + QLatin1Char('/'));
- return QLatin1Char(':') + resource;
-}
-
-void RCCFileInfo::writeDataInfo(RCCResourceLibrary &lib)
-{
- const bool text = (lib.m_format == RCCResourceLibrary::C_Code);
- //some info
- if (text) {
- if (m_language != QLocale::C) {
- lib.writeString(" // ");
- lib.writeByteArray(resourceName().toLocal8Bit());
- lib.writeString(" [");
- lib.writeByteArray(QByteArray::number(m_country));
- lib.writeString("::");
- lib.writeByteArray(QByteArray::number(m_language));
- lib.writeString("[\n ");
- } else {
- lib.writeString(" // ");
- lib.writeByteArray(resourceName().toLocal8Bit());
- lib.writeString("\n ");
- }
- }
-
- //pointer data
- if (m_flags & RCCFileInfo::Directory) {
- // name offset
- lib.writeNumber4(m_nameOffset);
-
- // flags
- lib.writeNumber2(m_flags);
-
- // child count
- lib.writeNumber4(m_children.size());
-
- // first child offset
- lib.writeNumber4(m_childOffset);
- } else {
- // name offset
- lib.writeNumber4(m_nameOffset);
-
- // flags
- lib.writeNumber2(m_flags);
-
- // locale
- lib.writeNumber2(m_country);
- lib.writeNumber2(m_language);
-
- //data offset
- lib.writeNumber4(m_dataOffset);
- }
- if (text)
- lib.writeChar('\n');
-}
-
-qint64 RCCFileInfo::writeDataBlob(RCCResourceLibrary &lib, qint64 offset,
- QString *errorMessage)
-{
- const bool text = (lib.m_format == RCCResourceLibrary::C_Code);
-
- //capture the offset
- m_dataOffset = offset;
-
- //find the data to be written
- QFile file(m_fileInfo.absoluteFilePath());
- if (!file.open(QFile::ReadOnly)) {
- *errorMessage = msgOpenReadFailed(m_fileInfo.absoluteFilePath(), file.errorString());
- return 0;
- }
- QByteArray data = file.readAll();
-
-#ifndef QT_NO_COMPRESS
- // Check if compression is useful for this file
- if (m_compressLevel != 0 && data.size() != 0) {
- QByteArray compressed =
- qCompress(reinterpret_cast<uchar *>(data.data()), data.size(), m_compressLevel);
-
- int compressRatio = int(100.0 * (data.size() - compressed.size()) / data.size());
- if (compressRatio >= m_compressThreshold) {
- data = compressed;
- m_flags |= Compressed;
- }
- }
-#endif // QT_NO_COMPRESS
-
- // some info
- if (text) {
- lib.writeString(" // ");
- lib.writeByteArray(m_fileInfo.absoluteFilePath().toLocal8Bit());
- lib.writeString("\n ");
- }
-
- // write the length
-
- lib.writeNumber4(data.size());
- if (text)
- lib.writeString("\n ");
- offset += 4;
-
- // write the payload
- const char *p = data.constData();
- if (text) {
- for (int i = data.size(), j = 0; --i >= 0; --j) {
- lib.writeHex(*p++);
- if (j == 0) {
- lib.writeString("\n ");
- j = 16;
- }
- }
- } else {
- for (int i = data.size(); --i >= 0; )
- lib.writeChar(*p++);
- }
- offset += data.size();
-
- // done
- if (text)
- lib.writeString("\n ");
- return offset;
-}
-
-qint64 RCCFileInfo::writeDataName(RCCResourceLibrary &lib, qint64 offset)
-{
- const bool text = (lib.m_format == RCCResourceLibrary::C_Code);
-
- // capture the offset
- m_nameOffset = offset;
-
- // some info
- if (text) {
- lib.writeString(" // ");
- lib.writeByteArray(m_name.toLocal8Bit());
- lib.writeString("\n ");
- }
-
- // write the length
- lib.writeNumber2(m_name.length());
- if (text)
- lib.writeString("\n ");
- offset += 2;
-
- // write the hash
- lib.writeNumber4(qt_hash(m_name));
- if (text)
- lib.writeString("\n ");
- offset += 4;
-
- // write the m_name
- const QChar *unicode = m_name.unicode();
- for (int i = 0; i < m_name.length(); ++i) {
- lib.writeNumber2(unicode[i].unicode());
- if (text && i % 16 == 0)
- lib.writeString("\n ");
- }
- offset += m_name.length()*2;
-
- // done
- if (text)
- lib.writeString("\n ");
- return offset;
-}
-
-
-///////////////////////////////////////////////////////////
-//
-// RCCResourceLibrary
-//
-///////////////////////////////////////////////////////////
-
-RCCResourceLibrary::Strings::Strings() :
- TAG_RCC(QLatin1String("RCC")),
- TAG_RESOURCE(QLatin1String("qresource")),
- TAG_FILE(QLatin1String("file")),
- ATTRIBUTE_LANG(QLatin1String("lang")),
- ATTRIBUTE_PREFIX(QLatin1String("prefix")),
- ATTRIBUTE_ALIAS(QLatin1String("alias")),
- ATTRIBUTE_THRESHOLD(QLatin1String("threshold")),
- ATTRIBUTE_COMPRESS(QLatin1String("compress"))
-{
-}
-
-RCCResourceLibrary::RCCResourceLibrary()
- : m_root(nullptr),
- m_format(C_Code),
- m_verbose(false),
- m_compressLevel(CONSTANT_COMPRESSLEVEL_DEFAULT),
- m_compressThreshold(CONSTANT_COMPRESSTHRESHOLD_DEFAULT),
- m_treeOffset(0),
- m_namesOffset(0),
- m_dataOffset(0),
- m_useNameSpace(CONSTANT_USENAMESPACE),
- m_errorDevice(nullptr)
-{
- m_out.reserve(30 * 1000 * 1000);
-}
-
-RCCResourceLibrary::~RCCResourceLibrary()
-{
- delete m_root;
-}
-
-enum RCCXmlTag {
- RccTag,
- ResourceTag,
- FileTag
-};
-
-bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
- const QString &fname, QString currentPath, bool ignoreErrors)
-{
- Q_ASSERT(m_errorDevice);
- const QChar slash = QLatin1Char('/');
- if (!currentPath.isEmpty() && !currentPath.endsWith(slash))
- currentPath += slash;
-
- QXmlStreamReader reader(inputDevice);
- QStack<RCCXmlTag> tokens;
-
- QString prefix;
- QLocale::Language language = QLocale::c().language();
- QLocale::Country country = QLocale::c().country();
- QString alias;
- int compressLevel = m_compressLevel;
- int compressThreshold = m_compressThreshold;
-
- while (!reader.atEnd()) {
- QXmlStreamReader::TokenType t = reader.readNext();
- switch (t) {
- case QXmlStreamReader::StartElement:
- if (reader.name() == m_strings.TAG_RCC) {
- if (!tokens.isEmpty())
- reader.raiseError(QLatin1String("expected <RCC> tag"));
- else
- tokens.push(RccTag);
- } else if (reader.name() == m_strings.TAG_RESOURCE) {
- if (tokens.isEmpty() || tokens.top() != RccTag) {
- reader.raiseError(QLatin1String("unexpected <RESOURCE> tag"));
- } else {
- tokens.push(ResourceTag);
-
- QXmlStreamAttributes attributes = reader.attributes();
- language = QLocale::c().language();
- country = QLocale::c().country();
-
- if (attributes.hasAttribute(m_strings.ATTRIBUTE_LANG)) {
- QString attribute = attributes.value(m_strings.ATTRIBUTE_LANG).toString();
- QLocale lang = QLocale(attribute);
- language = lang.language();
- if (2 == attribute.length()) {
- // Language only
- country = QLocale::AnyCountry;
- } else {
- country = lang.country();
- }
- }
-
- prefix.clear();
- if (attributes.hasAttribute(m_strings.ATTRIBUTE_PREFIX))
- prefix = attributes.value(m_strings.ATTRIBUTE_PREFIX).toString();
- if (!prefix.startsWith(slash))
- prefix.prepend(slash);
- if (!prefix.endsWith(slash))
- prefix += slash;
- }
- } else if (reader.name() == m_strings.TAG_FILE) {
- if (tokens.isEmpty() || tokens.top() != ResourceTag) {
- reader.raiseError(QLatin1String("unexpected <FILE> tag"));
- } else {
- tokens.push(FileTag);
-
- QXmlStreamAttributes attributes = reader.attributes();
- alias.clear();
- if (attributes.hasAttribute(m_strings.ATTRIBUTE_ALIAS))
- alias = attributes.value(m_strings.ATTRIBUTE_ALIAS).toString();
-
- compressLevel = m_compressLevel;
- if (attributes.hasAttribute(m_strings.ATTRIBUTE_COMPRESS))
- compressLevel = attributes.value(m_strings.ATTRIBUTE_COMPRESS).toString().toInt();
-
- compressThreshold = m_compressThreshold;
- if (attributes.hasAttribute(m_strings.ATTRIBUTE_THRESHOLD))
- compressThreshold = attributes.value(m_strings.ATTRIBUTE_THRESHOLD).toString().toInt();
-
- // Special case for -no-compress. Overrides all other settings.
- if (m_compressLevel == -2)
- compressLevel = 0;
- }
- } else {
- reader.raiseError(QString(QLatin1String("unexpected tag: %1")).arg(reader.name().toString()));
- }
- break;
-
- case QXmlStreamReader::EndElement:
- if (reader.name() == m_strings.TAG_RCC) {
- if (!tokens.isEmpty() && tokens.top() == RccTag)
- tokens.pop();
- else
- reader.raiseError(QLatin1String("unexpected closing tag"));
- } else if (reader.name() == m_strings.TAG_RESOURCE) {
- if (!tokens.isEmpty() && tokens.top() == ResourceTag)
- tokens.pop();
- else
- reader.raiseError(QLatin1String("unexpected closing tag"));
- } else if (reader.name() == m_strings.TAG_FILE) {
- if (!tokens.isEmpty() && tokens.top() == FileTag)
- tokens.pop();
- else
- reader.raiseError(QLatin1String("unexpected closing tag"));
- }
- break;
-
- case QXmlStreamReader::Characters:
- if (reader.isWhitespace())
- break;
- if (tokens.isEmpty() || tokens.top() != FileTag) {
- reader.raiseError(QLatin1String("unexpected text"));
- } else {
- QString fileName = reader.text().toString();
- if (fileName.isEmpty()) {
- const QString msg = QString::fromLatin1("RCC: Warning: Null node in XML of '%1'\n").arg(fname);
- m_errorDevice->write(msg.toUtf8());
- }
-
- if (alias.isNull())
- alias = fileName;
-
- alias = QDir::cleanPath(alias);
- while (alias.startsWith(QLatin1String("../")))
- alias.remove(0, 3);
- alias = QDir::cleanPath(m_resourceRoot) + prefix + alias;
-
- QString absFileName = fileName;
- if (QDir::isRelativePath(absFileName))
- absFileName.prepend(currentPath);
- QFileInfo file(absFileName);
- if (!file.exists()) {
- m_failedResources.push_back(absFileName);
- const QString msg = QString::fromLatin1("RCC: Error in '%1': Cannot find file '%2'\n").arg(fname).arg(fileName);
- m_errorDevice->write(msg.toUtf8());
- if (ignoreErrors)
- continue;
- else
- return false;
- } else if (file.isFile()) {
- const bool arc =
- addFile(alias,
- RCCFileInfo(alias.section(slash, -1),
- file,
- language,
- country,
- RCCFileInfo::NoFlags,
- compressLevel,
- compressThreshold)
- );
- if (!arc)
- m_failedResources.push_back(absFileName);
- } else {
- QDir dir;
- if (file.isDir()) {
- dir.setPath(file.filePath());
- } else {
- dir.setPath(file.path());
- dir.setNameFilters(QStringList(file.fileName()));
- if (alias.endsWith(file.fileName()))
- alias = alias.left(alias.length()-file.fileName().length());
- }
- if (!alias.endsWith(slash))
- alias += slash;
- QDirIterator it(dir, QDirIterator::FollowSymlinks|QDirIterator::Subdirectories);
- while (it.hasNext()) {
- it.next();
- QFileInfo child(it.fileInfo());
- if (child.fileName() != QLatin1String(".") && child.fileName() != QLatin1String("..")) {
- const bool arc =
- addFile(alias + child.fileName(),
- RCCFileInfo(child.fileName(),
- child,
- language,
- country,
- child.isDir() ? RCCFileInfo::Directory : RCCFileInfo::NoFlags,
- compressLevel,
- compressThreshold)
- );
- if (!arc)
- m_failedResources.push_back(child.fileName());
- }
- }
- }
- }
- break;
-
- default:
- break;
- }
- }
-
- if (reader.hasError()) {
- if (ignoreErrors)
- return true;
- int errorLine = reader.lineNumber();
- int errorColumn = reader.columnNumber();
- QString errorMessage = reader.errorString();
- QString msg = QString::fromLatin1("RCC Parse Error: '%1' Line: %2 Column: %3 [%4]\n").arg(fname).arg(errorLine).arg(errorColumn).arg(errorMessage);
- m_errorDevice->write(msg.toUtf8());
- return false;
- }
-
- if (m_root == nullptr) {
- const QString msg = QString::fromUtf8("RCC: Warning: No resources in '%1'.\n").arg(fname);
- m_errorDevice->write(msg.toUtf8());
- if (!ignoreErrors && m_format == Binary) {
- // create dummy entry, otherwise loading with QResource will crash
- m_root = new RCCFileInfo(QString(), QFileInfo(),
- QLocale::C, QLocale::AnyCountry, RCCFileInfo::Directory);
- }
- }
-
- return true;
-}
-
-bool RCCResourceLibrary::addFile(const QString &alias, const RCCFileInfo &file)
-{
- Q_ASSERT(m_errorDevice);
- if (file.m_fileInfo.size() > 0xffffffff) {
- const QString msg = QString::fromUtf8("File too big: %1\n").arg(file.m_fileInfo.absoluteFilePath());
- m_errorDevice->write(msg.toUtf8());
- return false;
- }
- if (!m_root)
- m_root = new RCCFileInfo(QString(), QFileInfo(), QLocale::C, QLocale::AnyCountry, RCCFileInfo::Directory);
-
- RCCFileInfo *parent = m_root;
- const QStringList nodes = alias.split(QLatin1Char('/'));
- for (int i = 1; i < nodes.size()-1; ++i) {
- const QString node = nodes.at(i);
- if (node.isEmpty())
- continue;
- if (!parent->m_children.contains(node)) {
- RCCFileInfo *s = new RCCFileInfo(node, QFileInfo(), QLocale::C, QLocale::AnyCountry, RCCFileInfo::Directory);
- s->m_parent = parent;
- parent->m_children.insert(node, s);
- parent = s;
- } else {
- parent = parent->m_children[node];
- }
- }
-
- const QString filename = nodes.at(nodes.size()-1);
- RCCFileInfo *s = new RCCFileInfo(file);
- s->m_parent = parent;
- if (parent->m_children.contains(filename)) {
- foreach (const QString &fileName, m_fileNames)
- qWarning("%s: Warning: potential duplicate alias detected: '%s'",
- qPrintable(fileName), qPrintable(filename));
- }
- parent->m_children.insertMulti(filename, s);
- return true;
-}
-
-void RCCResourceLibrary::reset()
-{
- if (m_root) {
- delete m_root;
- m_root = nullptr;
- }
- m_errorDevice = nullptr;
- m_failedResources.clear();
-}
-
-
-bool RCCResourceLibrary::readFiles(bool ignoreErrors, QIODevice &errorDevice)
-{
- reset();
- m_errorDevice = &errorDevice;
- //read in data
- if (m_verbose) {
- const QString msg = QString::fromUtf8("Processing %1 files [%2]\n")
- .arg(m_fileNames.size()).arg(static_cast<int>(ignoreErrors));
- m_errorDevice->write(msg.toUtf8());
- }
- for (int i = 0; i < m_fileNames.size(); ++i) {
- QFile fileIn;
- QString fname = m_fileNames.at(i);
- QString pwd;
- if (fname == QLatin1String("-")) {
- fname = QLatin1String("(stdin)");
- pwd = QDir::currentPath();
- fileIn.setFileName(fname);
- if (!fileIn.open(stdin, QIODevice::ReadOnly)) {
- m_errorDevice->write(msgOpenReadFailed(fname, fileIn.errorString()).toUtf8());
- return false;
- }
- } else {
- pwd = QFileInfo(fname).path();
- fileIn.setFileName(fname);
- if (!fileIn.open(QIODevice::ReadOnly)) {
- m_errorDevice->write(msgOpenReadFailed(fname, fileIn.errorString()).toUtf8());
- return false;
- }
- }
- if (m_verbose) {
- const QString msg = QString::fromUtf8("Interpreting %1\n").arg(fname);
- m_errorDevice->write(msg.toUtf8());
- }
-
- if (!interpretResourceFile(&fileIn, fname, pwd, ignoreErrors))
- return false;
- }
- return true;
-}
-
-QStringList RCCResourceLibrary::dataFiles() const
-{
- QStringList ret;
- QStack<RCCFileInfo*> pending;
-
- if (!m_root)
- return ret;
- pending.push(m_root);
- while (!pending.isEmpty()) {
- RCCFileInfo *file = pending.pop();
- for (QHash<QString, RCCFileInfo*>::iterator it = file->m_children.begin();
- it != file->m_children.end(); ++it) {
- RCCFileInfo *child = it.value();
- if (child->m_flags & RCCFileInfo::Directory)
- pending.push(child);
- ret.append(child->m_fileInfo.filePath());
- }
- }
- return ret;
-}
-
-// Determine map of resource identifier (':/newPrefix/images/p1.png') to file via recursion
-static void resourceDataFileMapRecursion(const RCCFileInfo *m_root, const QString &path, RCCResourceLibrary::ResourceDataFileMap &m)
-{
- typedef QHash<QString, RCCFileInfo*>::const_iterator ChildConstIterator;
- const QChar slash = QLatin1Char('/');
- const ChildConstIterator cend = m_root->m_children.constEnd();
- for (ChildConstIterator it = m_root->m_children.constBegin(); it != cend; ++it) {
- const RCCFileInfo *child = it.value();
- QString childName = path;
- childName += slash;
- childName += child->m_name;
- if (child->m_flags & RCCFileInfo::Directory) {
- resourceDataFileMapRecursion(child, childName, m);
- } else {
- m.insert(childName, child->m_fileInfo.filePath());
- }
- }
-}
-
-RCCResourceLibrary::ResourceDataFileMap RCCResourceLibrary::resourceDataFileMap() const
-{
- ResourceDataFileMap rc;
- if (m_root)
- resourceDataFileMapRecursion(m_root, QString(QLatin1Char(':')), rc);
- return rc;
-}
-
-bool RCCResourceLibrary::output(QIODevice &outDevice, QIODevice &errorDevice)
-{
- m_errorDevice = &errorDevice;
- //write out
- if (m_verbose)
- m_errorDevice->write("Outputting code\n");
- if (!writeHeader()) {
- m_errorDevice->write("Cannot write header\n");
- return false;
- }
- if (m_root) {
- if (!writeDataBlobs()) {
- m_errorDevice->write("Cannot write data blobs.\n");
- return false;
- }
- if (!writeDataNames()) {
- m_errorDevice->write("Cannot write file names\n");
- return false;
- }
- if (!writeDataStructure()) {
- m_errorDevice->write("Cannot write data tree\n");
- return false;
- }
- }
- if (!writeInitializer()) {
- m_errorDevice->write("Cannot write footer\n");
- return false;
- }
- outDevice.write(m_out.constData(), m_out.size());
- return true;
-}
-
-void RCCResourceLibrary::writeHex(quint8 tmp)
-{
- const char digits[] = "0123456789abcdef";
- writeChar('0');
- writeChar('x');
- if (tmp < 16) {
- writeChar(digits[tmp]);
- } else {
- writeChar(digits[tmp >> 4]);
- writeChar(digits[tmp & 0xf]);
- }
- writeChar(',');
-}
-
-void RCCResourceLibrary::writeNumber2(quint16 number)
-{
- if (m_format == RCCResourceLibrary::Binary) {
- writeChar(number >> 8);
- writeChar(number);
- } else {
- writeHex(number >> 8);
- writeHex(number);
- }
-}
-
-void RCCResourceLibrary::writeNumber4(quint32 number)
-{
- if (m_format == RCCResourceLibrary::Binary) {
- writeChar(number >> 24);
- writeChar(number >> 16);
- writeChar(number >> 8);
- writeChar(number);
- } else {
- writeHex(number >> 24);
- writeHex(number >> 16);
- writeHex(number >> 8);
- writeHex(number);
- }
-}
-
-bool RCCResourceLibrary::writeHeader()
-{
- if (m_format == C_Code) {
- writeString("/****************************************************************************\n");
- writeString("** Resource object code\n");
- writeString("**\n");
- writeString("** Created: ");
- writeByteArray(QDateTime::currentDateTime().toString().toLatin1());
- writeString("\n** by: The Resource Compiler for Qt version ");
- writeByteArray(QT_VERSION_STR);
- writeString("\n**\n");
- writeString("** WARNING! All changes made in this file will be lost!\n");
- writeString( "*****************************************************************************/\n\n");
- writeString("#include <QtCore/qglobal.h>\n\n");
- } else if (m_format == Binary) {
- writeString("qres");
- writeNumber4(0);
- writeNumber4(0);
- writeNumber4(0);
- writeNumber4(0);
- }
- return true;
-}
-
-bool RCCResourceLibrary::writeDataBlobs()
-{
- Q_ASSERT(m_errorDevice);
- if (m_format == C_Code)
- writeString("static const unsigned char qt_resource_data[] = {\n");
- else if (m_format == Binary)
- m_dataOffset = m_out.size();
- QStack<RCCFileInfo*> pending;
-
- if (!m_root)
- return false;
-
- pending.push(m_root);
- qint64 offset = 0;
- QString errorMessage;
- while (!pending.isEmpty()) {
- RCCFileInfo *file = pending.pop();
- for (QHash<QString, RCCFileInfo*>::iterator it = file->m_children.begin();
- it != file->m_children.end(); ++it) {
- RCCFileInfo *child = it.value();
- if (child->m_flags & RCCFileInfo::Directory)
- pending.push(child);
- else {
- offset = child->writeDataBlob(*this, offset, &errorMessage);
- if (offset == 0) {
- m_errorDevice->write(errorMessage.toUtf8());
- return false;
- }
- }
- }
- }
- if (m_format == C_Code)
- writeString("\n};\n\n");
- return true;
-}
-
-bool RCCResourceLibrary::writeDataNames()
-{
- if (m_format == C_Code)
- writeString("static const unsigned char qt_resource_name[] = {\n");
- else if (m_format == Binary)
- m_namesOffset = m_out.size();
-
- QHash<QString, int> names;
- QStack<RCCFileInfo*> pending;
-
- if (!m_root)
- return false;
-
- pending.push(m_root);
- qint64 offset = 0;
- while (!pending.isEmpty()) {
- RCCFileInfo *file = pending.pop();
- for (QHash<QString, RCCFileInfo*>::iterator it = file->m_children.begin();
- it != file->m_children.end(); ++it) {
- RCCFileInfo *child = it.value();
- if (child->m_flags & RCCFileInfo::Directory)
- pending.push(child);
- if (names.contains(child->m_name)) {
- child->m_nameOffset = names.value(child->m_name);
- } else {
- names.insert(child->m_name, offset);
- offset = child->writeDataName(*this, offset);
- }
- }
- }
- if (m_format == C_Code)
- writeString("\n};\n\n");
- return true;
-}
-
-static bool qt_rcc_compare_hash(const RCCFileInfo *left, const RCCFileInfo *right)
-{
- return qt_hash(left->m_name) < qt_hash(right->m_name);
-}
-
-bool RCCResourceLibrary::writeDataStructure()
-{
- if (m_format == C_Code)
- writeString("static const unsigned char qt_resource_struct[] = {\n");
- else if (m_format == Binary)
- m_treeOffset = m_out.size();
- QStack<RCCFileInfo*> pending;
-
- if (!m_root)
- return false;
-
- //calculate the child offsets (flat)
- pending.push(m_root);
- int offset = 1;
- while (!pending.isEmpty()) {
- RCCFileInfo *file = pending.pop();
- file->m_childOffset = offset;
-
- //sort by hash value for binary lookup
- QList<RCCFileInfo*> m_children = file->m_children.values();
- qSort(m_children.begin(), m_children.end(), qt_rcc_compare_hash);
-
- //write out the actual data now
- for (int i = 0; i < m_children.size(); ++i) {
- RCCFileInfo *child = m_children.at(i);
- ++offset;
- if (child->m_flags & RCCFileInfo::Directory)
- pending.push(child);
- }
- }
-
- //write out the structure (ie iterate again!)
- pending.push(m_root);
- m_root->writeDataInfo(*this);
- while (!pending.isEmpty()) {
- RCCFileInfo *file = pending.pop();
-
- //sort by hash value for binary lookup
- QList<RCCFileInfo*> m_children = file->m_children.values();
- qSort(m_children.begin(), m_children.end(), qt_rcc_compare_hash);
-
- //write out the actual data now
- for (int i = 0; i < m_children.size(); ++i) {
- RCCFileInfo *child = m_children.at(i);
- child->writeDataInfo(*this);
- if (child->m_flags & RCCFileInfo::Directory)
- pending.push(child);
- }
- }
- if (m_format == C_Code)
- writeString("\n};\n\n");
-
- return true;
-}
-
-void RCCResourceLibrary::writeMangleNamespaceFunction(const QByteArray &name)
-{
- if (m_useNameSpace) {
- writeString("QT_MANGLE_NAMESPACE(");
- writeByteArray(name);
- writeChar(')');
- } else {
- writeByteArray(name);
- }
-}
-
-void RCCResourceLibrary::writeAddNamespaceFunction(const QByteArray &name)
-{
- if (m_useNameSpace) {
- writeString("QT_PREPEND_NAMESPACE(");
- writeByteArray(name);
- writeChar(')');
- } else {
- writeByteArray(name);
- }
-}
-
-bool RCCResourceLibrary::writeInitializer()
-{
- if (m_format == C_Code) {
- //write("\nQT_BEGIN_NAMESPACE\n");
- QString initName = m_initName;
- if (!initName.isEmpty()) {
- initName.prepend(QLatin1Char('_'));
- initName.replace(QRegExp(QLatin1String("[^a-zA-Z0-9_]")), QLatin1String("_"));
- }
-
- //init
- if (m_useNameSpace)
- writeString("QT_BEGIN_NAMESPACE\n\n");
- if (m_root) {
- writeString("extern Q_CORE_EXPORT bool qRegisterResourceData\n "
- "(int, const unsigned char *, "
- "const unsigned char *, const unsigned char *);\n\n");
- writeString("extern Q_CORE_EXPORT bool qUnregisterResourceData\n "
- "(int, const unsigned char *, "
- "const unsigned char *, const unsigned char *);\n\n");
- }
- if (m_useNameSpace)
- writeString("QT_END_NAMESPACE\n\n\n");
- QString initResources = QLatin1String("qInitResources");
- initResources += initName;
- writeString("int ");
- writeMangleNamespaceFunction(initResources.toLatin1());
- writeString("()\n{\n");
-
- if (m_root) {
- writeString(" ");
- writeAddNamespaceFunction("qRegisterResourceData");
- writeString("\n (0x01, qt_resource_struct, "
- "qt_resource_name, qt_resource_data);\n");
- }
- writeString(" return 1;\n");
- writeString("}\n\n");
- writeString("Q_CONSTRUCTOR_FUNCTION(");
- writeMangleNamespaceFunction(initResources.toLatin1());
- writeString(")\n\n");
-
- //cleanup
- QString cleanResources = QLatin1String("qCleanupResources");
- cleanResources += initName;
- writeString("int ");
- writeMangleNamespaceFunction(cleanResources.toLatin1());
- writeString("()\n{\n");
- if (m_root) {
- writeString(" ");
- writeAddNamespaceFunction("qUnregisterResourceData");
- writeString("\n (0x01, qt_resource_struct, "
- "qt_resource_name, qt_resource_data);\n");
- }
- writeString(" return 1;\n");
- writeString("}\n\n");
- writeString("Q_DESTRUCTOR_FUNCTION(");
- writeMangleNamespaceFunction(cleanResources.toLatin1());
- writeString(")\n\n");
- } else if (m_format == Binary) {
- int i = 4;
- char *p = m_out.data();
- p[i++] = 0; // 0x01
- p[i++] = 0;
- p[i++] = 0;
- p[i++] = 1;
-
- p[i++] = (m_treeOffset >> 24) & 0xff;
- p[i++] = (m_treeOffset >> 16) & 0xff;
- p[i++] = (m_treeOffset >> 8) & 0xff;
- p[i++] = (m_treeOffset >> 0) & 0xff;
-
- p[i++] = (m_dataOffset >> 24) & 0xff;
- p[i++] = (m_dataOffset >> 16) & 0xff;
- p[i++] = (m_dataOffset >> 8) & 0xff;
- p[i++] = (m_dataOffset >> 0) & 0xff;
-
- p[i++] = (m_namesOffset >> 24) & 0xff;
- p[i++] = (m_namesOffset >> 16) & 0xff;
- p[i++] = (m_namesOffset >> 8) & 0xff;
- p[i++] = (m_namesOffset >> 0) & 0xff;
- }
- return true;
-}
-
-QT_END_NAMESPACE
diff --git a/tools/binarycreator/rcc/rcc.h b/tools/binarycreator/rcc/rcc.h
deleted file mode 100644
index ecf408dbc..000000000
--- a/tools/binarycreator/rcc/rcc.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/**************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Installer Framework.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-**************************************************************************/
-
-#ifndef RCC_H
-#define RCC_H
-
-#include <QtCore/QStringList>
-#include <QtCore/QHash>
-#include <QtCore/QString>
-
-QT_BEGIN_NAMESPACE
-
-class RCCFileInfo;
-class QIODevice;
-class QTextStream;
-
-
-class RCCResourceLibrary
-{
- RCCResourceLibrary(const RCCResourceLibrary &);
- RCCResourceLibrary &operator=(const RCCResourceLibrary &);
-
-public:
- RCCResourceLibrary();
- ~RCCResourceLibrary();
-
- bool output(QIODevice &out, QIODevice &errorDevice);
-
- bool readFiles(bool ignoreErrors, QIODevice &errorDevice);
-
- enum Format { Binary, C_Code };
- void setFormat(Format f) { m_format = f; }
- Format format() const { return m_format; }
-
- void setInputFiles(const QStringList &files) { m_fileNames = files; }
- QStringList inputFiles() const { return m_fileNames; }
-
- QStringList dataFiles() const;
-
- // Return a map of resource identifier (':/newPrefix/images/p1.png') to file.
- typedef QHash<QString, QString> ResourceDataFileMap;
- ResourceDataFileMap resourceDataFileMap() const;
-
- void setVerbose(bool b) { m_verbose = b; }
- bool verbose() const { return m_verbose; }
-
- void setInitName(const QString &name) { m_initName = name; }
- QString initName() const { return m_initName; }
-
- void setCompressLevel(int c) { m_compressLevel = c; }
- int compressLevel() const { return m_compressLevel; }
-
- void setCompressThreshold(int t) { m_compressThreshold = t; }
- int compressThreshold() const { return m_compressThreshold; }
-
- void setResourceRoot(const QString &root) { m_resourceRoot = root; }
- QString resourceRoot() const { return m_resourceRoot; }
-
- void setUseNameSpace(bool v) { m_useNameSpace = v; }
- bool useNameSpace() const { return m_useNameSpace; }
-
- QStringList failedResources() const { return m_failedResources; }
-
-private:
- struct Strings {
- Strings();
- const QString TAG_RCC;
- const QString TAG_RESOURCE;
- const QString TAG_FILE;
- const QString ATTRIBUTE_LANG;
- const QString ATTRIBUTE_PREFIX;
- const QString ATTRIBUTE_ALIAS;
- const QString ATTRIBUTE_THRESHOLD;
- const QString ATTRIBUTE_COMPRESS;
- };
- friend class RCCFileInfo;
- void reset();
- bool addFile(const QString &alias, const RCCFileInfo &file);
- bool interpretResourceFile(QIODevice *inputDevice, const QString &file,
- QString currentPath = QString(), bool ignoreErrors = false);
- bool writeHeader();
- bool writeDataBlobs();
- bool writeDataNames();
- bool writeDataStructure();
- bool writeInitializer();
- void writeMangleNamespaceFunction(const QByteArray &name);
- void writeAddNamespaceFunction(const QByteArray &name);
- void writeHex(quint8 number);
- void writeNumber2(quint16 number);
- void writeNumber4(quint32 number);
- void writeChar(char c) { m_out.append(c); }
- void writeByteArray(const QByteArray &);
- void write(const char *, int len);
-
- const Strings m_strings;
- RCCFileInfo *m_root;
- QStringList m_fileNames;
- QString m_resourceRoot;
- QString m_initName;
- Format m_format;
- bool m_verbose;
- int m_compressLevel;
- int m_compressThreshold;
- int m_treeOffset;
- int m_namesOffset;
- int m_dataOffset;
- bool m_useNameSpace;
- QStringList m_failedResources;
- QIODevice *m_errorDevice;
- QByteArray m_out;
-};
-
-QT_END_NAMESPACE
-
-#endif // RCC_H
diff --git a/tools/binarycreator/rcc/rccmain.cpp b/tools/binarycreator/rcc/rccmain.cpp
deleted file mode 100644
index 8c33997dd..000000000
--- a/tools/binarycreator/rcc/rccmain.cpp
+++ /dev/null
@@ -1,239 +0,0 @@
-/**************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Installer Framework.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-**************************************************************************/
-
-#include <rcc.h>
-#include "qcorecmdlineargs_p.h"
-
-#include <QDebug>
-#include <QDir>
-#include <QFile>
-#include <QFileInfo>
-#include <QTextStream>
-
-QT_BEGIN_NAMESPACE
-
-void showHelp(const QString &argv0, const QString &error)
-{
- fprintf(stderr, "Qt resource compiler\n");
- if (!error.isEmpty())
- fprintf(stderr, "%s: %s\n", qPrintable(argv0), qPrintable(error));
- fprintf(stderr, "Usage: %s [options] <inputs>\n\n"
- "Options:\n"
- " -o file write output to file rather than stdout\n"
- " -name name create an external initialization function with name\n"
- " -threshold level threshold to consider compressing files\n"
- " -compress level compress input files by level\n"
- " -root path prefix resource access path with root path\n"
- " -no-compress disable all compression\n"
- " -binary output a binary file for use as a dynamic resource\n"
- " -namespace turn off namespace macros\n"
- " -project Output a resource file containing all\n"
- " files from the current directory\n"
- " -version display version\n"
- " -help display this information\n",
- qPrintable(argv0));
-}
-
-void dumpRecursive(const QDir &dir, QTextStream &out)
-{
- QFileInfoList entries = dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot
- | QDir::NoSymLinks);
- foreach (const QFileInfo &entry, entries) {
- if (entry.isDir()) {
- dumpRecursive(entry.filePath(), out);
- } else {
- out << QLatin1String("<file>")
- << entry.filePath()
- << QLatin1String("</file>\n");
- }
- }
-}
-
-int createProject(const QString &outFileName)
-{
- QFile file;
- bool isOk = false;
- if (outFileName.isEmpty()) {
- isOk = file.open(stdout, QFile::WriteOnly | QFile::Text);
- } else {
- file.setFileName(outFileName);
- isOk = file.open(QFile::WriteOnly | QFile::Text);
- }
- if (!isOk) {
- fprintf(stderr, "Unable to open %s: %s\n",
- outFileName.isEmpty() ? qPrintable(outFileName) : "standard output",
- qPrintable(file.errorString()));
- return 1;
- }
-
- QTextStream out(&file);
- out << QLatin1String("<!DOCTYPE RCC><RCC version=\"1.0\">\n"
- "<qresource>\n");
-
- // use "." as dir to get relative file paths
- dumpRecursive(QDir(QLatin1String(".")), out);
-
- out << QLatin1String("</qresource>\n"
- "</RCC>\n");
-
- return 0;
-}
-
-int runRcc(int argc, char *argv[])
-{
- QString outFilename;
- bool helpRequested = false;
- bool list = false;
- bool projectRequested = false;
- QStringList filenamesIn;
-
- QStringList args = qCmdLineArgs(argc, argv);
-
- RCCResourceLibrary library;
-
- //parse options
- QString errorMsg;
- for (int i = 1; i < args.count() && errorMsg.isEmpty(); i++) {
- if (args[i].isEmpty())
- continue;
- if (args[i][0] == QLatin1Char('-')) { // option
- QString opt = args[i];
- if (opt == QLatin1String("-o")) {
- if (!(i < argc-1)) {
- errorMsg = QLatin1String("Missing output name");
- break;
- }
- outFilename = args[++i];
- } else if (opt == QLatin1String("-name")) {
- if (!(i < argc-1)) {
- errorMsg = QLatin1String("Missing target name");
- break;
- }
- library.setInitName(args[++i]);
- } else if (opt == QLatin1String("-root")) {
- if (!(i < argc-1)) {
- errorMsg = QLatin1String("Missing root path");
- break;
- }
- library.setResourceRoot(QDir::cleanPath(args[++i]));
- if (library.resourceRoot().isEmpty()
- || library.resourceRoot().at(0) != QLatin1Char('/'))
- errorMsg = QLatin1String("Root must start with a /");
- } else if (opt == QLatin1String("-compress")) {
- if (!(i < argc-1)) {
- errorMsg = QLatin1String("Missing compression level");
- break;
- }
- library.setCompressLevel(args[++i].toInt());
- } else if (opt == QLatin1String("-threshold")) {
- if (!(i < argc-1)) {
- errorMsg = QLatin1String("Missing compression threshold");
- break;
- }
- library.setCompressThreshold(args[++i].toInt());
- } else if (opt == QLatin1String("-binary")) {
- library.setFormat(RCCResourceLibrary::Binary);
- } else if (opt == QLatin1String("-namespace")) {
- library.setUseNameSpace(!library.useNameSpace());
- } else if (opt == QLatin1String("-verbose")) {
- library.setVerbose(true);
- } else if (opt == QLatin1String("-list")) {
- list = true;
- } else if (opt == QLatin1String("-version") || opt == QLatin1String("-v")) {
- fprintf(stderr, "Qt Resource Compiler version %s\n", QT_VERSION_STR);
- return 1;
- } else if (opt == QLatin1String("-help") || opt == QLatin1String("-h")) {
- helpRequested = true;
- } else if (opt == QLatin1String("-no-compress")) {
- library.setCompressLevel(-2);
- } else if (opt == QLatin1String("-project")) {
- projectRequested = true;
- } else {
- errorMsg = QString::fromLatin1("Unknown option: '%1'").arg(args[i]);
- }
- } else {
- if (!QFile::exists(args[i])) {
- qWarning("%s: File does not exist '%s'",
- qPrintable(args[0]), qPrintable(args[i]));
- return 1;
- }
- filenamesIn.append(args[i]);
- }
- }
-
- if (projectRequested && !helpRequested) {
- return createProject(outFilename);
- }
-
- if (!filenamesIn.size() || !errorMsg.isEmpty() || helpRequested) {
- showHelp(args[0], errorMsg);
- return 1;
- }
- QFile errorDevice;
- errorDevice.open(stderr, QIODevice::WriteOnly|QIODevice::Text);
-
- if (library.verbose())
- errorDevice.write("Qt resource compiler\n");
-
- library.setInputFiles(filenamesIn);
-
- if (!library.readFiles(list, errorDevice))
- return 1;
-
- // open output
- QFile out;
- QIODevice::OpenMode mode = QIODevice::WriteOnly;
- if (library.format() == RCCResourceLibrary::C_Code)
- mode |= QIODevice::Text;
-
- if (outFilename.isEmpty() || outFilename == QLatin1String("-")) {
- // using this overload close() only flushes.
- out.open(stdout, mode);
- } else {
- out.setFileName(outFilename);
- if (!out.open(mode)) {
- const QString msg = QString::fromUtf8("Unable to open %1 for writing: %2\n").arg(outFilename).arg(out.errorString());
- errorDevice.write(msg.toUtf8());
- return 1;
- }
- }
-
- // do the task
- if (list) {
- const QStringList data = library.dataFiles();
- for (int i = 0; i < data.size(); ++i) {
- out.write(qPrintable(QDir::cleanPath(data.at(i))));
- out.write("\n");
- }
- return 0;
- }
-
- return library.output(out, errorDevice) ? 0 : 1;
-}
-
-QT_END_NAMESPACE
diff --git a/tools/binarycreator/resources/copylibsintobundle.sh b/tools/binarycreator/resources/copylibsintobundle.sh
deleted file mode 100644
index 1ad5da4db..000000000
--- a/tools/binarycreator/resources/copylibsintobundle.sh
+++ /dev/null
@@ -1,189 +0,0 @@
-#!/bin/sh
-#############################################################################
-##
-## Copyright (C) 2017 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is part of the Qt Installer Framework.
-##
-## $QT_BEGIN_LICENSE:GPL-EXCEPT$
-## 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 The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 3 as published by the Free Software
-## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
-
-
-# this script puts all libs directly needed by the bundle into it
-
-QTDIR=""
-IS_DEBUG=0
-HAVE_CORE=0
-HAVE_SVG=0
-HAVE_PHONON=0
-HAVE_SCRIPT=0
-HAVE_SQL=0
-HAVE_WEBKIT=0
-
-function handleFile()
-{
- local FILE=$1
- local BUNDLE=$2
-
- # all dynamic libs directly needed by the bundle, which are not in /System/Library or in /usr/lib (which are system default libs, which we don't want)
- local LIBS=`xcrun otool -L $FILE | grep -v 'executable_path' | grep -v '/System/Library' | grep -v '/usr/lib' | grep '/' | sed -ne 's,^ *\(.*\) (.*,\1,p'`
-
- local lib
- for lib in $LIBS; do
- local NAME=`basename $lib`
-
- if echo $NAME | grep 'QtCore' >/dev/null; then
- HAVE_CORE=1
- QTDIR=`echo $lib | sed -ne 's,^\(.*\)/lib/[^/]*QtCore.*$,\1,p'`
- if echo $NAME | grep 'debug' >/dev/null; then
- IS_DEBUG=1
- fi
- elif echo $NAME | grep 'QtSvg' >/dev/null; then
- HAVE_SVG=1
- elif echo $NAME | grep 'phonon' >/dev/null; then
- HAVE_PHONON=1
- elif echo $NAME | grep 'QtScript' >/dev/null; then
- HAVE_SCRIPT=1
- elif echo $NAME | grep 'QtSql' >/dev/null; then
- HAVE_SQL=1
- elif echo $NAME | grep 'QtWebKit' >/dev/null; then
- HAVE_WEBKIT=1
- fi
-
- if [ `basename $FILE` != $NAME ]; then
-
- # this part handles libraries which are macOS frameworks
- if echo $lib | grep '\.framework' >/dev/null; then
- local FRAMEWORKPATH=`echo $lib | sed -ne 's,\(.*\.framework\).*,\1,p'`
- local FRAMEWORKNAME=`basename $FRAMEWORKPATH`
- local NEWFRAMEWORKPATH=`echo $lib | sed -ne "s,.*\($FRAMEWORKNAME\),\1,p"`
-
- # Qt installed via the precompled binaries...
- if [ $FRAMEWORKPATH = $FRAMEWORKNAME ]; then
- FRAMEWORKPATH="/Library/Frameworks/$FRAMEWORKNAME"
- if [ ! -e "$FRAMEWORKPATH" ]; then
- echo "Framework $FRAMEWORKNAME not found."
- exit 1
- fi
- fi
-
- if [ ! -e "$BUNDLE/Contents/Frameworks/$NEWFRAMEWORKPATH" ]; then
- echo Embedding framework $FRAMEWORKNAME
-
-
- # copy the framework into the bundle
- cp -R $FRAMEWORKPATH $BUNDLE/Contents/Frameworks
- # remove debug libs we've copied
- find $BUNDLE/Contents/Frameworks/$FRAMEWORKNAME -regex '.*_debug\(\.dSYM\)*' | xargs rm -rf
-
- handleFile "$BUNDLE/Contents/Frameworks/$NEWFRAMEWORKPATH" "$BUNDLE"
- fi
- # and inform the dynamic linker about this
- xcrun install_name_tool -change $lib @executable_path/../Frameworks/$NEWFRAMEWORKPATH $FILE
-
-
- # this part handles 'normal' dynamic libraries (.dylib)
- else
- if [ ! -e "$BUNDLE/Contents/Frameworks/$NAME" ]; then
- echo Embedding library $NAME
-
- # Qt installed via the precompled binaries...
- if [ $lib = $NAME ]; then
- lib="/Library/Frameworks/$NAME"
- if [ ! -e "$lib" ]; then
- lib="/usr/lib/$NAME"
- fi
- if [ ! -e "$lib" ]; then
- echo "Library $NAME not found."
- exit 1
- fi
- fi
-
- # copy the lib into the bundle
- cp $lib $BUNDLE/Contents/Frameworks
- handleFile "$BUNDLE/Contents/Frameworks/$NAME" "$BUNDLE"
- fi
-
- # and inform the dynamic linker about this
- xcrun install_name_tool -change $lib @executable_path/../Frameworks/$NAME $FILE
- fi
-
- fi
- done
-}
-
-function handleQtPlugins()
-{
- local PLUGINPATH=$QTDIR/plugins
-
- # QTDIR was not found, then we're using /Developer/Applications/Qt
- if [ "$PLUGINPATH" = "/plugins" ]; then
- PLUGINPATH="/Developer/Applications/Qt/plugins"
- fi
-
- CLASS=$1
- EXECUTABLE=$2
- BUNDLE=$3
- mkdir -p $BUNDLE/Contents/plugins/$CLASS
- echo Add $CLASS plugins
- for plugin in `ls $PLUGINPATH/$CLASS/*`; do
- plugin=`basename $plugin`
- if echo $plugin | grep 'debug' >/dev/null; then
- #if [ $IS_DEBUG -eq 1 ]; then
- cp "$PLUGINPATH/$CLASS/$plugin" $BUNDLE/Contents/plugins/$CLASS
- xcrun install_name_tool -change $plugin @executable_path/../plugins/$CLASS/$plugin $EXECUTABLE
- handleFile $BUNDLE/Contents/plugins/$CLASS/$plugin $BUNDLE
- #fi
- else
- #if [ $IS_DEBUG -eq 0 ]; then
- cp "$PLUGINPATH/$CLASS/$plugin" $BUNDLE/Contents/plugins/$CLASS
- xcrun install_name_tool -change $plugin @executable_path/../plugins/$CLASS/$plugin $EXECUTABLE
- handleFile $BUNDLE/Contents/plugins/$CLASS/$plugin $BUNDLE
- #fi
- fi
- done
-}
-
-# the app bundle we're working with
-BUNDLE=$1
-# the executable inside of the bundle
-EXECUTABLE=$BUNDLE/Contents/MacOS/`xargs < $BUNDLE/Contents/Info.plist | sed -ne 's,.*<key>CFBundleExecutable</key> <string>\([^<]*\)</string>.*,\1,p'`
-
-mkdir -p $BUNDLE/Contents/Frameworks
-
-handleFile $EXECUTABLE $BUNDLE
-
-if [ $HAVE_CORE -eq 1 ]; then
- handleQtPlugins "imageformats" "$EXECUTABLE" "$BUNDLE"
-fi
-if [ $HAVE_SVG -eq 1 ]; then
- handleQtPlugins "iconengines" "$EXECUTABLE" "$BUNDLE"
-fi
-if [ $HAVE_PHONON -eq 1 ]; then
- handleQtPlugins "phonon_backend" "$EXECUTABLE" "$BUNDLE"
-fi
-if [ $HAVE_SQL -eq 1 ]; then
- handleQtPlugins "sqldrivers" "$EXECUTABLE" "$BUNDLE"
-fi
-if [ $HAVE_WEBKIT -eq 1 ]; then
- handleQtPlugins "codecs" "$EXECUTABLE" "$BUNDLE"
-fi
diff --git a/tools/binarycreator/resources/default_icon_mac.icns b/tools/binarycreator/resources/default_icon_mac.icns
deleted file mode 100644
index 8d870d649..000000000
--- a/tools/binarycreator/resources/default_icon_mac.icns
+++ /dev/null
Binary files differ
diff --git a/tools/common/repositorygen.cpp b/tools/common/repositorygen.cpp
deleted file mode 100644
index 45ea0a541..000000000
--- a/tools/common/repositorygen.cpp
+++ /dev/null
@@ -1,965 +0,0 @@
-/**************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Installer Framework.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-**************************************************************************/
-#include "repositorygen.h"
-
-#include <constants.h>
-#include <fileio.h>
-#include <fileutils.h>
-#include <errors.h>
-#include <globals.h>
-#include <lib7z_create.h>
-#include <lib7z_extract.h>
-#include <lib7z_facade.h>
-#include <lib7z_list.h>
-#include <settings.h>
-#include <qinstallerglobal.h>
-#include <utils.h>
-#include <scriptengine.h>
-
-#include <updater.h>
-
-#include <QtCore/QDirIterator>
-#include <QtCore/QRegExp>
-
-#include <QtXml/QDomDocument>
-#include <QTemporaryDir>
-
-#include <iostream>
-
-using namespace QInstaller;
-using namespace QInstallerTools;
-
-void QInstallerTools::printRepositoryGenOptions()
-{
- std::cout << " -p|--packages dir The directory containing the available packages." << std::endl;
- std::cout << " This entry can be given multiple times." << std::endl;
- std::cout << " --repository dir The directory containing the available repository." << std::endl;
- std::cout << " This entry can be given multiple times." << std::endl;
-
- std::cout << " -e|--exclude p1,...,pn Exclude the given packages." << std::endl;
- std::cout << " -i|--include p1,...,pn Include the given packages and their dependencies" << std::endl;
- std::cout << " from the repository." << std::endl;
-
- std::cout << " --ignore-translations Do not use any translation" << std::endl;
- std::cout << " --ignore-invalid-packages Ignore all invalid packages instead of aborting." << std::endl;
- std::cout << " --ignore-invalid-repositories Ignore all invalid repositories instead of aborting." << std::endl;
-}
-
-QString QInstallerTools::makePathAbsolute(const QString &path)
-{
- if (QFileInfo(path).isRelative())
- return QDir::current().absoluteFilePath(path);
- return path;
-}
-
-void QInstallerTools::copyWithException(const QString &source, const QString &target, const QString &kind)
-{
- qDebug() << "Copying associated" << kind << "file" << source;
-
- const QFileInfo targetFileInfo(target);
- if (!targetFileInfo.dir().exists())
- QInstaller::mkpath(targetFileInfo.absolutePath());
-
- QFile sourceFile(source);
- if (!sourceFile.copy(target)) {
- qDebug() << "failed!\n";
- throw QInstaller::Error(QString::fromLatin1("Cannot copy the %1 file from \"%2\" to \"%3\": "
- "%4").arg(kind, QDir::toNativeSeparators(source), QDir::toNativeSeparators(target),
- /* in case of an existing target the error String does not show the file */
- (targetFileInfo.exists() ? QLatin1String("Target already exist.") : sourceFile.errorString())));
- }
-
- qDebug() << "done.";
-}
-
-static QStringList copyFilesFromNode(const QString &parentNode, const QString &childNode, const QString &attr,
- const QString &kind, const QDomNode &package, const PackageInfo &info, const QString &targetDir)
-{
- QStringList copiedFiles;
- const QDomNodeList nodes = package.firstChildElement(parentNode).childNodes();
- for (int i = 0; i < nodes.count(); ++i) {
- const QDomNode node = nodes.at(i);
- if (node.nodeName() != childNode)
- continue;
-
- const QDir dir(QString::fromLatin1("%1/meta").arg(info.directory));
- const QString filter = attr.isEmpty() ? node.toElement().text() : node.toElement().attribute(attr);
- const QStringList files = dir.entryList(QStringList(filter), QDir::Files);
- if (files.isEmpty()) {
- throw QInstaller::Error(QString::fromLatin1("Cannot find any %1 matching \"%2\" "
- "while copying %1 of \"%3\".").arg(kind, filter, info.name));
- }
-
- foreach (const QString &file, files) {
- const QString source(QString::fromLatin1("%1/meta/%2").arg(info.directory, file));
- const QString target(QString::fromLatin1("%1/%2/%3").arg(targetDir, info.name, file));
- copyWithException(source, target, kind);
- copiedFiles.append(file);
- }
- }
- return copiedFiles;
-}
-
-void QInstallerTools::copyMetaData(const QString &_targetDir, const QString &metaDataDir,
- const PackageInfoVector &packages, const QString &appName, const QString &appVersion,
- const QStringList &uniteMetadatas)
-{
- const QString targetDir = makePathAbsolute(_targetDir);
- if (!QFile::exists(targetDir))
- QInstaller::mkpath(targetDir);
-
- bool componentMetaExtracted = false;
- QDomDocument doc;
- QDomElement root;
- QFile existingUpdatesXml(QFileInfo(metaDataDir, QLatin1String("Updates.xml")).absoluteFilePath());
- if (existingUpdatesXml.open(QIODevice::ReadOnly) && doc.setContent(&existingUpdatesXml)) {
- root = doc.documentElement();
- // remove entry for this component from existing Updates.xml, if found
- foreach (const PackageInfo &info, packages) {
- const QDomNodeList packageNodes = root.childNodes();
- for (int i = packageNodes.count() - 1; i >= 0; --i) {
- const QDomNode node = packageNodes.at(i);
- if (node.nodeName() != QLatin1String("PackageUpdate"))
- continue;
- if (node.firstChildElement(QLatin1String("Name")).text() != info.name)
- continue;
- root.removeChild(node);
- }
- }
- existingUpdatesXml.close();
- } else {
- root = doc.createElement(QLatin1String("Updates"));
- root.appendChild(doc.createElement(QLatin1String("ApplicationName"))).appendChild(doc
- .createTextNode(appName));
- root.appendChild(doc.createElement(QLatin1String("ApplicationVersion"))).appendChild(doc
- .createTextNode(appVersion));
- root.appendChild(doc.createElement(QLatin1String("Checksum"))).appendChild(doc
- .createTextNode(QLatin1String("true")));
- }
-
- foreach (const PackageInfo &info, packages) {
- if (info.metaFile.isEmpty() && info.metaNode.isEmpty()) {
- if (!QDir(targetDir).mkpath(info.name))
- throw QInstaller::Error(QString::fromLatin1("Cannot create directory \"%1\".").arg(info.name));
-
- const QString packageXmlPath = QString::fromLatin1("%1/meta/package.xml").arg(info.directory);
- qDebug() << "Copy meta data for package" << info.name << "using" << packageXmlPath;
-
- QFile file(packageXmlPath);
- QInstaller::openForRead(&file);
-
- QString errMsg;
- int line = 0;
- int column = 0;
- QDomDocument packageXml;
- if (!packageXml.setContent(&file, &errMsg, &line, &column)) {
- throw QInstaller::Error(QString::fromLatin1("Cannot parse \"%1\": line: %2, column: %3: %4 (%5)")
- .arg(QDir::toNativeSeparators(packageXmlPath)).arg(line).arg(column).arg(errMsg, info.name));
- }
-
- QDomElement update = doc.createElement(QLatin1String("PackageUpdate"));
- QDomNode nameElement = update.appendChild(doc.createElement(QLatin1String("Name")));
- nameElement.appendChild(doc.createTextNode(info.name));
-
- // list of current unused or later transformed tags
- QStringList blackList;
- blackList << QLatin1String("UserInterfaces") << QLatin1String("Translations") <<
- QLatin1String("Licenses") << QLatin1String("Name");
-
- bool foundDefault = false;
- bool foundVirtual = false;
- bool foundDisplayName = false;
- bool foundDownloadableArchives = false;
- bool foundCheckable = false;
- const QDomNode package = packageXml.firstChildElement(QLatin1String("Package"));
- const QDomNodeList childNodes = package.childNodes();
- for (int i = 0; i < childNodes.count(); ++i) {
- const QDomNode node = childNodes.at(i);
- const QString key = node.nodeName();
-
- if (key == QLatin1String("Default"))
- foundDefault = true;
- if (key == QLatin1String("Virtual"))
- foundVirtual = true;
- if (key == QLatin1String("DisplayName"))
- foundDisplayName = true;
- if (key == QLatin1String("DownloadableArchives"))
- foundDownloadableArchives = true;
- if (key == QLatin1String("Checkable"))
- foundCheckable = true;
- if (node.isComment() || blackList.contains(key))
- continue; // just skip comments and some tags...
-
- QDomElement element = doc.createElement(key);
- for (int j = 0; j < node.attributes().size(); ++j) {
- element.setAttribute(node.attributes().item(j).toAttr().name(),
- node.attributes().item(j).toAttr().value());
- }
- update.appendChild(element).appendChild(doc.createTextNode(node.toElement().text()));
- }
-
- if (foundDefault && foundVirtual) {
- throw QInstaller::Error(QString::fromLatin1("Error: <Default> and <Virtual> elements are "
- "mutually exclusive in file \"%1\".").arg(QDir::toNativeSeparators(packageXmlPath)));
- }
-
- if (foundDefault && foundCheckable) {
- throw QInstaller::Error(QString::fromLatin1("Error: <Default> and <Checkable>"
- "elements are mutually exclusive in file \"%1\".")
- .arg(QDir::toNativeSeparators(packageXmlPath)));
- }
-
- if (!foundDisplayName) {
- qWarning() << "No DisplayName tag found at" << info.name << ", using component Name instead.";
- QDomElement displayNameElement = doc.createElement(QLatin1String("DisplayName"));
- update.appendChild(displayNameElement).appendChild(doc.createTextNode(info.name));
- }
-
- // get the size of the data
- quint64 componentSize = 0;
- quint64 compressedComponentSize = 0;
-
- const QDir::Filters filters = QDir::Files | QDir::NoDotAndDotDot;
- const QDir dataDir = QString::fromLatin1("%1/%2/data").arg(metaDataDir, info.name);
- const QFileInfoList entries = dataDir.exists() ? dataDir.entryInfoList(filters | QDir::Dirs)
- : QDir(QString::fromLatin1("%1/%2").arg(metaDataDir, info.name)).entryInfoList(filters);
- qDebug() << "calculate size of directory" << dataDir.absolutePath();
- foreach (const QFileInfo &fi, entries) {
- try {
- if (fi.isDir()) {
- QDirIterator recursDirIt(fi.filePath(), QDirIterator::Subdirectories);
- while (recursDirIt.hasNext()) {
- recursDirIt.next();
- const quint64 size = QInstaller::fileSize(recursDirIt.fileInfo());
- componentSize += size;
- compressedComponentSize += size;
- }
- } else if (Lib7z::isSupportedArchive(fi.filePath())) {
- // if it's an archive already, list its files and sum the uncompressed sizes
- QFile archive(fi.filePath());
- compressedComponentSize += archive.size();
- QInstaller::openForRead(&archive);
-
- QVector<Lib7z::File>::const_iterator fileIt;
- const QVector<Lib7z::File> files = Lib7z::listArchive(&archive);
- for (fileIt = files.begin(); fileIt != files.end(); ++fileIt)
- componentSize += fileIt->uncompressedSize;
- } else {
- // otherwise just add its size
- const quint64 size = QInstaller::fileSize(fi);
- componentSize += size;
- compressedComponentSize += size;
- }
- } catch (const QInstaller::Error &error) {
- qDebug().noquote() << error.message();
- } catch(...) {
- // ignore, that's just about the sizes - and size doesn't matter, you know?
- }
- }
-
- QDomElement fileElement = doc.createElement(QLatin1String("UpdateFile"));
- fileElement.setAttribute(QLatin1String("UncompressedSize"), componentSize);
- fileElement.setAttribute(QLatin1String("CompressedSize"), compressedComponentSize);
- // adding the OS attribute to be compatible with old sdks
- fileElement.setAttribute(QLatin1String("OS"), QLatin1String("Any"));
- update.appendChild(fileElement);
-
- root.appendChild(update);
-
- // copy script file
- const QString script = package.firstChildElement(QLatin1String("Script")).text();
- if (!script.isEmpty()) {
- QFile scriptFile(QString::fromLatin1("%1/meta/%2").arg(info.directory, script));
- if (!scriptFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
- throw QInstaller::Error(QString::fromLatin1("Cannot open component script at \"%1\".")
- .arg(QDir::toNativeSeparators(scriptFile.fileName())));
- }
-
- const QString scriptContent = QLatin1String("(function() {")
- + QString::fromUtf8(scriptFile.readAll())
- + QLatin1String(";"
- " if (typeof Component == \"undefined\")"
- " throw \"Missing Component constructor. Please check your script.\";"
- "})();");
-
- // if the user isn't aware of the downloadable archives value we will add it automatically later
- foundDownloadableArchives |= scriptContent.contains(QLatin1String("addDownloadableArchive"))
- || scriptContent.contains(QLatin1String("removeDownloadableArchive"));
-
- static QInstaller::ScriptEngine testScriptEngine;
- const QJSValue value = testScriptEngine.evaluate(scriptContent, scriptFile.fileName());
- if (value.isError()) {
- throw QInstaller::Error(QString::fromLatin1("Exception while loading component "
- "script at \"%1\": %2").arg(QDir::toNativeSeparators(scriptFile.fileName()),
- value.toString().isEmpty() ? QString::fromLatin1("Unknown error.") :
- value.toString() + QStringLiteral(" on line number: ") +
- value.property(QStringLiteral("lineNumber")).toString()));
- }
-
- const QString toLocation(QString::fromLatin1("%1/%2/%3").arg(targetDir, info.name, script));
- copyWithException(scriptFile.fileName(), toLocation, QInstaller::scScript);
- }
-
- // write DownloadableArchives tag if that is missed by the user
- if (!foundDownloadableArchives && !info.copiedFiles.isEmpty()) {
- QStringList realContentFiles;
- foreach (const QString &filePath, info.copiedFiles) {
- if (!filePath.endsWith(QLatin1String(".sha1"), Qt::CaseInsensitive)) {
- const QString fileName = QFileInfo(filePath).fileName();
- // remove unnecessary version string from filename and add it to the list
- realContentFiles.append(fileName.mid(info.version.count()));
- }
- }
-
- update.appendChild(doc.createElement(QLatin1String("DownloadableArchives"))).appendChild(doc
- .createTextNode(realContentFiles.join(QChar::fromLatin1(','))));
- }
-
- // copy user interfaces
- const QStringList uiFiles = copyFilesFromNode(QLatin1String("UserInterfaces"),
- QLatin1String("UserInterface"), QString(), QLatin1String("user interface"), package, info,
- targetDir);
- if (!uiFiles.isEmpty()) {
- update.appendChild(doc.createElement(QLatin1String("UserInterfaces"))).appendChild(doc
- .createTextNode(uiFiles.join(QChar::fromLatin1(','))));
- }
-
- // copy translations
- QStringList trFiles;
- if (!qApp->arguments().contains(QString::fromLatin1("--ignore-translations"))) {
- trFiles = copyFilesFromNode(QLatin1String("Translations"), QLatin1String("Translation"),
- QString(), QLatin1String("translation"), package, info, targetDir);
- if (!trFiles.isEmpty()) {
- update.appendChild(doc.createElement(QLatin1String("Translations"))).appendChild(doc
- .createTextNode(trFiles.join(QChar::fromLatin1(','))));
- }
- }
-
- // copy license files
- const QStringList licenses = copyFilesFromNode(QLatin1String("Licenses"), QLatin1String("License"),
- QLatin1String("file"), QLatin1String("license"), package, info, targetDir);
- if (!licenses.isEmpty()) {
- foreach (const QString &trFile, trFiles) {
- // Copy translated license file based on the assumption that it will have the same base name
- // as the original license plus the file name of an existing translation file without suffix.
- foreach (const QString &license, licenses) {
- const QFileInfo untranslated(license);
- const QString translatedLicense = QString::fromLatin1("%2_%3.%4").arg(untranslated
- .baseName(), QFileInfo(trFile).baseName(), untranslated.completeSuffix());
- // ignore copy failure, that's just about the translations
- QFile::copy(QString::fromLatin1("%1/meta/%2").arg(info.directory).arg(translatedLicense),
- QString::fromLatin1("%1/%2/%3").arg(targetDir, info.name, translatedLicense));
- }
- }
- update.appendChild(package.firstChildElement(QLatin1String("Licenses")).cloneNode());
- }
- } else {
- // Extract metadata from archive
- if (!info.metaFile.isEmpty()){
- QFile metaFile(info.metaFile);
- QInstaller::openForRead(&metaFile);
- Lib7z::extractArchive(&metaFile, targetDir);
- componentMetaExtracted = true;
- }
-
- // Restore "PackageUpdate" node;
- QDomDocument update;
- if (!update.setContent(info.metaNode)) {
- throw QInstaller::Error(QString::fromLatin1("Cannot restore \"PackageUpdate\" description for node %1").arg(info.name));
- }
-
- root.appendChild(update.documentElement());
- }
- }
-
- if (!componentMetaExtracted) {
- foreach (const QString uniteMetadata, uniteMetadatas) {
- QFile metaFile(QFileInfo(metaDataDir, uniteMetadata).absoluteFilePath());
- QInstaller::openForRead(&metaFile);
- Lib7z::extractArchive(&metaFile, targetDir);
- }
- }
-
- doc.appendChild(root);
-
- QFile targetUpdatesXml(targetDir + QLatin1String("/Updates.xml"));
- QInstaller::openForWrite(&targetUpdatesXml);
- QInstaller::blockingWrite(&targetUpdatesXml, doc.toByteArray());
-}
-
-PackageInfoVector QInstallerTools::createListOfPackages(const QStringList &packagesDirectories,
- QStringList *packagesToFilter, FilterType filterType)
-{
- qDebug() << "Collecting information about available packages...";
-
- bool ignoreInvalidPackages = qApp->arguments().contains(QString::fromLatin1("--ignore-invalid-packages"));
-
- PackageInfoVector dict;
- QFileInfoList entries;
- foreach (const QString &packagesDirectory, packagesDirectories)
- entries.append(QDir(packagesDirectory).entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot));
- for (QFileInfoList::const_iterator it = entries.constBegin(); it != entries.constEnd(); ++it) {
- if (filterType == Exclude) {
- // Check for current file in exclude list, if found, skip it and remove it from exclude list
- if (packagesToFilter->contains(it->fileName())) {
- packagesToFilter->removeAll(it->fileName());
- continue;
- }
- } else {
- // Check for current file in include list, if not found, skip it; if found, remove it from include list
- if (!packagesToFilter->contains(it->fileName()))
- continue;
- packagesToFilter->removeAll(it->fileName());
- }
- qDebug() << "Found subdirectory" << it->fileName();
- // because the filter is QDir::Dirs - filename means the name of the subdirectory
- if (it->fileName().contains(QLatin1Char('-'))) {
- qDebug("When using the component \"%s\" as a dependency, "
- "to ensure backward compatibility, you must add a colon symbol at the end, "
- "even if you do not specify a version.",
- qUtf8Printable(it->fileName()));
- }
-
- QFile file(QString::fromLatin1("%1/meta/package.xml").arg(it->filePath()));
- QFileInfo fileInfo(file);
- if (!fileInfo.exists()) {
- if (ignoreInvalidPackages)
- continue;
- throw QInstaller::Error(QString::fromLatin1("Component \"%1\" does not contain a package "
- "description (meta/package.xml is missing).").arg(QDir::toNativeSeparators(it->fileName())));
- }
-
- file.open(QIODevice::ReadOnly);
-
- QDomDocument doc;
- QString error;
- int errorLine = 0;
- int errorColumn = 0;
- if (!doc.setContent(&file, &error, &errorLine, &errorColumn)) {
- if (ignoreInvalidPackages)
- continue;
- throw QInstaller::Error(QString::fromLatin1("Component package description in \"%1\" is invalid. "
- "Error at line: %2, column: %3 -> %4").arg(QDir::toNativeSeparators(fileInfo.absoluteFilePath()),
- QString::number(errorLine),
- QString::number(errorColumn), error));
- }
-
- const QDomElement packageElement = doc.firstChildElement(QLatin1String("Package"));
- const QString name = packageElement.firstChildElement(QLatin1String("Name")).text();
- if (!name.isEmpty() && name != it->fileName()) {
- qWarning().nospace() << "The <Name> tag in the file " << fileInfo.absoluteFilePath()
- << " is ignored - the installer uses the path element right before the 'meta'"
- << " (" << it->fileName() << ")";
- }
-
- QString releaseDate = packageElement.firstChildElement(QLatin1String("ReleaseDate")).text();
- if (releaseDate.isEmpty()) {
- qWarning("Release date for \"%s\" is empty! Using the current date instead.",
- qPrintable(fileInfo.absoluteFilePath()));
- releaseDate = QDate::currentDate().toString(Qt::ISODate);
- }
-
- if (!QDate::fromString(releaseDate, Qt::ISODate).isValid()) {
- if (ignoreInvalidPackages)
- continue;
- throw QInstaller::Error(QString::fromLatin1("Release date for \"%1\" is invalid! <ReleaseDate>%2"
- "</ReleaseDate>. Supported format: YYYY-MM-DD").arg(QDir::toNativeSeparators(fileInfo.absoluteFilePath()),
- releaseDate));
- }
-
- PackageInfo info;
- info.name = it->fileName();
- info.version = packageElement.firstChildElement(QLatin1String("Version")).text();
- // Version cannot start with comparison characters, be an empty string
- // or have whitespaces at the beginning or at the end
- if (!QRegExp(QLatin1String("(?![<=>\\s]+)(.+)")).exactMatch(info.version) ||
- (info.version != info.version.trimmed())) {
- if (ignoreInvalidPackages)
- continue;
- throw QInstaller::Error(QString::fromLatin1("Component version for \"%1\" is invalid! <Version>%2</Version>")
- .arg(QDir::toNativeSeparators(fileInfo.absoluteFilePath()), info.version));
- }
- info.dependencies = packageElement.firstChildElement(QLatin1String("Dependencies")).text()
- .split(QInstaller::commaRegExp(), QString::SkipEmptyParts);
- info.directory = it->filePath();
- dict.push_back(info);
-
- qDebug() << "- it provides the package" << info.name << " - " << info.version;
- }
-
- if (!packagesToFilter->isEmpty() && packagesToFilter->at(0) != QString::fromLatin1(
- "X_fake_filter_component_for_online_only_installer_X")) {
- qWarning() << "The following explicitly given packages could not be found\n in package directory:" << *packagesToFilter;
- }
-
- if (dict.isEmpty())
- qDebug() << "No available packages found at the specified location.";
-
- return dict;
-}
-
-PackageInfoVector QInstallerTools::createListOfRepositoryPackages(const QStringList &repositoryDirectories,
- QStringList *packagesToFilter, FilterType filterType)
-{
- qDebug() << "Collecting information about available repository packages...";
-
- bool ignoreInvalidRepositories = qApp->arguments().contains(QString::fromLatin1("--ignore-invalid-repositories"));
-
- PackageInfoVector dict;
- QFileInfoList entries;
- foreach (const QString &repositoryDirectory, repositoryDirectories)
- entries.append(QFileInfo(repositoryDirectory));
- for (QFileInfoList::const_iterator it = entries.constBegin(); it != entries.constEnd(); ++it) {
-
- qDebug() << "Process repository" << it->fileName();
-
- QFile file(QString::fromLatin1("%1/Updates.xml").arg(it->filePath()));
-
- QFileInfo fileInfo(file);
- if (!fileInfo.exists()) {
- if (ignoreInvalidRepositories) {
- qDebug() << "- skip invalid repository";
- continue;
- }
- throw QInstaller::Error(QString::fromLatin1("Repository \"%1\" does not contain a update "
- "description (Updates.xml is missing).").arg(QDir::toNativeSeparators(it->fileName())));
- }
- if (!file.open(QIODevice::ReadOnly)) {
- qDebug() << "Cannot open Updates.xml for reading:" << file.errorString();
- continue;
- }
-
- QString error;
- QDomDocument doc;
- if (!doc.setContent(&file, &error)) {
- qDebug().nospace() << "Cannot fetch a valid version of Updates.xml from repository "
- << it->fileName() << ": " << error;
- continue;
- }
- file.close();
-
- const QDomElement root = doc.documentElement();
- if (root.tagName() != QLatin1String("Updates")) {
- throw QInstaller::Error(QCoreApplication::translate("QInstaller",
- "Invalid content in \"%1\".").arg(QDir::toNativeSeparators(file.fileName())));
- }
-
- const QDomNodeList children = root.childNodes();
- for (int i = 0; i < children.count(); ++i) {
- const QDomElement el = children.at(i).toElement();
- if ((!el.isNull()) && (el.tagName() == QLatin1String("PackageUpdate"))) {
- QInstallerTools::PackageInfo info;
-
- QDomElement c1 = el.firstChildElement(QInstaller::scName);
- if (!c1.isNull())
- info.name = c1.text();
- else
- continue;
- if (filterType == Exclude) {
- // Check for current package in exclude list, if found, skip it
- if (packagesToFilter->contains(info.name)) {
- continue;
- }
- } else {
- // Check for current package in include list, if not found, skip it
- if (!packagesToFilter->contains(info.name))
- continue;
- }
- c1 = el.firstChildElement(QInstaller::scVersion);
- if (!c1.isNull())
- info.version = c1.text();
- else
- continue;
-
- info.directory = QString::fromLatin1("%1/%2").arg(it->filePath(), info.name);
- const QDomElement sha1 = el.firstChildElement(QInstaller::scSHA1);
- if (!sha1.isNull()) {
- info.metaFile = QString::fromLatin1("%1/%3%2").arg(info.directory,
- QString::fromLatin1("meta.7z"), info.version);
- }
-
- const QDomNodeList c2 = el.childNodes();
- for (int j = 0; j < c2.count(); ++j) {
- const QDomElement c2Element = c2.at(j).toElement();
- if (c2Element.tagName() == QInstaller::scDependencies)
- info.dependencies = c2Element.text()
- .split(QInstaller::commaRegExp(), QString::SkipEmptyParts);
- else if (c2Element.tagName() == QInstaller::scDownloadableArchives) {
- QStringList names = c2Element.text()
- .split(QInstaller::commaRegExp(), QString::SkipEmptyParts);
- foreach (const QString &name, names) {
- info.copiedFiles.append(QString::fromLatin1("%1/%3%2").arg(info.directory,
- name, info.version));
- info.copiedFiles.append(QString::fromLatin1("%1/%3%2.sha1").arg(info.directory,
- name, info.version));
- }
- }
- }
- QString metaString;
- {
- QTextStream metaStream(&metaString);
- el.save(metaStream, 0);
- }
- info.metaNode = metaString;
- dict.push_back(info);
- qDebug() << "- it provides the package" << info.name << " - " << info.version;
- }
- }
- }
-
- return dict;
-}
-
-QHash<QString, QString> QInstallerTools::buildPathToVersionMapping(const PackageInfoVector &info)
-{
- QHash<QString, QString> map;
- foreach (const PackageInfo &inf, info)
- map[inf.name] = inf.version;
- return map;
-}
-
-static void writeSHA1ToNodeWithName(QDomDocument &doc, QDomNodeList &list, const QByteArray &sha1sum,
- const QString &nodename = QString())
-{
- if (nodename.isEmpty())
- qDebug() << "Writing sha1sum node.";
- else
- qDebug() << "Searching sha1sum node for" << nodename;
- QString sha1Value = QString::fromLatin1(sha1sum.toHex().constData());
- for (int i = 0; i < list.size(); ++i) {
- QDomNode curNode = list.at(i);
- QDomNode nameTag = curNode.firstChildElement(scName);
- if ((!nameTag.isNull() && nameTag.toElement().text() == nodename) || nodename.isEmpty()) {
- QDomNode sha1Node = curNode.firstChildElement(scSHA1);
- QDomNode newSha1Node = doc.createElement(scSHA1);
- newSha1Node.appendChild(doc.createTextNode(sha1Value));
-
- if (!sha1Node.isNull() && sha1Node.hasChildNodes()) {
- QDomNode sha1NodeChild = sha1Node.firstChild();
- QString sha1OldValue = sha1NodeChild.nodeValue();
- if (sha1Value == sha1OldValue) {
- qDebug() << "- keeping the existing sha1sum" << sha1OldValue;
- continue;
- } else {
- qDebug() << "- clearing the old sha1sum" << sha1OldValue;
- sha1Node.removeChild(sha1NodeChild);
- }
- }
- if (sha1Node.isNull())
- curNode.appendChild(newSha1Node);
- else
- curNode.replaceChild(newSha1Node, sha1Node);
- qDebug() << "- writing the sha1sum" << sha1Value;
- }
- }
-}
-
-void QInstallerTools::compressMetaDirectories(const QString &repoDir, const QString &existingUnite7zUrl,
- const QHash<QString, QString> &versionMapping, bool createSplitMetadata, bool createUnifiedMetadata)
-{
- QDomDocument doc;
- // use existing Updates.xml, if any
- QFile existingUpdatesXml(QFileInfo(QDir(repoDir), QLatin1String("Updates.xml")).absoluteFilePath());
- if (!existingUpdatesXml.open(QIODevice::ReadOnly) || !doc.setContent(&existingUpdatesXml)) {
- qDebug() << "Cannot find Updates.xml";
- }
- existingUpdatesXml.close();
-
- QDir dir(repoDir);
- const QStringList entryList = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
-
- QStringList absPaths;
- if (createUnifiedMetadata) {
- absPaths = unifyMetadata(repoDir, existingUnite7zUrl, doc);
- }
-
- if (createSplitMetadata) {
- splitMetadata(entryList, repoDir, doc, versionMapping);
- } else {
- // remove the files that got compressed
- foreach (const QString path, absPaths)
- QInstaller::removeFiles(path, true);
- }
-
- QInstaller::openForWrite(&existingUpdatesXml);
- QInstaller::blockingWrite(&existingUpdatesXml, doc.toByteArray());
- existingUpdatesXml.close();
-}
-
-QStringList QInstallerTools::unifyMetadata(const QString &repoDir, const QString &existingRepoDir, QDomDocument doc)
-{
- QStringList absPaths;
- QDir dir(repoDir);
- const QStringList entryList = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
-
- foreach (const QString &i, entryList) {
- dir.cd(i);
- const QString absPath = dir.absolutePath();
- absPaths.append(absPath);
- dir.cdUp();
- }
-
- QTemporaryDir existingRepoTempDir;
- QString existingRepoTemp = existingRepoTempDir.path();
- if (!existingRepoDir.isEmpty()) {
- existingRepoTempDir.setAutoRemove(false);
- QFile archiveFile(existingRepoDir);
- QInstaller::openForRead(&archiveFile);
- Lib7z::extractArchive(&archiveFile, existingRepoTemp);
- QDir dir(existingRepoTemp);
- QStringList existingRepoEntries = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
- foreach (const QString existingRepoEntry, existingRepoEntries) {
- if (entryList.contains(existingRepoEntry)) {
- continue;
- } else {
- dir.cd(existingRepoEntry);
- const QString absPath = dir.absolutePath();
- absPaths.append(absPath);
- }
- }
- }
-
- // Compress all metadata from repository to one single 7z
- const QString metadataFilename = QDateTime::currentDateTime().
- toString(QLatin1String("yyyy-MM-dd-hhmm")) + QLatin1String("_meta.7z");
- const QString tmpTarget = repoDir + QDir::separator() + metadataFilename;
- Lib7z::createArchive(tmpTarget, absPaths, Lib7z::TmpFile::No);
-
- QFile tmp(tmpTarget);
- tmp.open(QFile::ReadOnly);
- const QByteArray sha1Sum = QInstaller::calculateHash(&tmp, QCryptographicHash::Sha1);
- QDomNodeList elements = doc.elementsByTagName(QLatin1String("Updates"));
- writeSHA1ToNodeWithName(doc, elements, sha1Sum, QString());
-
- qDebug() << "Updating the metadata node with name " << metadataFilename;
- if (elements.count() > 0) {
- QDomNode node = elements.at(0);
- QDomNode nameTag = node.firstChildElement(QLatin1String("MetadataName"));
-
- QDomNode newNodeTag = doc.createElement(QLatin1String("MetadataName"));
- newNodeTag.appendChild(doc.createTextNode(metadataFilename));
-
- if (nameTag.isNull())
- node.appendChild(newNodeTag);
- else
- node.replaceChild(newNodeTag, nameTag);
- }
- QInstaller::removeDirectory(existingRepoTemp, true);
- return absPaths;
-}
-
-void QInstallerTools::splitMetadata(const QStringList &entryList, const QString &repoDir,
- QDomDocument doc, const QHash<QString, QString> &versionMapping)
-{
- QStringList absPaths;
- QDomNodeList elements = doc.elementsByTagName(QLatin1String("PackageUpdate"));
- QDir dir(repoDir);
- foreach (const QString &i, entryList) {
- dir.cd(i);
- const QString absPath = dir.absolutePath();
- const QString path = QString(i).remove(repoDir);
- if (path.isNull())
- continue;
- const QString versionPrefix = versionMapping[path];
- const QString fn = QLatin1String(versionPrefix.toLatin1() + "meta.7z");
- const QString tmpTarget = repoDir + QLatin1String("/") + fn;
- Lib7z::createArchive(tmpTarget, QStringList() << absPath, Lib7z::TmpFile::No);
- // remove the files that got compressed
- QInstaller::removeFiles(absPath, true);
- QFile tmp(tmpTarget);
- tmp.open(QFile::ReadOnly);
- const QByteArray sha1Sum = QInstaller::calculateHash(&tmp, QCryptographicHash::Sha1);
- writeSHA1ToNodeWithName(doc, elements, sha1Sum, path);
- const QString finalTarget = absPath + QLatin1String("/") + fn;
- if (!tmp.rename(finalTarget)) {
- throw QInstaller::Error(QString::fromLatin1("Cannot move file \"%1\" to \"%2\".").arg(
- QDir::toNativeSeparators(tmpTarget), QDir::toNativeSeparators(finalTarget)));
- }
- dir.cdUp();
- }
-}
-
-void QInstallerTools::copyComponentData(const QStringList &packageDirs, const QString &repoDir,
- PackageInfoVector *const infos)
-{
- for (int i = 0; i < infos->count(); ++i) {
- const PackageInfo info = infos->at(i);
- const QString name = info.name;
- qDebug() << "Copying component data for" << name;
-
- const QString namedRepoDir = QString::fromLatin1("%1/%2").arg(repoDir, name);
- if (!QDir().mkpath(namedRepoDir)) {
- throw QInstaller::Error(QString::fromLatin1("Cannot create repository directory for component \"%1\".")
- .arg(name));
- }
-
- if (info.copiedFiles.isEmpty()) {
- QStringList compressedFiles;
- QStringList filesToCompress;
- foreach (const QString &packageDir, packageDirs) {
- const QDir dataDir(QString::fromLatin1("%1/%2/data").arg(packageDir, name));
- foreach (const QString &entry, dataDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::Files)) {
- QFileInfo fileInfo(dataDir.absoluteFilePath(entry));
- if (fileInfo.isFile() && !fileInfo.isSymLink()) {
- const QString absoluteEntryFilePath = dataDir.absoluteFilePath(entry);
- if (Lib7z::isSupportedArchive(absoluteEntryFilePath)) {
- QFile tmp(absoluteEntryFilePath);
- QString target = QString::fromLatin1("%1/%3%2").arg(namedRepoDir, entry, info.version);
- qDebug() << "Copying archive from" << tmp.fileName() << "to" << target;
- if (!tmp.copy(target)) {
- throw QInstaller::Error(QString::fromLatin1("Cannot copy file \"%1\" to \"%2\": %3")
- .arg(QDir::toNativeSeparators(tmp.fileName()), QDir::toNativeSeparators(target), tmp.errorString()));
- }
- compressedFiles.append(target);
- } else {
- filesToCompress.append(absoluteEntryFilePath);
- }
- } else if (fileInfo.isDir()) {
- qDebug() << "Compressing data directory" << entry;
- QString target = QString::fromLatin1("%1/%3%2.7z").arg(namedRepoDir, entry, info.version);
- Lib7z::createArchive(target, QStringList() << dataDir.absoluteFilePath(entry),
- Lib7z::TmpFile::No);
- compressedFiles.append(target);
- } else if (fileInfo.isSymLink()) {
- filesToCompress.append(dataDir.absoluteFilePath(entry));
- }
- }
- }
-
- if (!filesToCompress.isEmpty()) {
- qDebug() << "Compressing files found in data directory:" << filesToCompress;
- QString target = QString::fromLatin1("%1/%3%2").arg(namedRepoDir, QLatin1String("content.7z"),
- info.version);
- Lib7z::createArchive(target, filesToCompress, Lib7z::TmpFile::No);
- compressedFiles.append(target);
- }
-
- foreach (const QString &target, compressedFiles) {
- (*infos)[i].copiedFiles.append(target);
-
- QFile archiveFile(target);
- QFile archiveHashFile(archiveFile.fileName() + QLatin1String(".sha1"));
-
- qDebug() << "Hash is stored in" << archiveHashFile.fileName();
- qDebug() << "Creating hash of archive" << archiveFile.fileName();
-
- try {
- QInstaller::openForRead(&archiveFile);
- const QByteArray hashOfArchiveData = QInstaller::calculateHash(&archiveFile,
- QCryptographicHash::Sha1).toHex();
- archiveFile.close();
-
- QInstaller::openForWrite(&archiveHashFile);
- archiveHashFile.write(hashOfArchiveData);
- qDebug() << "Generated sha1 hash:" << hashOfArchiveData;
- (*infos)[i].copiedFiles.append(archiveHashFile.fileName());
- archiveHashFile.close();
- } catch (const QInstaller::Error &/*e*/) {
- archiveFile.close();
- archiveHashFile.close();
- throw;
- }
- }
- } else {
- foreach (const QString &file, (*infos)[i].copiedFiles) {
- QFileInfo fromInfo(file);
- QFile from(file);
- QString target = QString::fromLatin1("%1/%2").arg(namedRepoDir, fromInfo.fileName());
- qDebug() << "Copying file from" << from.fileName() << "to" << target;
- if (!from.copy(target)) {
- throw QInstaller::Error(QString::fromLatin1("Cannot copy file \"%1\" to \"%2\": %3")
- .arg(QDir::toNativeSeparators(from.fileName()), QDir::toNativeSeparators(target), from.errorString()));
- }
- }
- }
- }
-}
-
-void QInstallerTools::filterNewComponents(const QString &repositoryDir, QInstallerTools::PackageInfoVector &packages)
-{
- QDomDocument doc;
- QFile file(repositoryDir + QLatin1String("/Updates.xml"));
- if (file.open(QFile::ReadOnly) && doc.setContent(&file)) {
- const QDomElement root = doc.documentElement();
- if (root.tagName() != QLatin1String("Updates")) {
- throw QInstaller::Error(QCoreApplication::translate("QInstaller",
- "Invalid content in \"%1\".").arg(QDir::toNativeSeparators(file.fileName())));
- }
- file.close(); // close the file, we read the content already
-
- // read the already existing updates xml content
- const QDomNodeList children = root.childNodes();
- QHash <QString, QInstallerTools::PackageInfo> hash;
- for (int i = 0; i < children.count(); ++i) {
- const QDomElement el = children.at(i).toElement();
- if ((!el.isNull()) && (el.tagName() == QLatin1String("PackageUpdate"))) {
- QInstallerTools::PackageInfo info;
- const QDomNodeList c2 = el.childNodes();
- for (int j = 0; j < c2.count(); ++j) {
- const QDomElement c2Element = c2.at(j).toElement();
- if (c2Element.tagName() == scName)
- info.name = c2Element.text();
- else if (c2Element.tagName() == scVersion)
- info.version = c2Element.text();
- }
- hash.insert(info.name, info);
- }
- }
-
- // remove all components that have no update (decision based on the version tag)
- for (int i = packages.count() - 1; i >= 0; --i) {
- const QInstallerTools::PackageInfo info = packages.at(i);
-
- // check if component already exists & version did not change
- if (hash.contains(info.name) && KDUpdater::compareVersion(info.version, hash.value(info.name).version) < 1) {
- packages.remove(i); // the version did not change, no need to update the component
- continue;
- }
- qDebug() << "Update component" << info.name << "in"<< repositoryDir << ".";
- }
- }
-}
-
-QString QInstallerTools::existingUniteMeta7z(const QString &repositoryDir)
-{
- QString uniteMeta7z = QString();
- QFile file(repositoryDir + QLatin1String("/Updates.xml"));
- QDomDocument doc;
- if (file.open(QFile::ReadOnly) && doc.setContent(&file)) {
- QDomNodeList elements = doc.elementsByTagName(QLatin1String("MetadataName"));
- if (elements.count() > 0 && elements.at(0).isElement()) {
- uniteMeta7z = elements.at(0).toElement().text();
- QFile metaFile(repositoryDir + QDir::separator() + uniteMeta7z);
- if (!metaFile.exists()) {
- throw QInstaller::Error(QString::fromLatin1("Unite meta7z \"%1\" does not exist in repository \"%2\"")
- .arg(QDir::toNativeSeparators(metaFile.fileName()), repositoryDir));
- }
- }
- }
- return uniteMeta7z;
-}
diff --git a/tools/common/repositorygen.h b/tools/common/repositorygen.h
deleted file mode 100644
index f5202c1fc..000000000
--- a/tools/common/repositorygen.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/**************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Installer Framework.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-**************************************************************************/
-
-#ifndef QINSTALLER_REPOSITORYGEN_H
-#define QINSTALLER_REPOSITORYGEN_H
-
-#include <QHash>
-#include <QString>
-#include <QStringList>
-#include <QVector>
-#include <QDomDocument>
-
-namespace QInstallerTools {
-
-
-struct PackageInfo
-{
- QString name;
- QString version;
- QString directory;
- QStringList dependencies;
- QStringList copiedFiles;
- QString metaFile;
- QString metaNode;
-};
-typedef QVector<PackageInfo> PackageInfoVector;
-
-enum FilterType {
- Include,
- Exclude
-};
-
-void printRepositoryGenOptions();
-QString makePathAbsolute(const QString &path);
-void copyWithException(const QString &source, const QString &target, const QString &kind = QString());
-
-PackageInfoVector createListOfPackages(const QStringList &packagesDirectories, QStringList *packagesToFilter,
- FilterType ftype);
-
-PackageInfoVector createListOfRepositoryPackages(const QStringList &repositoryDirectories, QStringList *packagesToFilter,
- FilterType filterType);
-
-QHash<QString, QString> buildPathToVersionMapping(const PackageInfoVector &info);
-
-void compressMetaDirectories(const QString &repoDir, const QString &existingUnite7zUrl,
- const QHash<QString, QString> &versionMapping, bool createSplitMetadata, bool createUnifiedMetadata);
-
-QStringList unifyMetadata(const QString &repoDir, const QString &existingRepoDir, QDomDocument doc);
-void splitMetadata(const QStringList &entryList, const QString &repoDir, QDomDocument doc,
- const QHash<QString, QString> &versionMapping);
-
-void copyMetaData(const QString &outDir, const QString &dataDir, const PackageInfoVector &packages,
- const QString &appName, const QString& appVersion, const QStringList &uniteMetadatas);
-void copyComponentData(const QStringList &packageDir, const QString &repoDir, PackageInfoVector *const infos);
-
-void filterNewComponents(const QString &repositoryDir, QInstallerTools::PackageInfoVector &packages);
-
-QString existingUniteMeta7z(const QString &repositoryDir);
-
-} // namespace QInstallerTools
-
-#endif // QINSTALLER_REPOSITORYGEN_H
diff --git a/tools/repogen/repogen.cpp b/tools/repogen/repogen.cpp
index 5c67cbc1c..10aa0370b 100644
--- a/tools/repogen/repogen.cpp
+++ b/tools/repogen/repogen.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -25,8 +25,8 @@
** $QT_END_LICENSE$
**
**************************************************************************/
-#include "common/repositorygen.h"
+#include <repositorygen.h>
#include <errors.h>
#include <fileutils.h>
#include <init.h>
diff --git a/tools/repogen/repogen.pri b/tools/repogen/repogen.pri
deleted file mode 100644
index 319b137ff..000000000
--- a/tools/repogen/repogen.pri
+++ /dev/null
@@ -1 +0,0 @@
-INCLUDEPATH += $$PWD/../common
diff --git a/tools/repogen/repogen.pro b/tools/repogen/repogen.pro
index 016a8fe8e..0380bb78b 100644
--- a/tools/repogen/repogen.pro
+++ b/tools/repogen/repogen.pro
@@ -2,7 +2,6 @@ TEMPLATE = app
TARGET = repogen
INCLUDEPATH += . ..
-include(repogen.pri)
include(../../installerfw.pri)
QT -= gui
@@ -11,9 +10,7 @@ QT += qml xml
CONFIG += console
DESTDIR = $$IFW_APP_PATH
-SOURCES += repogen.cpp \
- ../common/repositorygen.cpp
-HEADERS += ../common/repositorygen.h
+SOURCES += repogen.cpp
macx:include(../../no_app_bundle.pri)