mirror of https://github.com/mgba-emu/mgba.git
Qt: Initial support for forwarder-kit
This commit is contained in:
parent
6bdb3470e7
commit
7f30bdc850
|
@ -11,9 +11,11 @@
|
|||
#include <QNetworkReply>
|
||||
|
||||
#include "ConfigController.h"
|
||||
#include "VFileDevice.h"
|
||||
|
||||
#include <mgba/core/version.h>
|
||||
#include <mgba/feature/updater.h>
|
||||
#include <mgba-util/vfs.h>
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
|
@ -28,22 +30,17 @@ const char* SUFFIX = "";
|
|||
ForwarderController::ForwarderController(QObject* parent)
|
||||
: QObject(parent)
|
||||
, m_netman(new QNetworkAccessManager(this))
|
||||
, m_originalPath(qgetenv("PATH"))
|
||||
{
|
||||
m_netman->setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy);
|
||||
connect(this, &ForwarderController::buildFailed, this, [this]() {
|
||||
m_inProgress = false;
|
||||
});
|
||||
connect(this, &ForwarderController::buildComplete, this, [this]() {
|
||||
m_inProgress = false;
|
||||
});
|
||||
connect(this, &ForwarderController::buildFailed, this, &ForwarderController::cleanup);
|
||||
connect(this, &ForwarderController::buildComplete, this, &ForwarderController::cleanup);
|
||||
}
|
||||
|
||||
void ForwarderController::setGenerator(std::unique_ptr<ForwarderGenerator>&& generator) {
|
||||
m_generator = std::move(generator);
|
||||
connect(m_generator.get(), &ForwarderGenerator::buildFailed, this, &ForwarderController::buildFailed);
|
||||
connect(m_generator.get(), &ForwarderGenerator::buildFailed, this, &ForwarderController::cleanup);
|
||||
connect(m_generator.get(), &ForwarderGenerator::buildComplete, this, &ForwarderController::buildComplete);
|
||||
connect(m_generator.get(), &ForwarderGenerator::buildComplete, this, &ForwarderController::cleanup);
|
||||
}
|
||||
|
||||
void ForwarderController::startBuild(const QString& outFilename) {
|
||||
|
@ -53,6 +50,15 @@ void ForwarderController::startBuild(const QString& outFilename) {
|
|||
m_inProgress = true;
|
||||
m_outFilename = outFilename;
|
||||
|
||||
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
|
||||
// Amend the path for downloaded programs forwarder-kit
|
||||
QByteArray arr = m_originalPath;
|
||||
QStringList path = QString::fromUtf8(arr).split(LIST_SPLIT);
|
||||
path << ConfigController::cacheDir();
|
||||
arr = path.join(LIST_SPLIT).toUtf8();
|
||||
qputenv("PATH", arr);
|
||||
#endif
|
||||
|
||||
QStringList neededTools = m_generator->externalTools();
|
||||
for (const auto& tool : neededTools) {
|
||||
if (!toolInstalled(tool)) {
|
||||
|
@ -64,8 +70,67 @@ void ForwarderController::startBuild(const QString& outFilename) {
|
|||
}
|
||||
|
||||
void ForwarderController::downloadForwarderKit() {
|
||||
QString fkUrl("https://github.com/mgba-emu/forwarder-kit/releases/latest/download/forwarder-kit-%1.zip");
|
||||
#ifdef Q_OS_WIN64
|
||||
fkUrl = fkUrl.arg("win64");
|
||||
#elif defined(Q_OS_WIN32)
|
||||
fkUrl = fkUrl.arg("win32");
|
||||
#elif defined(Q_OS_MAC) && (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||
// Modern macOS build
|
||||
fkUrl = fkUrl.arg("macos");
|
||||
#else
|
||||
// TODO
|
||||
emit buildFailed();
|
||||
return;
|
||||
#endif
|
||||
QNetworkReply* reply = m_netman->get(QNetworkRequest(QUrl(fkUrl)));
|
||||
connect(reply, &QNetworkReply::finished, this, [this, reply]() {
|
||||
gotForwarderKit(reply);
|
||||
});
|
||||
connectErrorFailure(reply);
|
||||
}
|
||||
|
||||
void ForwarderController::gotForwarderKit(QNetworkReply* reply) {
|
||||
if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() != 200) {
|
||||
emit buildFailed();
|
||||
return;
|
||||
}
|
||||
|
||||
QFile fkZip(ConfigController::cacheDir() + "/forwarder-kit.zip");
|
||||
fkZip.open(QIODevice::WriteOnly | QIODevice::Truncate);
|
||||
QByteArray arr;
|
||||
do {
|
||||
arr = reply->read(0x800);
|
||||
fkZip.write(arr);
|
||||
} while (!arr.isEmpty());
|
||||
fkZip.close();
|
||||
|
||||
VDir* fkDir = VFileDevice::openArchive(fkZip.fileName());
|
||||
|
||||
// This has to be done in multiple passes to avoid seeking breaking the listing
|
||||
QStringList files;
|
||||
for (VDirEntry* entry = fkDir->listNext(fkDir); entry; entry = fkDir->listNext(fkDir)) {
|
||||
if (entry->type(entry) != VFS_FILE) {
|
||||
continue;
|
||||
}
|
||||
files << entry->name(entry);
|
||||
}
|
||||
|
||||
for (const QString& source : files) {
|
||||
VFile* sourceVf = fkDir->openFile(fkDir, source.toUtf8().constData(), O_RDONLY);
|
||||
VFile* targetVf = VFileDevice::open(ConfigController::cacheDir() + "/" + source, O_CREAT | O_TRUNC | O_WRONLY);
|
||||
VFileDevice::copyFile(sourceVf, targetVf);
|
||||
sourceVf->close(sourceVf);
|
||||
targetVf->close(targetVf);
|
||||
|
||||
QFile target(ConfigController::cacheDir() + "/" + source);
|
||||
target.setPermissions(target.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeUser);
|
||||
}
|
||||
|
||||
fkDir->close(fkDir);
|
||||
fkZip.remove();
|
||||
|
||||
downloadManifest();
|
||||
}
|
||||
|
||||
void ForwarderController::downloadManifest() {
|
||||
|
@ -73,13 +138,7 @@ void ForwarderController::downloadManifest() {
|
|||
connect(reply, &QNetworkReply::finished, this, [this, reply]() {
|
||||
gotManifest(reply);
|
||||
});
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||
connect(reply, &QNetworkReply::errorOccurred, this, [this, reply]() {
|
||||
#else
|
||||
connect(reply, qOverload<>(&QNetworkReply::error), this, [this, reply]() {
|
||||
#endif
|
||||
emit buildFailed();
|
||||
});
|
||||
connectErrorFailure(reply);
|
||||
}
|
||||
|
||||
void ForwarderController::gotManifest(QNetworkReply* reply) {
|
||||
|
@ -128,6 +187,7 @@ void ForwarderController::downloadBuild(const QUrl& url) {
|
|||
QByteArray data = reply->readAll();
|
||||
m_sourceFile.write(data);
|
||||
});
|
||||
connectErrorFailure(reply);
|
||||
}
|
||||
|
||||
void ForwarderController::gotBuild(QNetworkReply* reply) {
|
||||
|
@ -144,6 +204,11 @@ void ForwarderController::gotBuild(QNetworkReply* reply) {
|
|||
|
||||
void ForwarderController::cleanup() {
|
||||
m_sourceFile.remove();
|
||||
m_inProgress = false;
|
||||
|
||||
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
|
||||
qputenv("PATH", m_originalPath);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ForwarderController::toolInstalled(const QString& tool) {
|
||||
|
@ -157,3 +222,13 @@ bool ForwarderController::toolInstalled(const QString& tool) {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ForwarderController::connectErrorFailure(QNetworkReply* reply) {
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||
connect(reply, &QNetworkReply::errorOccurred, this, [this, reply]() {
|
||||
#else
|
||||
connect(reply, qOverload<>(&QNetworkReply::error), this, [this, reply]() {
|
||||
#endif
|
||||
emit buildFailed();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ signals:
|
|||
private slots:
|
||||
void gotManifest(QNetworkReply*);
|
||||
void gotBuild(QNetworkReply*);
|
||||
void gotForwarderKit(QNetworkReply*);
|
||||
|
||||
private:
|
||||
void downloadForwarderKit();
|
||||
|
@ -46,12 +47,15 @@ private:
|
|||
bool toolInstalled(const QString& tool);
|
||||
void cleanup();
|
||||
|
||||
void connectErrorFailure(QNetworkReply*);
|
||||
|
||||
QString m_channel{"dev"};
|
||||
QString m_outFilename;
|
||||
QNetworkAccessManager* m_netman;
|
||||
std::unique_ptr<ForwarderGenerator> m_generator;
|
||||
QFile m_sourceFile;
|
||||
bool m_inProgress = false;
|
||||
QByteArray m_originalPath;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue