feat(updater) select valid asset
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
parent
98174b7a37
commit
bee88b1c7f
@ -584,6 +584,7 @@ set(PRISMUPDATER_SOURCES
|
||||
updater/prismupdater/UpdaterDialogs.h
|
||||
updater/prismupdater/UpdaterDialogs.cpp
|
||||
updater/prismupdater/GitHubRelease.h
|
||||
updater/prismupdater/GitHubRelease.cpp
|
||||
|
||||
Json.h
|
||||
Json.cpp
|
||||
|
36
launcher/updater/prismupdater/GitHubRelease.cpp
Normal file
36
launcher/updater/prismupdater/GitHubRelease.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
#include "GitHubRelease.h"
|
||||
|
||||
QDebug operator<<(QDebug debug, const GitHubReleaseAsset& asset)
|
||||
{
|
||||
QDebugStateSaver saver(debug);
|
||||
debug.nospace() << "GitHubReleaseAsset( "
|
||||
"id: " << asset.id << ", "
|
||||
"name " << asset.name << ", "
|
||||
"label: " << asset.label << ", "
|
||||
"content_type: " << asset.content_type << ", "
|
||||
"size: " << asset.size << ", "
|
||||
"created_at: " << asset.created_at << ", "
|
||||
"updated_at: " << asset.updated_at << ", "
|
||||
"browser_download_url: " << asset.browser_download_url << " "
|
||||
")";
|
||||
return debug;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, const GitHubRelease& rls)
|
||||
{
|
||||
QDebugStateSaver saver(debug);
|
||||
debug.nospace() << "GitHubRelease( "
|
||||
"id: " << rls.id << ", "
|
||||
"name " << rls.name << ", "
|
||||
"tag_name: " << rls.tag_name << ", "
|
||||
"created_at: " << rls.created_at << ", "
|
||||
"published_at: " << rls.published_at << ", "
|
||||
"prerelease: " << rls.prerelease << ", "
|
||||
"draft: " << rls.draft << ", "
|
||||
"version" << rls.version << ", "
|
||||
"body: " << rls.body << ", "
|
||||
"assets: " << rls.assets << " "
|
||||
")";
|
||||
return debug;
|
||||
}
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "Version.h"
|
||||
|
||||
struct GitHubReleaseAsset {
|
||||
@ -32,3 +34,7 @@ struct GitHubRelease {
|
||||
|
||||
bool isValid() const { return id > 0; }
|
||||
};
|
||||
|
||||
QDebug operator<<(QDebug debug, const GitHubReleaseAsset& rls);
|
||||
QDebug operator<<(QDebug debug, const GitHubRelease& rls);
|
||||
|
||||
|
@ -33,8 +33,8 @@
|
||||
#include <QDebug>
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkProxy>
|
||||
#include <QNetworkRequest>
|
||||
#include <QProcess>
|
||||
#include <memory>
|
||||
|
||||
@ -128,17 +128,16 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription(QObject::tr("An auto-updater for Prism Launcher"));
|
||||
|
||||
parser.addOptions({ { { "d", "dir" }, "Use a custom path as application root (use '.' for current directory).", "directory" },
|
||||
{ { "I", "install-version" }, "Install a spesfic version.", "version name" },
|
||||
{ { "U", "update-url" }, "Update from the spesified repo.", "github repo url" },
|
||||
{ { "e", "executable" }, "Path to the prismluancher executable.", "path" },
|
||||
parser.addOptions({ { { "d", "dir" }, tr("Use a custom path as application root (use '.' for current directory)."), tr("directory") },
|
||||
{ { "I", "install-version" }, "Install a spesfic version.", tr("version name") },
|
||||
{ { "U", "update-url" }, tr("Update from the spesified repo."), tr("github repo url") },
|
||||
{ { "c", "check-only" },
|
||||
"Only check if an update is needed. Exit status 100 if true, 0 if false (or non 0 if there was an error)." },
|
||||
{ { "F", "force" }, "Force an update, even if one is not needed." },
|
||||
{ { "l", "list" }, "List avalible releases." },
|
||||
{ "debug", "Log debug to console." },
|
||||
{ { "L", "latest" }, "Update to the latest avalible version." },
|
||||
{ { "D", "allow-downgrade" }, "Allow the updater to downgrade to previous verisons." } });
|
||||
tr("Only check if an update is needed. Exit status 100 if true, 0 if false (or non 0 if there was an error).") },
|
||||
{ { "F", "force" }, tr("Force an update, even if one is not needed.") },
|
||||
{ { "l", "list" }, tr("List avalible releases.") },
|
||||
{ "debug", tr("Log debug to console.") },
|
||||
{ { "L", "latest" }, tr("Update to the latest avalible version.") },
|
||||
{ { "D", "allow-downgrade" }, tr("Allow the updater to downgrade to previous verisons.") } });
|
||||
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
@ -146,13 +145,25 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar
|
||||
|
||||
logToConsole = parser.isSet("debug");
|
||||
|
||||
auto prism_executable = parser.value("executable");
|
||||
if (prism_executable.isEmpty()) {
|
||||
prism_executable = QCoreApplication::applicationDirPath() + "/" + BuildConfig.LAUNCHER_APP_BINARY_NAME;
|
||||
auto prism_executable = QCoreApplication::applicationDirPath() + "/" + BuildConfig.LAUNCHER_APP_BINARY_NAME;
|
||||
#if defined(Q_OS_WIN32)
|
||||
prism_executable += ".exe";
|
||||
prism_executable += ".exe";
|
||||
#endif
|
||||
|
||||
if (BuildConfig.BUILD_PLATFORM.toLower() == "macos")
|
||||
showFatalErrorMessage(tr("MacOS Not Supported"), tr("The updater does not support instaltions on MacOS"));
|
||||
|
||||
if (!QFileInfo(prism_executable).isFile())
|
||||
showFatalErrorMessage(tr("Unsupprted Instaltion"), tr("The updater can not find the main exacutable."));
|
||||
|
||||
if (prism_executable.startsWith("/tmp/.mount_")) {
|
||||
m_appimage = true;
|
||||
m_appimagePath = QProcessEnvironment::systemEnvironment().value(QStringLiteral("APPIMAGE"));
|
||||
if (m_appimagePath.isEmpty())
|
||||
showFatalErrorMessage(tr("Unsupprted Instaltion"),
|
||||
tr("Updater is running as misconfigured AppImage? ($APPIMAGE environment variable is missing)"));
|
||||
}
|
||||
|
||||
m_prismExecutable = prism_executable;
|
||||
|
||||
auto prism_update_url = parser.value("update-url");
|
||||
@ -210,7 +221,7 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
{ // setup logging
|
||||
static const QString logBase = BuildConfig.LAUNCHER_NAME + "Updater" + (m_checkOnly ? "-CheckOnly" : "") + "-%0.log";
|
||||
auto moveFile = [](const QString& oldName, const QString& newName) {
|
||||
@ -226,13 +237,13 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar
|
||||
|
||||
logFile = std::unique_ptr<QFile>(new QFile(logBase.arg(0)));
|
||||
if (!logFile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
|
||||
showFatalErrorMessage("The launcher data folder is not writable!",
|
||||
QString("The launcher couldn't create a log file - the data folder is not writable.\n"
|
||||
"\n"
|
||||
"Make sure you have write permissions to the data folder.\n"
|
||||
"(%1)\n"
|
||||
"\n"
|
||||
"The launcher cannot continue until you fix this problem.")
|
||||
showFatalErrorMessage(tr("The launcher data folder is not writable!"),
|
||||
tr("The launcher couldn't create a log file - the data folder is not writable.\n"
|
||||
"\n"
|
||||
"Make sure you have write permissions to the data folder.\n"
|
||||
"(%1)\n"
|
||||
"\n"
|
||||
"The launcher cannot continue until you fix this problem.")
|
||||
.arg(dataPath));
|
||||
return;
|
||||
}
|
||||
@ -296,8 +307,6 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar
|
||||
qDebug() << "<> Log initialized.";
|
||||
}
|
||||
|
||||
|
||||
|
||||
{ // log debug program info
|
||||
qDebug() << qPrintable(BuildConfig.LAUNCHER_DISPLAYNAME) << "Updater"
|
||||
<< ", (c) 2022-2023 " << qPrintable(QString(BuildConfig.LAUNCHER_COPYRIGHT).replace("\n", ", "));
|
||||
@ -316,7 +325,7 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar
|
||||
qDebug() << "<> Paths set.";
|
||||
}
|
||||
|
||||
{ // network
|
||||
{ // network
|
||||
m_network = makeShared<QNetworkAccessManager>(new QNetworkAccessManager());
|
||||
qDebug() << "Detecting proxy settings...";
|
||||
QNetworkProxy proxy = QNetworkProxy::applicationProxy();
|
||||
@ -341,7 +350,6 @@ PrismUpdaterApp::~PrismUpdaterApp()
|
||||
FreeConsole();
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void PrismUpdaterApp::fail(const QString& reason)
|
||||
@ -477,17 +485,79 @@ GitHubRelease PrismUpdaterApp::selectRelease()
|
||||
SelectReleaseDialog dlg(Version(m_prismVerison), releases);
|
||||
auto result = dlg.exec();
|
||||
|
||||
if (result == QDialog::Rejected) {
|
||||
return {};
|
||||
}
|
||||
GitHubRelease release = dlg.selectedRelease();
|
||||
|
||||
return release;
|
||||
}
|
||||
|
||||
QList<GitHubReleaseAsset> PrismUpdaterApp::validReleaseArtifacts(const GitHubRelease& release)
|
||||
{
|
||||
QList<GitHubReleaseAsset> valid;
|
||||
|
||||
qDebug() << "Selecting best asset from" << release.tag_name << "for platfom" << BuildConfig.BUILD_PLATFORM << "portable:" << m_portable;
|
||||
if (BuildConfig.BUILD_PLATFORM.isEmpty())
|
||||
qWarning() << "Build platform is not set!";
|
||||
for (auto asset : release.assets) {
|
||||
if (!m_appimage && asset.name.toLower().endsWith("appimage"))
|
||||
continue;
|
||||
else if (m_appimage && !asset.name.toLower().endsWith("appimage"))
|
||||
continue;
|
||||
|
||||
bool for_platform = !BuildConfig.BUILD_PLATFORM.isEmpty() && asset.name.toLower().contains(BuildConfig.BUILD_PLATFORM.toLower());
|
||||
bool for_portable = asset.name.toLower().contains("portable");
|
||||
if (((m_portable && for_portable) || (!m_portable && !for_portable)) && for_platform) {
|
||||
valid.append(asset);
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
GitHubReleaseAsset PrismUpdaterApp::selectAsset(const QList<GitHubReleaseAsset>& assets)
|
||||
{
|
||||
SelectReleaseAssetDialog dlg(assets);
|
||||
auto result = dlg.exec();
|
||||
|
||||
if (result == QDialog::Rejected) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return release;
|
||||
GitHubReleaseAsset asset = dlg.selectedAsset();
|
||||
return asset;
|
||||
}
|
||||
|
||||
void PrismUpdaterApp::performUpdate(const GitHubRelease& release)
|
||||
{
|
||||
qDebug() << "Updating to" << release.tag_name;
|
||||
auto valid_assets = validReleaseArtifacts(release);
|
||||
qDebug() << "vallid release assets:" << valid_assets;
|
||||
|
||||
GitHubReleaseAsset selected_asset;
|
||||
if (valid_assets.isEmpty()) {
|
||||
showFatalErrorMessage(tr("No Valid Release Assets"),
|
||||
tr("Github release %1 has no valid assets for this platform: %2")
|
||||
.arg(release.tag_name)
|
||||
.arg(tr("%1 portable: %2").arg(BuildConfig.BUILD_PLATFORM).arg(m_portable)));
|
||||
return;
|
||||
} else if (valid_assets.length() > 1) {
|
||||
selected_asset = selectAsset(valid_assets);
|
||||
} else {
|
||||
selected_asset = valid_assets.takeFirst();
|
||||
}
|
||||
|
||||
if (! selected_asset.isValid()) {
|
||||
showFatalErrorMessage("No version selected.", "No version was selected.");
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "will intall" << selected_asset;
|
||||
}
|
||||
|
||||
QFileInfo PrismUpdaterApp::downloadAsset(const GitHubReleaseAsset& asset)
|
||||
{
|
||||
// TODO! (researching what to do with appimages)
|
||||
}
|
||||
|
||||
void PrismUpdaterApp::loadPrismVersionFromExe(const QString& exe_path)
|
||||
@ -562,14 +632,12 @@ void PrismUpdaterApp::downloadReleasePage(const QString& api_url, int page)
|
||||
});
|
||||
connect(download.get(), &Net::Download::failed, this, &PrismUpdaterApp::downloadError);
|
||||
|
||||
|
||||
m_current_task.reset(download);
|
||||
connect(download.get(), &Net::Download::finished, this, [this](){
|
||||
connect(download.get(), &Net::Download::finished, this, [this]() {
|
||||
qDebug() << "Download" << m_current_task->getUid().toString() << "finsihed";
|
||||
m_current_task.reset();
|
||||
m_current_url = "";
|
||||
});
|
||||
|
||||
|
||||
QCoreApplication::processEvents();
|
||||
|
||||
|
@ -39,7 +39,6 @@
|
||||
#include "QObjectPtr.h"
|
||||
#include "net/Download.h"
|
||||
|
||||
|
||||
#define PRISM_EXTERNAL_EXE
|
||||
#include "FileSystem.h"
|
||||
|
||||
@ -65,25 +64,34 @@ class PrismUpdaterApp : public QApplication {
|
||||
|
||||
void downloadReleasePage(const QString& api_url, int page);
|
||||
int parseReleasePage(const QByteArray* responce);
|
||||
GitHubRelease getLatestRelease();
|
||||
|
||||
bool needUpdate(const GitHubRelease& release);
|
||||
|
||||
GitHubRelease getLatestRelease();
|
||||
GitHubRelease selectRelease();
|
||||
void performUpdate(const GitHubRelease& release);
|
||||
void printReleases();
|
||||
QList<GitHubRelease> newerReleases();
|
||||
QList<GitHubRelease> nonDraftReleases();
|
||||
|
||||
void printReleases();
|
||||
|
||||
QList<GitHubReleaseAsset> validReleaseArtifacts(const GitHubRelease& release);
|
||||
GitHubReleaseAsset selectAsset(const QList<GitHubReleaseAsset>& assets);
|
||||
void performUpdate(const GitHubRelease& release);
|
||||
|
||||
QFileInfo downloadAsset(const GitHubReleaseAsset& asset);
|
||||
|
||||
public slots:
|
||||
void downloadError(QString reason);
|
||||
|
||||
private:
|
||||
|
||||
const QString& root() { return m_rootPath; }
|
||||
|
||||
bool isPortable() { return m_portable; }
|
||||
|
||||
QString m_rootPath;
|
||||
bool m_portable = false;
|
||||
bool m_appimage = false;
|
||||
QString m_appimagePath;
|
||||
QString m_prismExecutable;
|
||||
QUrl m_prismRepoUrl;
|
||||
Version m_userSelectedVersion;
|
||||
|
@ -76,3 +76,71 @@ void SelectReleaseDialog::selectionChanged(QTreeWidgetItem* current, QTreeWidget
|
||||
ui->changelogTextBrowser->setHtml(body);
|
||||
}
|
||||
|
||||
|
||||
|
||||
SelectReleaseAssetDialog::SelectReleaseAssetDialog( const QList<GitHubReleaseAsset>& assets, QWidget* parent)
|
||||
: QDialog(parent), m_assets(assets), ui(new Ui::SelectReleaseDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->changelogTextBrowser->setOpenExternalLinks(true);
|
||||
ui->changelogTextBrowser->setLineWrapMode(QTextBrowser::LineWrapMode::WidgetWidth);
|
||||
ui->changelogTextBrowser->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded);
|
||||
|
||||
ui->versionsTree->setColumnCount(2);
|
||||
|
||||
ui->versionsTree->header()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
ui->versionsTree->header()->setSectionResizeMode(1, QHeaderView::Stretch);
|
||||
ui->versionsTree->setHeaderLabels({tr("Verison"), tr("Published Date")});
|
||||
ui->versionsTree->header()->setStretchLastSection(false);
|
||||
|
||||
ui->eplainLabel->setText(tr("Select a version to install."));
|
||||
|
||||
ui->changelogTextBrowser->setHidden(true);
|
||||
|
||||
loadAssets();
|
||||
|
||||
connect(ui->versionsTree, &QTreeWidget::currentItemChanged, this, &SelectReleaseAssetDialog::selectionChanged);
|
||||
|
||||
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &SelectReleaseAssetDialog::accept);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &SelectReleaseAssetDialog::reject);
|
||||
}
|
||||
|
||||
SelectReleaseAssetDialog::~SelectReleaseAssetDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void SelectReleaseAssetDialog::loadAssets()
|
||||
{
|
||||
for (auto rls : m_assets) {
|
||||
appendAsset(rls);
|
||||
}
|
||||
}
|
||||
|
||||
void SelectReleaseAssetDialog::appendAsset(GitHubReleaseAsset const& asset)
|
||||
{
|
||||
auto rls_item = new QTreeWidgetItem(ui->versionsTree);
|
||||
rls_item->setText(0, asset.name);
|
||||
rls_item->setExpanded(true);
|
||||
rls_item->setText(1, asset.updated_at.toString());
|
||||
rls_item->setData(0, Qt::UserRole, QVariant(asset.id));
|
||||
|
||||
ui->versionsTree->addTopLevelItem(rls_item);
|
||||
}
|
||||
|
||||
GitHubReleaseAsset SelectReleaseAssetDialog::getAsset(QTreeWidgetItem* item) {
|
||||
int id = item->data(0, Qt::UserRole).toInt();
|
||||
GitHubReleaseAsset selected_asset;
|
||||
for (auto asset: m_assets) {
|
||||
if (asset.id == id)
|
||||
selected_asset = asset;
|
||||
}
|
||||
return selected_asset;
|
||||
}
|
||||
|
||||
void SelectReleaseAssetDialog::selectionChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous)
|
||||
{
|
||||
GitHubReleaseAsset asset = getAsset(current);
|
||||
m_selectedAsset = asset;
|
||||
}
|
||||
|
@ -31,3 +31,23 @@ class SelectReleaseDialog : public QDialog {
|
||||
|
||||
Ui::SelectReleaseDialog* ui;
|
||||
};
|
||||
|
||||
class SelectReleaseAssetDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SelectReleaseAssetDialog(const QList<GitHubReleaseAsset>& assets, QWidget* parent = 0);
|
||||
~SelectReleaseAssetDialog();
|
||||
|
||||
void loadAssets();
|
||||
void appendAsset(GitHubReleaseAsset const& asset);
|
||||
GitHubReleaseAsset selectedAsset() { return m_selectedAsset; }
|
||||
private slots:
|
||||
GitHubReleaseAsset getAsset(QTreeWidgetItem* item);
|
||||
void selectionChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous);
|
||||
|
||||
protected:
|
||||
QList<GitHubReleaseAsset> m_assets;
|
||||
GitHubReleaseAsset m_selectedAsset;
|
||||
|
||||
Ui::SelectReleaseDialog* ui;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user