2015-08-19 02:13:28 +02:00
|
|
|
#include "mingwbundle.h"
|
2015-09-04 14:37:01 +02:00
|
|
|
#include "utilities.h"
|
2015-08-19 02:13:28 +02:00
|
|
|
#include "manager.h"
|
2015-09-05 17:25:05 +02:00
|
|
|
#include "config.h"
|
2015-08-19 02:13:28 +02:00
|
|
|
|
|
|
|
#include <c++utilities/conversion/stringconversion.h>
|
|
|
|
#include <c++utilities/misc/memory.h>
|
|
|
|
|
|
|
|
#include <KTar>
|
2015-09-04 14:37:01 +02:00
|
|
|
#include <K7Zip>
|
|
|
|
#include <KZip>
|
2015-08-19 02:13:28 +02:00
|
|
|
|
|
|
|
#include <QtConcurrent/QtConcurrent>
|
2015-09-04 14:37:01 +02:00
|
|
|
#include <QStringBuilder>
|
|
|
|
#include <QJsonDocument>
|
|
|
|
#include <QJsonArray>
|
|
|
|
#include <QFile>
|
2015-08-19 02:13:28 +02:00
|
|
|
|
|
|
|
#include <string>
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
2015-09-05 17:25:05 +02:00
|
|
|
namespace RepoIndex {
|
2015-08-19 02:13:28 +02:00
|
|
|
|
2015-09-04 14:37:01 +02:00
|
|
|
using namespace Utilities;
|
|
|
|
|
2015-08-19 02:13:28 +02:00
|
|
|
const string prefix("mingw-w64-");
|
|
|
|
|
2015-09-04 14:37:01 +02:00
|
|
|
MingwBundle::MingwBundle(const Manager &manager, const ApplicationUtilities::StringVector &packages, const ApplicationUtilities::StringVector &iconPackages) :
|
2015-08-19 02:13:28 +02:00
|
|
|
m_manager(manager)
|
|
|
|
{
|
2015-09-05 17:25:05 +02:00
|
|
|
cerr << shchar << "Resolving dependencies ..." << endl;
|
2015-08-19 02:13:28 +02:00
|
|
|
string missing;
|
2015-09-04 14:37:01 +02:00
|
|
|
// add mingw-w64 packages
|
2015-08-19 02:13:28 +02:00
|
|
|
for(const auto &pkgName : packages) {
|
|
|
|
bool found = false;
|
2015-09-05 17:25:05 +02:00
|
|
|
for(const auto &syncDb : manager.syncDatabases()) {
|
2015-09-04 14:37:01 +02:00
|
|
|
if(auto *pkg = syncDb.second->packageByName(QString::fromLocal8Bit(ConversionUtilities::startsWith(pkgName, prefix) ? pkgName.data() : (prefix + pkgName).data()))) {
|
2015-08-19 02:13:28 +02:00
|
|
|
if(missing.empty()) {
|
2015-09-04 14:37:01 +02:00
|
|
|
decltype(m_packages)::value_type entry(syncDb.second.get(), pkg);
|
|
|
|
if(find(m_packages.cbegin(), m_packages.cend(), entry) == m_packages.cend()) {
|
|
|
|
m_packages.emplace_back(entry);
|
|
|
|
}
|
2015-08-19 02:13:28 +02:00
|
|
|
}
|
|
|
|
addDependencies(pkg);
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!found) {
|
|
|
|
missing.push_back(' ');
|
|
|
|
missing.append(pkgName);
|
|
|
|
}
|
|
|
|
}
|
2015-09-04 14:37:01 +02:00
|
|
|
// add additional icon packages
|
|
|
|
for(const auto &pkgName : iconPackages) {
|
|
|
|
bool found = false;
|
2015-09-05 17:25:05 +02:00
|
|
|
for(const auto &syncDb : manager.syncDatabases()) {
|
2015-09-04 14:37:01 +02:00
|
|
|
if(auto *pkg = syncDb.second->packageByName(QString::fromLocal8Bit(pkgName.data()))) {
|
|
|
|
if(missing.empty()) {
|
|
|
|
decltype(m_packages)::value_type entry(syncDb.second.get(), pkg);
|
|
|
|
if(find(m_packages.cbegin(), m_packages.cend(), entry) == m_packages.cend()) {
|
|
|
|
m_packages.emplace_back(entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!found) {
|
|
|
|
missing.push_back(' ');
|
|
|
|
missing.append(pkgName);
|
|
|
|
}
|
|
|
|
}
|
2015-08-19 02:13:28 +02:00
|
|
|
if(!missing.empty()) {
|
|
|
|
throw runtime_error("The following packages can not be found:" + missing);
|
|
|
|
} else {
|
2015-09-05 17:25:05 +02:00
|
|
|
cerr << shchar << "Adding the following packages:";
|
2015-08-19 02:13:28 +02:00
|
|
|
for(const auto &pkg : m_packages) {
|
2015-09-05 17:25:05 +02:00
|
|
|
cerr << shchar << ' ' << pkg.second->name().toLocal8Bit().data();
|
2015-08-19 02:13:28 +02:00
|
|
|
}
|
2015-09-05 17:25:05 +02:00
|
|
|
cerr << shchar << endl;
|
2015-08-19 02:13:28 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-04 14:37:01 +02:00
|
|
|
void MingwBundle::addDependencies(const Package *pkg)
|
|
|
|
{
|
|
|
|
string missing;
|
|
|
|
for(const auto &dep : pkg->dependencies()) {
|
|
|
|
if(dep.name.startsWith(QLatin1String("mingw-w64-"), Qt::CaseInsensitive)) {
|
|
|
|
bool found = false;
|
2015-09-05 17:25:05 +02:00
|
|
|
for(const auto &syncDbEntry : m_manager.syncDatabases()) {
|
2015-09-04 14:37:01 +02:00
|
|
|
if(const auto *pkg = syncDbEntry.second->packageProviding(dep)) {
|
|
|
|
if(missing.empty()) {
|
|
|
|
decltype(m_packages)::value_type entry(syncDbEntry.second.get(), pkg);
|
|
|
|
if(find(m_packages.cbegin(), m_packages.cend(), entry) == m_packages.cend()) {
|
|
|
|
m_packages.emplace_back(entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
addDependencies(pkg);
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!found) {
|
|
|
|
missing.push_back(' ');
|
|
|
|
missing.append(dep.name.toLocal8Bit().data());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!missing.empty()) {
|
|
|
|
throw runtime_error("The following dependencies of the " + string(pkg->name().toLocal8Bit().data()) + " package can not be resolved:" + missing);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-19 02:13:28 +02:00
|
|
|
enum class RelevantFileType
|
|
|
|
{
|
|
|
|
Binary,
|
2015-09-04 14:37:01 +02:00
|
|
|
Translation,
|
|
|
|
QtTranslation,
|
|
|
|
QtPlugin,
|
|
|
|
Icon
|
2015-08-19 02:13:28 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
enum class RelevantFileArch
|
|
|
|
{
|
|
|
|
x86_64,
|
2015-09-04 14:37:01 +02:00
|
|
|
i686,
|
|
|
|
Any
|
2015-08-19 02:13:28 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct RelevantFile
|
|
|
|
{
|
2015-09-04 14:37:01 +02:00
|
|
|
RelevantFile(const KArchiveFile *file, const RelevantFileType type, const RelevantFileArch arch, const QString &subDir = QString()) :
|
2015-08-19 02:13:28 +02:00
|
|
|
file(file),
|
|
|
|
fileType(type),
|
2015-09-04 14:37:01 +02:00
|
|
|
arch(arch),
|
|
|
|
subDir(subDir)
|
2015-08-19 02:13:28 +02:00
|
|
|
{}
|
|
|
|
const KArchiveFile *file;
|
|
|
|
RelevantFileType fileType;
|
|
|
|
RelevantFileArch arch;
|
2015-09-04 14:37:01 +02:00
|
|
|
QString subDir;
|
2015-08-19 02:13:28 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct PkgFileInfo
|
|
|
|
{
|
2015-09-04 14:37:01 +02:00
|
|
|
PkgFileInfo(const QString &name, const QString &path) :
|
|
|
|
name(name),
|
|
|
|
path(path),
|
|
|
|
failure(false)
|
|
|
|
{}
|
|
|
|
QString name;
|
2015-08-19 02:13:28 +02:00
|
|
|
QString path;
|
|
|
|
unique_ptr<KTar> archive;
|
|
|
|
list<RelevantFile> relevantFiles;
|
|
|
|
bool failure;
|
|
|
|
};
|
|
|
|
|
2015-09-04 14:37:01 +02:00
|
|
|
void addEntries(PkgFileInfo &pkgFileInfo, RelevantFileType fileType, const KArchiveDirectory *dir, const QString &relPath = QString())
|
|
|
|
{
|
|
|
|
QString newPath = relPath.isEmpty() ? dir->name() : relPath % QChar('/') % dir->name();
|
|
|
|
for(const auto &entryName : dir->entries()) {
|
|
|
|
if(auto *entry = dir->entry(entryName)) {
|
|
|
|
if(entry->isDirectory()) {
|
|
|
|
addEntries(pkgFileInfo, fileType, static_cast<const KArchiveDirectory *>(entry), newPath);
|
|
|
|
} else if(entry->isFile()) {
|
|
|
|
pkgFileInfo.relevantFiles.emplace_back(static_cast<const KArchiveFile *>(entry), fileType, RelevantFileArch::Any, newPath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-19 02:13:28 +02:00
|
|
|
void getFiles(PkgFileInfo &pkgFileInfo)
|
|
|
|
{
|
|
|
|
pkgFileInfo.archive = make_unique<KTar>(pkgFileInfo.path);
|
|
|
|
if(pkgFileInfo.archive->open(QIODevice::ReadOnly)) {
|
|
|
|
static const pair<RelevantFileArch, QString> roots[] = {
|
|
|
|
make_pair(RelevantFileArch::x86_64, QStringLiteral("/usr/x86_64-w64-mingw32")),
|
|
|
|
make_pair(RelevantFileArch::i686, QStringLiteral("/usr/i686-w64-mingw32"))
|
|
|
|
};
|
|
|
|
for(const auto &root : roots) {
|
|
|
|
const auto *rootEntry = pkgFileInfo.archive->directory()->entry(root.second);
|
|
|
|
if(rootEntry && rootEntry->isDirectory()) {
|
|
|
|
const auto *rootDir = static_cast<const KArchiveDirectory *>(rootEntry);
|
|
|
|
const auto *binEntry = rootDir->entry(QStringLiteral("bin"));
|
|
|
|
if(binEntry && binEntry->isDirectory()) {
|
|
|
|
const auto *binDir = static_cast<const KArchiveDirectory *>(binEntry);
|
|
|
|
for(const auto &entryName : binDir->entries()) {
|
|
|
|
if(entryName.endsWith(QLatin1String(".exe")) || entryName.endsWith(QLatin1String(".dll"))) {
|
|
|
|
if(const auto *entry = binDir->entry(entryName)) {
|
|
|
|
if(entry->isFile()) {
|
|
|
|
const auto *binFile = static_cast<const KArchiveFile *>(entry);
|
|
|
|
pkgFileInfo.relevantFiles.emplace_back(binFile, RelevantFileType::Binary, root.first);
|
2015-09-04 14:37:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const auto *libEntry = rootDir->entry(QStringLiteral("lib"));
|
|
|
|
if(libEntry && libEntry->isDirectory()) {
|
|
|
|
const auto *libDir = static_cast<const KArchiveDirectory *>(libEntry);
|
|
|
|
const auto *qtEntry = libDir->entry("qt");
|
|
|
|
if(qtEntry && qtEntry->isDirectory()) {
|
|
|
|
const auto *qtDir = static_cast<const KArchiveDirectory *>(qtEntry);
|
|
|
|
const auto *pluginsEntry = qtDir->entry(QStringLiteral("plugins"));
|
|
|
|
if(pluginsEntry && pluginsEntry->isDirectory()) {
|
|
|
|
const auto *pluginsDir = static_cast<const KArchiveDirectory *>(pluginsEntry);
|
|
|
|
for(const auto &pluginCategory : pluginsDir->entries()) {
|
|
|
|
const auto *categoryEntry = pluginsDir->entry(pluginCategory);
|
|
|
|
if(categoryEntry && categoryEntry->isDirectory()) {
|
|
|
|
const auto *categoryDir = static_cast<const KArchiveDirectory *>(categoryEntry);
|
|
|
|
for(const auto &entryName : categoryDir->entries()) {
|
|
|
|
if(const auto *pluginEntry = categoryDir->entry(entryName)) {
|
|
|
|
if(pluginEntry->isFile()) {
|
|
|
|
const auto *pluginFile = static_cast<const KArchiveFile *>(pluginEntry);
|
|
|
|
pkgFileInfo.relevantFiles.emplace_back(pluginFile, RelevantFileType::QtPlugin, root.first, categoryDir->name());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const auto *shareEntry = rootDir->entry(QStringLiteral("share"));
|
|
|
|
if(shareEntry && shareEntry->isDirectory()) {
|
|
|
|
const auto *shareDir = static_cast<const KArchiveDirectory *>(shareEntry);
|
|
|
|
const auto *qtEntry = shareDir->entry(QStringLiteral("qt"));
|
|
|
|
if(qtEntry && qtEntry->isDirectory()) {
|
|
|
|
const auto *qtDir = static_cast<const KArchiveDirectory *>(qtEntry);
|
|
|
|
const auto *trEntry = qtDir->entry(QStringLiteral("translations"));
|
|
|
|
if(trEntry && trEntry->isDirectory()) {
|
|
|
|
const auto trDir = static_cast<const KArchiveDirectory *>(trEntry);
|
|
|
|
for(const auto &entryName : trDir->entries()) {
|
|
|
|
if(entryName.endsWith(QLatin1String(".qm"))) {
|
|
|
|
if(const auto *qmEntry = trDir->entry(entryName)) {
|
|
|
|
if(qmEntry->isFile()) {
|
|
|
|
const auto *qmFile = static_cast<const KArchiveFile *>(qmEntry);
|
|
|
|
pkgFileInfo.relevantFiles.emplace_back(qmFile, RelevantFileType::QtTranslation, root.first);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(pkgFileInfo.name.compare(QLatin1String("qt"))) {
|
|
|
|
const auto *appEntry = shareDir->entry(pkgFileInfo.name);
|
|
|
|
if(appEntry && appEntry->isDirectory()) {
|
|
|
|
const auto *appDir = static_cast<const KArchiveDirectory *>(appEntry);
|
|
|
|
const auto *trEntry = appDir->entry(QStringLiteral("translations"));
|
|
|
|
if(trEntry && trEntry->isDirectory()) {
|
|
|
|
const auto trDir = static_cast<const KArchiveDirectory *>(trEntry);
|
|
|
|
for(const auto &entryName : trDir->entries()) {
|
|
|
|
if(entryName.endsWith(QLatin1String(".qm"))) {
|
|
|
|
if(const auto *qmEntry = trDir->entry(entryName)) {
|
|
|
|
if(qmEntry->isFile()) {
|
|
|
|
const auto *qmFile = static_cast<const KArchiveFile *>(qmEntry);
|
|
|
|
pkgFileInfo.relevantFiles.emplace_back(qmFile, RelevantFileType::Translation, root.first);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-08-19 02:13:28 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-09-04 14:37:01 +02:00
|
|
|
const auto *iconsEntry = pkgFileInfo.archive->directory()->entry(QStringLiteral("usr/share/icons"));
|
|
|
|
if(iconsEntry && iconsEntry->isDirectory()) {
|
|
|
|
const auto *iconsDir = static_cast<const KArchiveDirectory *>(iconsEntry);
|
|
|
|
for(const auto &themeName : iconsDir->entries()) {
|
|
|
|
const auto *themeEntry = iconsDir->entry(themeName);
|
|
|
|
if(themeEntry && themeEntry->isDirectory()) {
|
|
|
|
addEntries(pkgFileInfo, RelevantFileType::Icon, static_cast<const KArchiveDirectory *>(themeEntry));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-08-19 02:13:28 +02:00
|
|
|
} else {
|
|
|
|
pkgFileInfo.failure = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-04 14:37:01 +02:00
|
|
|
void MingwBundle::createBundle(const string &targetDir, const string &targetName, const string &targetFormat) const
|
2015-08-19 02:13:28 +02:00
|
|
|
{
|
2015-09-05 17:25:05 +02:00
|
|
|
cerr << shchar << "Gathering relevant files ..." << endl;
|
2015-09-04 14:37:01 +02:00
|
|
|
// get package files
|
2015-08-19 02:13:28 +02:00
|
|
|
list<PkgFileInfo> pkgFiles;
|
|
|
|
for(const auto &entry : m_packages) {
|
|
|
|
QString pkgFile;
|
2015-09-04 14:37:01 +02:00
|
|
|
if(!entry.first->packagesDirectory().isEmpty()) {
|
|
|
|
pkgFile = entry.first->packagesDirectory() % QChar('/') % entry.second->fileName();
|
2015-08-19 02:13:28 +02:00
|
|
|
}
|
|
|
|
if(pkgFile.isEmpty() || !QFile::exists(pkgFile)) {
|
|
|
|
if(!m_manager.pacmanCacheDir().isEmpty()) {
|
2015-09-04 14:37:01 +02:00
|
|
|
pkgFile = m_manager.pacmanCacheDir() % QChar('/') % entry.second->fileName();
|
2015-08-19 02:13:28 +02:00
|
|
|
}
|
|
|
|
if(pkgFile.isEmpty() || !QFile::exists(pkgFile)) {
|
2015-09-04 14:37:01 +02:00
|
|
|
throw runtime_error("The package file " + string(entry.second->fileName().toLocal8Bit().data()) + " can't be found.");
|
2015-08-19 02:13:28 +02:00
|
|
|
// TODO: download package from mirror
|
|
|
|
}
|
|
|
|
}
|
2015-09-04 14:37:01 +02:00
|
|
|
pkgFiles.emplace_back(entry.second->name().startsWith(QLatin1String("mingw-w64-")) ? entry.second->name().mid(10) : entry.second->name(), pkgFile);
|
2015-08-19 02:13:28 +02:00
|
|
|
}
|
2015-09-04 14:37:01 +02:00
|
|
|
// get relevant files from packages
|
2015-08-19 02:13:28 +02:00
|
|
|
QtConcurrent::blockingMap(pkgFiles, getFiles);
|
2015-09-04 14:37:01 +02:00
|
|
|
// check whether all packages could be opened
|
|
|
|
string failed;
|
|
|
|
for(const auto &pkgFile : pkgFiles) {
|
|
|
|
if(pkgFile.failure) {
|
|
|
|
failed.push_back(' ');
|
|
|
|
failed.append(pkgFile.path.toLocal8Bit().data());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!failed.empty()) {
|
|
|
|
throw runtime_error("Unable to open the following package files:" + failed);
|
|
|
|
}
|
|
|
|
// make a list with package info to be included in the target archive
|
|
|
|
QJsonArray pkgArray;
|
|
|
|
for(const auto &entry : m_packages) {
|
|
|
|
pkgArray << entry.second->basicInfo(true);
|
|
|
|
}
|
|
|
|
QJsonDocument pkgList;
|
|
|
|
pkgList.setArray(pkgArray);
|
|
|
|
QByteArray pkgListBytes = pkgList.toJson();
|
|
|
|
// make target archive
|
|
|
|
static const QString user(QStringLiteral("root"));
|
|
|
|
static const QString &group = user;
|
|
|
|
static const pair<RelevantFileArch, QString> roots[] = {
|
|
|
|
make_pair(RelevantFileArch::x86_64, QStringLiteral("x86_64-w64-mingw32")),
|
|
|
|
make_pair(RelevantFileArch::i686, QStringLiteral("i686-w64-mingw32"))
|
|
|
|
};
|
|
|
|
for(const auto &root : roots) {
|
|
|
|
QString targetPath = qstr(targetDir) % QChar('/') % root.second % QChar('-') % qstr(targetName) % QChar('.') % qstr(targetFormat);
|
2015-09-05 17:25:05 +02:00
|
|
|
cerr << shchar << "Making archive \"" << targetPath.toLocal8Bit().data() << "\" ..." << endl;
|
2015-09-04 14:37:01 +02:00
|
|
|
unique_ptr<KArchive> targetArchive;
|
|
|
|
if(targetFormat == "7z") {
|
|
|
|
targetArchive = make_unique<K7Zip>(targetPath);
|
|
|
|
} else if(targetFormat == "zip") {
|
|
|
|
targetArchive = make_unique<KZip>(targetPath);
|
|
|
|
} else if(ConversionUtilities::startsWith<string>(targetFormat, "tar")) {
|
|
|
|
targetArchive = make_unique<KTar>(targetPath);
|
|
|
|
} else {
|
|
|
|
throw runtime_error("Specified archive format \"" + targetFormat + "\" is unknown.");
|
|
|
|
}
|
|
|
|
if(targetArchive->open(QIODevice::WriteOnly)) {
|
|
|
|
// add package list
|
|
|
|
targetArchive->writeFile(root.second % QStringLiteral("/var/lib/repoindex/packages.list"), pkgListBytes, 0100644, user, group);
|
|
|
|
// add relevant files from packages
|
|
|
|
for(const auto &pkgFile : pkgFiles) {
|
|
|
|
for(const RelevantFile &relevantFile : pkgFile.relevantFiles) {
|
|
|
|
if(relevantFile.arch == RelevantFileArch::Any || relevantFile.arch == root.first) {
|
|
|
|
switch(relevantFile.fileType) {
|
|
|
|
case RelevantFileType::Binary:
|
|
|
|
targetArchive->writeFile(root.second % QStringLiteral("/bin/") % relevantFile.file->name(), relevantFile.file->data(), 0100755, user, group);
|
|
|
|
break;
|
|
|
|
case RelevantFileType::Translation:
|
|
|
|
targetArchive->writeFile(root.second % QStringLiteral("/share/") % pkgFile.name % QStringLiteral("/translations/") % relevantFile.file->name(), relevantFile.file->data(), 0100644, user, group);
|
|
|
|
break;
|
|
|
|
case RelevantFileType::QtTranslation:
|
|
|
|
targetArchive->writeFile(root.second % QStringLiteral("/share/qt/translations/") % relevantFile.file->name(), relevantFile.file->data(), 0100644, user, group);
|
|
|
|
break;
|
|
|
|
case RelevantFileType::QtPlugin:
|
|
|
|
targetArchive->writeFile(root.second % QStringLiteral("/bin/") % relevantFile.subDir % QChar('/') % relevantFile.file->name(), relevantFile.file->data(), 0100755, user, group);
|
|
|
|
break;
|
|
|
|
case RelevantFileType::Icon:
|
|
|
|
targetArchive->writeFile(root.second % QStringLiteral("/share/icons/") % relevantFile.subDir % QChar('/') % relevantFile.file->name(), relevantFile.file->data(), 0100644, user, group);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-08-19 02:13:28 +02:00
|
|
|
}
|
|
|
|
}
|
2015-09-04 14:37:01 +02:00
|
|
|
} else if(targetArchive->device()) {
|
|
|
|
throw runtime_error("Unable to open target archive: " + string(targetArchive->device()->errorString().toLocal8Bit().data()));
|
|
|
|
} else {
|
|
|
|
throw runtime_error("Unable to open target archive.");
|
2015-08-19 02:13:28 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace PackageManagement
|
|
|
|
|