repoindex/alpm/mingwbundle.cpp

171 lines
5.5 KiB
C++

#include "mingwbundle.h"
#include "manager.h"
#include <c++utilities/conversion/stringconversion.h>
#include <c++utilities/misc/memory.h>
#include <KTar>
#include <QFile>
#include <QtConcurrent/QtConcurrent>
#include <string>
#include <iostream>
using namespace std;
namespace PackageManagement {
const string prefix("mingw-w64-");
MingwBundle::MingwBundle(const Manager &manager, const ApplicationUtilities::StringVector &packages) :
m_manager(manager)
{
string missing;
for(const auto &pkgName : packages) {
bool found = false;
for(const auto &syncDb : manager.syncDataBases()) {
if(auto pkg = syncDb.second.package(ConversionUtilities::startsWith(pkgName, prefix) ? pkgName.data() : (prefix + pkgName).data())) {
if(missing.empty()) {
m_packages.emplace_back(syncDb.second, pkg);
}
addDependencies(pkg);
found = true;
break;
}
}
if(!found) {
missing.push_back(' ');
missing.append(pkgName);
}
}
if(!missing.empty()) {
throw runtime_error("The following packages can not be found:" + missing);
} else {
cerr << "Adding the following packages:";
for(const auto &pkg : m_packages) {
cerr << ' ' << pkg.second.name();
}
cerr << endl;
}
}
enum class RelevantFileType
{
Binary,
Translation
};
enum class RelevantFileArch
{
x86_64,
i686
};
struct RelevantFile
{
RelevantFile(const KArchiveFile *file, const RelevantFileType type, const RelevantFileArch arch) :
file(file),
fileType(type),
arch(arch)
{}
const KArchiveFile *file;
RelevantFileType fileType;
RelevantFileArch arch;
};
struct PkgFileInfo
{
PkgFileInfo(const QString &path) : path(path), failure(false) {}
QString path;
unique_ptr<KTar> archive;
list<RelevantFile> relevantFiles;
bool failure;
};
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);
cerr << entryName.toLocal8Bit().data() << endl;
}
}
}
}
}
}
}
} else {
pkgFileInfo.failure = true;
}
}
void MingwBundle::createBundle(const string &path) const
{
list<PkgFileInfo> pkgFiles;
for(const auto &entry : m_packages) {
QString pkgFile;
if(!entry.first.packagesDirectory().isEmpty()) {
pkgFile = QStringLiteral("%1/%2").arg(entry.first.packagesDirectory(), QString::fromLocal8Bit(entry.second.fileName()));
}
if(pkgFile.isEmpty() || !QFile::exists(pkgFile)) {
if(!m_manager.pacmanCacheDir().isEmpty()) {
pkgFile = QStringLiteral("%1/%2").arg(m_manager.pacmanCacheDir(), QString::fromLocal8Bit(entry.second.fileName()));
}
if(pkgFile.isEmpty() || !QFile::exists(pkgFile)) {
throw runtime_error("The package file " + string(entry.second.fileName()) + " can't be found.");
// TODO: download package from mirror
}
}
pkgFiles.emplace_back(pkgFile);
}
QtConcurrent::blockingMap(pkgFiles, getFiles);
}
void MingwBundle::addDependencies(const AlpmPackage &pkg)
{
string missing;
for(const auto &depInfo : pkg.dependencies()) {
bool found = false;
for(const auto &syncDb : m_manager.syncDataBases()) {
if(auto pkg = syncDb.second.package(depInfo->name)) {
if(missing.empty()) {
m_packages.emplace_back(syncDb.second, pkg);
}
addDependencies(pkg);
found = true;
break;
}
}
if(!found) {
missing.push_back(' ');
missing.append(depInfo->name);
}
}
if(!missing.empty()) {
throw runtime_error("The following dependencies of the " + string(pkg.name()) + " package can not be resolved:" + missing);
}
}
} // namespace PackageManagement