feat(updater): tie in updater part 1
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
parent
90da57a806
commit
d8e0b14dc4
@ -132,6 +132,8 @@
|
|||||||
|
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
#include "updater/MacSparkleUpdater.h"
|
#include "updater/MacSparkleUpdater.h"
|
||||||
|
#else
|
||||||
|
#include "updater/PrismExternalUpdater.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined Q_OS_WIN32
|
#if defined Q_OS_WIN32
|
||||||
@ -271,10 +273,15 @@ void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr
|
|||||||
Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
||||||
{
|
{
|
||||||
#if defined Q_OS_WIN32
|
#if defined Q_OS_WIN32
|
||||||
// attach the parent console
|
// attach the parent console if stdout not already captured
|
||||||
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
|
auto stdout_type = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE));
|
||||||
|
if (stdout_type == FILE_TYPE_CHAR || stdout_type == FILE_TYPE_UNKNOWN) {
|
||||||
|
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
|
||||||
|
BindCrtHandlesToStdHandles(true, true, true);
|
||||||
|
consoleAttached = true;
|
||||||
|
}
|
||||||
|
} else if (stdout_type == FILE_TYPE_DISK || stdout_type == FILE_TYPE_PIPE ) {
|
||||||
BindCrtHandlesToStdHandles(true, true, true);
|
BindCrtHandlesToStdHandles(true, true, true);
|
||||||
consoleAttached = true;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
setOrganizationName(BuildConfig.LAUNCHER_NAME);
|
setOrganizationName(BuildConfig.LAUNCHER_NAME);
|
||||||
@ -823,6 +830,8 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
|||||||
qDebug() << "Initializing updater";
|
qDebug() << "Initializing updater";
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
m_updater.reset(new MacSparkleUpdater());
|
m_updater.reset(new MacSparkleUpdater());
|
||||||
|
#else
|
||||||
|
m_updater.reset(new PrismExternalUpdater(m_rootPath, dataPath));
|
||||||
#endif
|
#endif
|
||||||
qDebug() << "<> Updater started.";
|
qDebug() << "<> Updater started.";
|
||||||
}
|
}
|
||||||
|
@ -179,6 +179,11 @@ set(MAC_UPDATE_SOURCES
|
|||||||
updater/MacSparkleUpdater.mm
|
updater/MacSparkleUpdater.mm
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(PRISM_UPDATE_SOURCES
|
||||||
|
updater/PrismExternalUpdater.h
|
||||||
|
updater/PrismExternalUpdater.cpp
|
||||||
|
)
|
||||||
|
|
||||||
# Backend for the news bar... there's usually no news.
|
# Backend for the news bar... there's usually no news.
|
||||||
set(NEWS_SOURCES
|
set(NEWS_SOURCES
|
||||||
# News System
|
# News System
|
||||||
@ -728,6 +733,8 @@ set(LOGIC_SOURCES
|
|||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
set (LOGIC_SOURCES ${LOGIC_SOURCES} ${MAC_UPDATE_SOURCES})
|
set (LOGIC_SOURCES ${LOGIC_SOURCES} ${MAC_UPDATE_SOURCES})
|
||||||
|
else()
|
||||||
|
set (LOGIC_SOURCES ${LOGIC_SOURCES} ${PRISM_UPDATE_SOURCES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
SET(LAUNCHER_SOURCES
|
SET(LAUNCHER_SOURCES
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "StringUtils.h"
|
#include "StringUtils.h"
|
||||||
|
#include <qpair.h>
|
||||||
|
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
@ -149,7 +150,7 @@ QString StringUtils::truncateUrlHumanFriendly(QUrl& url, int max_len, bool hard_
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((url_compact.length() >= max_len) && hard_limit) {
|
if ((url_compact.length() >= max_len) && hard_limit) {
|
||||||
// still too long, truncate normaly
|
// still too long, truncate normally
|
||||||
url_compact = QString(str_url);
|
url_compact = QString(str_url);
|
||||||
auto to_remove = url_compact.length() - max_len + 3;
|
auto to_remove = url_compact.length() - max_len + 3;
|
||||||
url_compact.remove(url_compact.length() - to_remove - 1, to_remove);
|
url_compact.remove(url_compact.length() - to_remove - 1, to_remove);
|
||||||
@ -182,3 +183,28 @@ QString StringUtils::getRandomAlphaNumeric()
|
|||||||
{
|
{
|
||||||
return QUuid::createUuid().toString(QUuid::Id128);
|
return QUuid::createUuid().toString(QUuid::Id128);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPair<QString, QString> splitFirst(const QString& s, const QString& sep, Qt::CaseSensitivity cs = Qt::CaseSensitive) {
|
||||||
|
QString left, right;
|
||||||
|
auto index = s.indexOf(sep, 0, cs);
|
||||||
|
left = s.mid(0, index);
|
||||||
|
right = s.mid(index + 1);
|
||||||
|
return qMakePair(left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPair<QString, QString> splitFirst(const QString& s, QChar sep, Qt::CaseSensitivity cs = Qt::CaseSensitive) {
|
||||||
|
QString left, right;
|
||||||
|
auto index = s.indexOf(sep, 0, cs);
|
||||||
|
left = s.mid(0, index);
|
||||||
|
right = s.mid(index + 1);
|
||||||
|
return qMakePair(left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPair<QString, QString> splitFirst(const QString& s, const QRegularExpression& re) {
|
||||||
|
QString left, right;
|
||||||
|
auto index = s.indexOf(re);
|
||||||
|
left = s.mid(0, index);
|
||||||
|
right = s.mid(index + 1);
|
||||||
|
return qMakePair(left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QPair>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace StringUtils {
|
namespace StringUtils {
|
||||||
|
|
||||||
@ -70,8 +72,8 @@ int naturalCompare(const QString& s1, const QString& s2, Qt::CaseSensitivity cs)
|
|||||||
/**
|
/**
|
||||||
* @brief Truncate a url while keeping its readability py placing the `...` in the middle of the path
|
* @brief Truncate a url while keeping its readability py placing the `...` in the middle of the path
|
||||||
* @param url Url to truncate
|
* @param url Url to truncate
|
||||||
* @param max_len max lenght of url in charaters
|
* @param max_len max length of url in characters
|
||||||
* @param hard_limit if truncating the path can't get the url short enough, truncate it normaly.
|
* @param hard_limit if truncating the path can't get the url short enough, truncate it normally.
|
||||||
*/
|
*/
|
||||||
QString truncateUrlHumanFriendly(QUrl &url, int max_len, bool hard_limit = false);
|
QString truncateUrlHumanFriendly(QUrl &url, int max_len, bool hard_limit = false);
|
||||||
|
|
||||||
@ -79,4 +81,9 @@ QString humanReadableFileSize(double bytes, bool use_si = false, int decimal_poi
|
|||||||
|
|
||||||
|
|
||||||
QString getRandomAlphaNumeric();
|
QString getRandomAlphaNumeric();
|
||||||
|
|
||||||
|
QPair<QString, QString> splitFirst(const QString& s, const QString& sep, Qt::CaseSensitivity cs = Qt::CaseSensitive);
|
||||||
|
QPair<QString, QString> splitFirst(const QString& s, QChar sep, Qt::CaseSensitivity cs = Qt::CaseSensitive);
|
||||||
|
QPair<QString, QString> splitFirst(const QString& s, const QRegularExpression& re);
|
||||||
|
|
||||||
} // namespace StringUtils
|
} // namespace StringUtils
|
||||||
|
206
launcher/updater/PrismExternalUpdater.cpp
Normal file
206
launcher/updater/PrismExternalUpdater.cpp
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 Rachel Powers <508861+Ryex@users.noreply.github.com>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PrismExternalUpdater.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QProgressDialog>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QSettings>
|
||||||
|
|
||||||
|
#include "StringUtils.h"
|
||||||
|
|
||||||
|
#include "BuildConfig.h"
|
||||||
|
|
||||||
|
class PrismExternalUpdater::Private {
|
||||||
|
public:
|
||||||
|
QDir appDir;
|
||||||
|
QDir dataDir;
|
||||||
|
QTimer updateTimer;
|
||||||
|
bool allowBeta;
|
||||||
|
bool autoCheck;
|
||||||
|
double updateInterval;
|
||||||
|
QDateTime lastCheck;
|
||||||
|
std::unique_ptr<QSettings> settings;
|
||||||
|
};
|
||||||
|
|
||||||
|
PrismExternalUpdater::PrismExternalUpdater(const QString& appDir, const QString& dataDir)
|
||||||
|
{
|
||||||
|
priv = new PrismExternalUpdater::Private();
|
||||||
|
priv->appDir = QDir(appDir);
|
||||||
|
priv->dataDir = QDir(dataDir);
|
||||||
|
auto settings_file = priv->dataDir.absoluteFilePath("prismlauncher_update.cfg");
|
||||||
|
priv->settings = std::make_unique<QSettings>(settings_file, QSettings::Format::IniFormat);
|
||||||
|
priv->allowBeta = priv->settings->value("allow_beta", false).toBool();
|
||||||
|
priv->autoCheck = priv->settings->value("auto_check", false).toBool();
|
||||||
|
bool interval_ok;
|
||||||
|
priv->updateInterval = priv->settings->value("update_interval", 86400).toInt(&interval_ok);
|
||||||
|
if (!interval_ok)
|
||||||
|
priv->updateInterval = 86400;
|
||||||
|
auto last_check = priv->settings->value("last_check");
|
||||||
|
if (!last_check.isNull() && last_check.isValid()) {
|
||||||
|
priv->lastCheck = QDateTime::fromString(last_check.toString(), Qt::ISODate);
|
||||||
|
}
|
||||||
|
connectTimer();
|
||||||
|
resetAutoCheckTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
PrismExternalUpdater::~PrismExternalUpdater()
|
||||||
|
{
|
||||||
|
if (priv->updateTimer.isActive())
|
||||||
|
priv->updateTimer.stop();
|
||||||
|
disconnectTimer();
|
||||||
|
priv->settings->sync();
|
||||||
|
delete priv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrismExternalUpdater::checkForUpdates()
|
||||||
|
{
|
||||||
|
QProgressDialog progress(tr("Checking for updates..."), "", 0, -1);
|
||||||
|
progress.setCancelButton(nullptr);
|
||||||
|
progress.show();
|
||||||
|
|
||||||
|
QProcess proc;
|
||||||
|
auto exe_name = QStringLiteral("%1_updater").arg(BuildConfig.LAUNCHER_APP_BINARY_NAME);
|
||||||
|
#if defined Q_OS_WIN32
|
||||||
|
exe_name.append(".exe");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QStringList args = { "--check-only" };
|
||||||
|
if (priv->allowBeta)
|
||||||
|
args.append("--pre-release");
|
||||||
|
|
||||||
|
proc.start(priv->appDir.absoluteFilePath(exe_name), args);
|
||||||
|
auto result_start = proc.waitForStarted(5000);
|
||||||
|
if (!result_start) {
|
||||||
|
auto err = proc.error();
|
||||||
|
qDebug() << "Failed to start updater after 5 seconds." << "reason:" << err << proc.errorString();
|
||||||
|
}
|
||||||
|
auto result_finished = proc.waitForFinished(60000);
|
||||||
|
if (!result_finished) {
|
||||||
|
auto err = proc.error();
|
||||||
|
qDebug() << "Updater failed to close after 60 seconds." << "reason:" << err << proc.errorString();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto exit_code = proc.exitCode();
|
||||||
|
|
||||||
|
auto std_output = proc.readAllStandardOutput();
|
||||||
|
auto std_error = proc.readAllStandardError();
|
||||||
|
|
||||||
|
switch (exit_code) {
|
||||||
|
case 0:
|
||||||
|
// no update available
|
||||||
|
{
|
||||||
|
qDebug() << "No update available";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
// there was an error
|
||||||
|
{
|
||||||
|
qDebug() << "Updater subprocess error" << std_error;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 100:
|
||||||
|
// update available
|
||||||
|
{
|
||||||
|
auto [first_line, remainder1] = StringUtils::splitFirst(std_output, '\n');
|
||||||
|
auto [second_line, remainder2] = StringUtils::splitFirst(remainder1, '\n');
|
||||||
|
auto [third_line, changelog] = StringUtils::splitFirst(remainder2, '\n');
|
||||||
|
auto version_name = StringUtils::splitFirst(first_line, ": ").second;
|
||||||
|
auto version_tag = StringUtils::splitFirst(second_line, ": ").second;
|
||||||
|
auto release_timestamp = QDateTime::fromString(StringUtils::splitFirst(third_line, ": ").second, Qt::ISODate);
|
||||||
|
qDebug() << "Update available:" << version_name << version_tag << release_timestamp;
|
||||||
|
qDebug() << "Update changelog:" << changelog;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// unknown error code
|
||||||
|
{
|
||||||
|
qDebug() << "Updater exited with unknown code" << exit_code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
priv->lastCheck = QDateTime::currentDateTime();
|
||||||
|
priv->settings->setValue("last_check", priv->lastCheck.toString(Qt::ISODate));
|
||||||
|
priv->settings->sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PrismExternalUpdater::getAutomaticallyChecksForUpdates() {
|
||||||
|
return priv->autoCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
double PrismExternalUpdater::getUpdateCheckInterval() {
|
||||||
|
return priv->updateInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PrismExternalUpdater::getBetaAllowed() {
|
||||||
|
return priv->allowBeta;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrismExternalUpdater::setAutomaticallyChecksForUpdates(bool check) {
|
||||||
|
priv->autoCheck = check;
|
||||||
|
priv->settings->setValue("auto_check", check);
|
||||||
|
priv->settings->sync();
|
||||||
|
resetAutoCheckTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrismExternalUpdater::setUpdateCheckInterval(double seconds) {
|
||||||
|
priv->updateInterval = seconds;
|
||||||
|
priv->settings->setValue("update_interval", seconds);
|
||||||
|
priv->settings->sync();
|
||||||
|
resetAutoCheckTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrismExternalUpdater::setBetaAllowed(bool allowed) {
|
||||||
|
priv->allowBeta = allowed;
|
||||||
|
priv->settings->setValue("auto_beta", allowed);
|
||||||
|
priv->settings->sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrismExternalUpdater::resetAutoCheckTimer() {
|
||||||
|
int timeoutDuration = 0;
|
||||||
|
auto now = QDateTime::currentDateTime();
|
||||||
|
if (priv->autoCheck) {
|
||||||
|
if (priv->lastCheck.isValid()) {
|
||||||
|
auto diff = priv->lastCheck.secsTo(now);
|
||||||
|
auto secs_left = priv->updateInterval - diff;
|
||||||
|
if (secs_left < 0)
|
||||||
|
secs_left = 0;
|
||||||
|
timeoutDuration = secs_left * 1000; // to msec
|
||||||
|
}
|
||||||
|
priv->updateTimer.start(timeoutDuration);
|
||||||
|
} else {
|
||||||
|
if (priv->updateTimer.isActive())
|
||||||
|
priv->updateTimer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrismExternalUpdater::connectTimer() {
|
||||||
|
connect(&priv->updateTimer, &QTimer::timeout, this, &PrismExternalUpdater::autoCheckTimerFired);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrismExternalUpdater::disconnectTimer() {
|
||||||
|
disconnect(&priv->updateTimer, &QTimer::timeout, this, &PrismExternalUpdater::autoCheckTimerFired);
|
||||||
|
}
|
94
launcher/updater/PrismExternalUpdater.h
Normal file
94
launcher/updater/PrismExternalUpdater.h
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 Rachel Powers <508861+Ryex@users.noreply.github.com>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "ExternalUpdater.h"
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* An implementation for the updater on windows and linux that uses out external updater.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class PrismExternalUpdater : public ExternalUpdater {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
PrismExternalUpdater(const QString& appDir, const QString& dataDir);
|
||||||
|
~PrismExternalUpdater() override;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Check for updates manually, showing the user a progress bar and an alert if no updates are found.
|
||||||
|
*/
|
||||||
|
void checkForUpdates() override;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Indicates whether or not to check for updates automatically.
|
||||||
|
*/
|
||||||
|
bool getAutomaticallyChecksForUpdates() override;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Indicates the current automatic update check interval in seconds.
|
||||||
|
*/
|
||||||
|
double getUpdateCheckInterval() override;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Indicates whether or not beta updates should be checked for in addition to regular releases.
|
||||||
|
*/
|
||||||
|
bool getBetaAllowed() override;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set whether or not to check for updates automatically.
|
||||||
|
*
|
||||||
|
* The update schedule cycle will be reset in a short delay after the property’s new value is set. This is to allow
|
||||||
|
* reverting this property without kicking off a schedule change immediately."
|
||||||
|
*/
|
||||||
|
void setAutomaticallyChecksForUpdates(bool check) override;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the current automatic update check interval in seconds.
|
||||||
|
*
|
||||||
|
* The update schedule cycle will be reset in a short delay after the property’s new value is set. This is to allow
|
||||||
|
* reverting this property without kicking off a schedule change immediately."
|
||||||
|
*/
|
||||||
|
void setUpdateCheckInterval(double seconds) override;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set whether or not beta updates should be checked for in addition to regular releases.
|
||||||
|
*/
|
||||||
|
void setBetaAllowed(bool allowed) override;
|
||||||
|
|
||||||
|
void resetAutoCheckTimer();
|
||||||
|
void disconnectTimer();
|
||||||
|
void connectTimer();
|
||||||
|
|
||||||
|
void performUpdate();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void autoCheckTimerFired();
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Private;
|
||||||
|
|
||||||
|
Private* priv;
|
||||||
|
};
|
@ -41,6 +41,7 @@
|
|||||||
|
|
||||||
#include <QProgressDialog>
|
#include <QProgressDialog>
|
||||||
#include <sys.h>
|
#include <sys.h>
|
||||||
|
#include <winbase.h>
|
||||||
|
|
||||||
#if defined Q_OS_WIN32
|
#if defined Q_OS_WIN32
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
@ -202,11 +203,17 @@ void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr
|
|||||||
PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, argv)
|
PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, argv)
|
||||||
{
|
{
|
||||||
#if defined Q_OS_WIN32
|
#if defined Q_OS_WIN32
|
||||||
// attach the parent console
|
// attach the parent console if stdout not already captured
|
||||||
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
|
auto stdout_type = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE));
|
||||||
|
if (stdout_type == FILE_TYPE_CHAR || stdout_type == FILE_TYPE_UNKNOWN) {
|
||||||
|
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
|
||||||
|
BindCrtHandlesToStdHandles(true, true, true);
|
||||||
|
consoleAttached = true;
|
||||||
|
}
|
||||||
|
} else if (stdout_type == FILE_TYPE_DISK || stdout_type == FILE_TYPE_PIPE ) {
|
||||||
BindCrtHandlesToStdHandles(true, true, true);
|
BindCrtHandlesToStdHandles(true, true, true);
|
||||||
consoleAttached = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
setOrganizationName(BuildConfig.LAUNCHER_NAME);
|
setOrganizationName(BuildConfig.LAUNCHER_NAME);
|
||||||
setOrganizationDomain(BuildConfig.LAUNCHER_DOMAIN);
|
setOrganizationDomain(BuildConfig.LAUNCHER_DOMAIN);
|
||||||
@ -226,6 +233,7 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar
|
|||||||
{ { "U", "update-url" }, tr("Update from the specified repo."), tr("github repo url") },
|
{ { "U", "update-url" }, tr("Update from the specified repo."), tr("github repo url") },
|
||||||
{ { "c", "check-only" },
|
{ { "c", "check-only" },
|
||||||
tr("Only check if an update is needed. Exit status 100 if true, 0 if false (or non 0 if there was an error).") },
|
tr("Only check if an update is needed. Exit status 100 if true, 0 if false (or non 0 if there was an error).") },
|
||||||
|
{ { "p", "pre-release" }, tr("Allow updating to pre-release releases") },
|
||||||
{ { "F", "force" }, tr("Force an update, even if one is not needed.") },
|
{ { "F", "force" }, tr("Force an update, even if one is not needed.") },
|
||||||
{ { "l", "list" }, tr("List available releases.") },
|
{ { "l", "list" }, tr("List available releases.") },
|
||||||
{ "debug", tr("Log debug to console.") },
|
{ "debug", tr("Log debug to console.") },
|
||||||
@ -297,6 +305,8 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar
|
|||||||
m_prismVersionMinor = version_parts.takeFirst().toInt();
|
m_prismVersionMinor = version_parts.takeFirst().toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_allowPreRelease = parser.isSet("pre-release");
|
||||||
|
|
||||||
QString origCwdPath = QDir::currentPath();
|
QString origCwdPath = QDir::currentPath();
|
||||||
QString binPath = applicationDirPath();
|
QString binPath = applicationDirPath();
|
||||||
|
|
||||||
@ -542,10 +552,19 @@ void PrismUpdaterApp::run()
|
|||||||
auto need_update = needUpdate(latest);
|
auto need_update = needUpdate(latest);
|
||||||
|
|
||||||
if (m_checkOnly) {
|
if (m_checkOnly) {
|
||||||
if (need_update)
|
if (need_update) {
|
||||||
|
QTextStream stdOutStream(stdout);
|
||||||
|
stdOutStream << "Name: " << latest.name << "\n";
|
||||||
|
stdOutStream << "Version: " << latest.tag_name << "\n";
|
||||||
|
stdOutStream << "TimeStamp: " << latest.created_at.toString(Qt::ISODate) << "\n";
|
||||||
|
stdOutStream << latest.body << "\n";
|
||||||
|
stdOutStream.flush();
|
||||||
|
|
||||||
return exit(100);
|
return exit(100);
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
return exit(0);
|
return exit(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_isFlatpak) {
|
if (m_isFlatpak) {
|
||||||
@ -958,10 +977,11 @@ void PrismUpdaterApp::unpackAndInstall(QFileInfo archive)
|
|||||||
if (auto loc = unpackArchive(archive)) {
|
if (auto loc = unpackArchive(archive)) {
|
||||||
auto marker_file_path = loc.value().absoluteFilePath(".prism_launcher_updater_unpack.marker");
|
auto marker_file_path = loc.value().absoluteFilePath(".prism_launcher_updater_unpack.marker");
|
||||||
FS::write(marker_file_path, applicationDirPath().toUtf8());
|
FS::write(marker_file_path, applicationDirPath().toUtf8());
|
||||||
auto new_updater_path = loc.value().absoluteFilePath("prismlauncher_updater");
|
auto exe_name = QStringLiteral("%1_updater").arg(BuildConfig.LAUNCHER_APP_BINARY_NAME);
|
||||||
#if defined Q_OS_WIN32
|
#if defined Q_OS_WIN32
|
||||||
new_updater_path.append(".exe");
|
exe_name.append(".exe");
|
||||||
#endif
|
#endif
|
||||||
|
auto new_updater_path = loc.value().absoluteFilePath(exe_name);
|
||||||
logUpdate(tr("Starting new updater at '%1'").arg(new_updater_path));
|
logUpdate(tr("Starting new updater at '%1'").arg(new_updater_path));
|
||||||
QProcess proc = QProcess();
|
QProcess proc = QProcess();
|
||||||
if (!proc.startDetached(new_updater_path, { "-d", m_dataPath }, loc.value().absolutePath())) {
|
if (!proc.startDetached(new_updater_path, { "-d", m_dataPath }, loc.value().absolutePath())) {
|
||||||
@ -1110,7 +1130,7 @@ bool PrismUpdaterApp::loadPrismVersionFromExe(const QString& exe_path)
|
|||||||
QProcess proc = QProcess();
|
QProcess proc = QProcess();
|
||||||
proc.setProcessChannelMode(QProcess::MergedChannels);
|
proc.setProcessChannelMode(QProcess::MergedChannels);
|
||||||
proc.setReadChannel(QProcess::StandardOutput);
|
proc.setReadChannel(QProcess::StandardOutput);
|
||||||
proc.start(exe_path, { "-v" });
|
proc.start(exe_path, { "--version" });
|
||||||
if (!proc.waitForStarted(5000)) {
|
if (!proc.waitForStarted(5000)) {
|
||||||
showFatalErrorMessage(tr("Failed to Check Version"), tr("Failed to launcher child launcher process to read version."));
|
showFatalErrorMessage(tr("Failed to Check Version"), tr("Failed to launcher child launcher process to read version."));
|
||||||
return false;
|
return false;
|
||||||
@ -1119,7 +1139,7 @@ bool PrismUpdaterApp::loadPrismVersionFromExe(const QString& exe_path)
|
|||||||
showFatalErrorMessage(tr("Failed to Check Version"), tr("Child launcher process failed."));
|
showFatalErrorMessage(tr("Failed to Check Version"), tr("Child launcher process failed."));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto out = proc.readAll();
|
auto out = proc.readAllStandardOutput();
|
||||||
auto lines = out.split('\n');
|
auto lines = out.split('\n');
|
||||||
if (lines.length() < 2)
|
if (lines.length() < 2)
|
||||||
return false;
|
return false;
|
||||||
@ -1250,7 +1270,11 @@ GitHubRelease PrismUpdaterApp::getLatestRelease()
|
|||||||
{
|
{
|
||||||
GitHubRelease latest;
|
GitHubRelease latest;
|
||||||
for (auto release : m_releases) {
|
for (auto release : m_releases) {
|
||||||
if (!latest.isValid() || (!release.draft && release.version > latest.version)) {
|
if (release.draft)
|
||||||
|
continue;
|
||||||
|
if (release.prerelease && !m_allowPreRelease)
|
||||||
|
continue;
|
||||||
|
if (!latest.isValid() || (release.version > latest.version)) {
|
||||||
latest = release;
|
latest = release;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,6 +113,7 @@ class PrismUpdaterApp : public QApplication {
|
|||||||
bool m_printOnly;
|
bool m_printOnly;
|
||||||
bool m_selectUI;
|
bool m_selectUI;
|
||||||
bool m_allowDowngrade;
|
bool m_allowDowngrade;
|
||||||
|
bool m_allowPreRelease;
|
||||||
|
|
||||||
QString m_updateLogPath;
|
QString m_updateLogPath;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user