mirror of
https://github.com/QuasarApp/installer-framework.git
synced 2025-04-29 15:04:32 +00:00
Merge remote-tracking branch 'origin/3.0'
Change-Id: Id2e682dc2698e08f91bee83e2a94de57403545a0
This commit is contained in:
commit
741d16a9bd
@ -126,13 +126,11 @@ DEFINES += NOMINMAX QT_NO_CAST_FROM_ASCII QT_STRICT_ITERATORS QT_USE_QSTRINGBUIL
|
||||
IFW_VERSION_STR=$$IFW_VERSION_STR IFW_VERSION=$$IFW_VERSION
|
||||
DEFINES += IFW_REPOSITORY_FORMAT_VERSION=$$IFW_REPOSITORY_FORMAT_VERSION
|
||||
|
||||
static {
|
||||
LIBS += -l7z
|
||||
win32-g++*: LIBS += -lmpr -luuid
|
||||
LIBS += -l7z
|
||||
win32-g++*: LIBS += -lmpr -luuid
|
||||
|
||||
equals(TEMPLATE, app) {
|
||||
equals(TEMPLATE, app) {
|
||||
msvc:POST_TARGETDEPS += $$IFW_LIB_PATH/installer.lib $$IFW_LIB_PATH/7z.lib
|
||||
win32-g++*:POST_TARGETDEPS += $$IFW_LIB_PATH/libinstaller.a $$IFW_LIB_PATH/lib7z.a
|
||||
unix:POST_TARGETDEPS += $$IFW_LIB_PATH/libinstaller.a $$IFW_LIB_PATH/lib7z.a
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ TEMPLATE = lib
|
||||
TARGET = installer
|
||||
INCLUDEPATH += . ..
|
||||
|
||||
CONFIG += staticlib
|
||||
|
||||
include(../7zip/7zip.pri)
|
||||
include(../kdtools/kdtools.pri)
|
||||
include(../../../installerfw.pri)
|
||||
|
@ -1439,11 +1439,11 @@ Errore durante lo scaricamento %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Click Done to exit the %1 Wizard.</source>
|
||||
<translation>Clicca Fatto per uscire dalla procedura guidatadi %1.</translation>
|
||||
<translation>Clicca Fatto per uscire dalla procedura guidata di %1.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Click Finish to exit the %1 Wizard.</source>
|
||||
<translation>Clicca Finito per uscire dalla procedura guidatadi %1.</translation>
|
||||
<translation>Clicca Finito per uscire dalla procedura guidata di %1.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Restart</source>
|
||||
|
@ -870,6 +870,10 @@
|
||||
<source>&Deselect All</source>
|
||||
<translation>&Снять отметки выбора со всех компонентов</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>&Browse QBSP files</source>
|
||||
<translation>&Обзор файлов QBSP</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>This component will occupy approximately %1 on your hard disk drive.</source>
|
||||
<translation>Этот компонент займёт приблизительно %1 на жестком диске.</translation>
|
||||
@ -891,16 +895,12 @@
|
||||
<translation>Пожалуйста, выберите компоненты, которые вы хотите удалить.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Select the components to install. Deselect installed components to uninstall them.</source>
|
||||
<translation>Выберите компоненты для установки.Для удаления уже установленных компонентов снимите отметки выбора.</translation>
|
||||
<source>Select the components to install. Deselect installed components to uninstall them. Any components already installed will not be updated.</source>
|
||||
<translation>Выберите компоненты для установки. Для удаления уже установленных компонентов снимите отметки выбора. Уже установленные компоненты не будут обновлены.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>To install new compressed repository, browse the repositories from your computer</source>
|
||||
<translation type="unfinished">Для установки нового хранилища укажите путь к нему на вашем компьютере</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>&Browse BSP or 7z files...</source>
|
||||
<translation>&Обзор BSP или 7z файлов...</translation>
|
||||
<translation>Для установки нового хранилища укажите путь к нему на вашем компьютере</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open File</source>
|
||||
@ -1155,9 +1155,8 @@ Error while loading %2</source>
|
||||
<translation>Обнаружено несовпадение контрольной суммы «%1».</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Network error while downloading "%1": %2</source>
|
||||
<extracomment>%2 is a sentence describing the error</extracomment>
|
||||
<translation>Возникла ошибка сети при загрузке «%1»: %2</translation>
|
||||
<source>Network error while downloading '%1': %2.</source>
|
||||
<translation>Возникла ошибка сети при загрузке «%1»: %2.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Unknown network error while downloading "%1".</source>
|
||||
@ -1463,6 +1462,10 @@ Error while loading %2</source>
|
||||
<source>Preparing meta information download...</source>
|
||||
<translation>Подготовка к загрузке метаданных...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Unpacking compressed repositories. This may take a while...</source>
|
||||
<translation>Распаковка сжатых хранилищ. Это может занять некоторое время...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Meta data download canceled.</source>
|
||||
<translation>Загрузка метаданных отменена.</translation>
|
||||
@ -1495,10 +1498,6 @@ Error while loading %2</source>
|
||||
<source>Extracting meta information...</source>
|
||||
<translation>Извлечение метаданных...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Unpacking compressed repositories...</source>
|
||||
<translation>Распаковка сжатых хранилищ...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error while extracting archive "%1": %2</source>
|
||||
<translation>Ошибка извлечения из архива «%1»: %2</translation>
|
||||
|
@ -50,6 +50,15 @@
|
||||
|
||||
#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 {
|
||||
@ -99,6 +108,159 @@ static void chmod755(const QString &absolutFilePath)
|
||||
}
|
||||
#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_OSX
|
||||
@ -124,6 +286,11 @@ static int assemble(Input input, const QInstaller::Settings &settings, const QSt
|
||||
// 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"));
|
||||
@ -182,6 +349,10 @@ static int assemble(Input input, const QInstaller::Settings &settings, const QSt
|
||||
<< 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;
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
TEMPLATE = app
|
||||
TARGET = devtool
|
||||
|
||||
include(../../installerfw.pri)
|
||||
QT = core network qml xml
|
||||
|
||||
QT -= gui
|
||||
QT += network xml
|
||||
include(../../installerfw.pri)
|
||||
|
||||
CONFIG += console
|
||||
DESTDIR = $$IFW_APP_PATH
|
||||
|
Loading…
x
Reference in New Issue
Block a user