feat(updater): final step for portable install
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
parent
d2a3acd493
commit
4313466589
@ -148,8 +148,8 @@ set(Launcher_VERSION_NAME4_COMMA "${Launcher_VERSION_MAJOR},${Launcher_VERSION_M
|
|||||||
# Build platform.
|
# Build platform.
|
||||||
set(Launcher_BUILD_PLATFORM "" CACHE STRING "A short string identifying the platform that this build was built for. Only used to display in the about dialog.")
|
set(Launcher_BUILD_PLATFORM "" CACHE STRING "A short string identifying the platform that this build was built for. Only used to display in the about dialog.")
|
||||||
|
|
||||||
# Channel list URL
|
# Github repo URL with releases for updater
|
||||||
set(Launcher_UPDATER_BASE "" CACHE STRING "Base URL for the updater.")
|
set(Launcher_UPDATER_GITHUB_REPO "" CACHE STRING "Base URL for the updater.")
|
||||||
|
|
||||||
# The metadata server
|
# The metadata server
|
||||||
set(Launcher_META_URL "https://meta.prismlauncher.org/v1/" CACHE STRING "URL to fetch Launcher's meta files from.")
|
set(Launcher_META_URL "https://meta.prismlauncher.org/v1/" CACHE STRING "URL to fetch Launcher's meta files from.")
|
||||||
|
@ -108,10 +108,11 @@ ModDetails ReadMCModTOML(QByteArray contents)
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
tomlData = toml::parse(contents.toStdString());
|
toml::parse_result result = toml::parse(contents.toStdString());
|
||||||
if (!tomlData) {
|
if (!result) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
tomlData = result.table();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// array defined by [[mods]]
|
// array defined by [[mods]]
|
||||||
|
@ -241,12 +241,13 @@ auto V1::getIndexForMod(QDir& index_dir, QString slug) -> Mod
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
table = toml::parse_file(StringUtils::toStdString(index_dir.absoluteFilePath(real_fname)));
|
toml::parse_result result = toml::parse_file(StringUtils::toStdString(index_dir.absoluteFilePath(real_fname)));
|
||||||
if (!table) {
|
if (!result) {
|
||||||
qWarning() << QString("Could not open file %1!").arg(normalized_fname);
|
qWarning() << QString("Could not open file %1!").arg(normalized_fname);
|
||||||
qWarning() << "Reason: " << QString(table.error().what());
|
qWarning() << "Reason: " << result.error().description();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
table = result.table();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// index_file.close();
|
// index_file.close();
|
||||||
|
@ -68,6 +68,8 @@ ProgressDialog::ProgressDialog(QWidget* parent) : QDialog(parent), ui(new Ui::Pr
|
|||||||
setAttribute(Qt::WidgetAttribute::WA_QuitOnClose, true);
|
setAttribute(Qt::WidgetAttribute::WA_QuitOnClose, true);
|
||||||
setSkipButton(false);
|
setSkipButton(false);
|
||||||
changeProgress(0, 100);
|
changeProgress(0, 100);
|
||||||
|
updateSize();
|
||||||
|
adjustSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProgressDialog::setSkipButton(bool present, QString label)
|
void ProgressDialog::setSkipButton(bool present, QString label)
|
||||||
@ -96,7 +98,11 @@ ProgressDialog::~ProgressDialog()
|
|||||||
void ProgressDialog::updateSize()
|
void ProgressDialog::updateSize()
|
||||||
{
|
{
|
||||||
QSize lastSize = this->size();
|
QSize lastSize = this->size();
|
||||||
QSize qSize = QSize(480, minimumSizeHint().height());
|
auto min_height = minimumSizeHint().height();
|
||||||
|
if (ui->taskProgressScrollArea->isHidden())
|
||||||
|
min_height -= ui->taskProgressScrollArea->minimumSizeHint().height();
|
||||||
|
min_height = std::max(min_height, 0);
|
||||||
|
QSize qSize = QSize(480, min_height);
|
||||||
|
|
||||||
// if the current window is too small
|
// if the current window is too small
|
||||||
if ((lastSize != qSize) && (lastSize.height() < qSize.height()))
|
if ((lastSize != qSize) && (lastSize.height() < qSize.height()))
|
||||||
@ -111,7 +117,6 @@ void ProgressDialog::updateSize()
|
|||||||
}
|
}
|
||||||
|
|
||||||
setMinimumSize(qSize);
|
setMinimumSize(qSize);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ProgressDialog::execWithTask(Task* task)
|
int ProgressDialog::execWithTask(Task* task)
|
||||||
|
@ -48,6 +48,9 @@
|
|||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Global Task Status...</string>
|
<string>Global Task Status...</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@ -109,8 +112,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>464</width>
|
<width>460</width>
|
||||||
<height>96</height>
|
<height>108</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="taskProgressLayout">
|
<layout class="QVBoxLayout" name="taskProgressLayout">
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include <qglobal.h>
|
#include <QProgressDialog>
|
||||||
#include <sys.h>
|
#include <sys.h>
|
||||||
|
|
||||||
#if defined Q_OS_WIN32
|
#if defined Q_OS_WIN32
|
||||||
@ -106,7 +106,7 @@ void appDebugOutput(QtMsgType type, const QMessageLogContext& context, const QSt
|
|||||||
#if defined Q_OS_WIN32
|
#if defined Q_OS_WIN32
|
||||||
|
|
||||||
// taken from https://stackoverflow.com/a/25927081
|
// taken from https://stackoverflow.com/a/25927081
|
||||||
// getting a proper output to console with redirection support on windows is apearently hell
|
// getting a proper output to console with redirection support on windows is apparently hell
|
||||||
void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr)
|
void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr)
|
||||||
{
|
{
|
||||||
// Re-initialize the C runtime "FILE" handles with clean handles bound to "nul". We do this because it has been
|
// Re-initialize the C runtime "FILE" handles with clean handles bound to "nul". We do this because it has been
|
||||||
@ -266,8 +266,11 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar
|
|||||||
m_prismExecutable = prism_executable;
|
m_prismExecutable = prism_executable;
|
||||||
|
|
||||||
auto prism_update_url = parser.value("update-url");
|
auto prism_update_url = parser.value("update-url");
|
||||||
|
if (prism_update_url.isEmpty())
|
||||||
|
prism_update_url = BuildConfig.UPDATER_GITHUB_REPO;
|
||||||
if (prism_update_url.isEmpty())
|
if (prism_update_url.isEmpty())
|
||||||
prism_update_url = "https://github.com/PrismLauncher/PrismLauncher";
|
prism_update_url = "https://github.com/PrismLauncher/PrismLauncher";
|
||||||
|
|
||||||
m_prismRepoUrl = QUrl::fromUserInput(prism_update_url);
|
m_prismRepoUrl = QUrl::fromUserInput(prism_update_url);
|
||||||
|
|
||||||
m_checkOnly = parser.isSet("check-only");
|
m_checkOnly = parser.isSet("check-only");
|
||||||
@ -334,6 +337,8 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_updateLogPath = FS::PathCombine(m_dataPath, "prism_launcher_update.log");
|
||||||
|
|
||||||
{ // setup logging
|
{ // setup logging
|
||||||
static const QString logBase = BuildConfig.LAUNCHER_NAME + "Updater" + (m_checkOnly ? "-CheckOnly" : "") + "-%0.log";
|
static const QString logBase = BuildConfig.LAUNCHER_NAME + "Updater" + (m_checkOnly ? "-CheckOnly" : "") + "-%0.log";
|
||||||
auto moveFile = [](const QString& oldName, const QString& newName) {
|
auto moveFile = [](const QString& oldName, const QString& newName) {
|
||||||
@ -424,14 +429,16 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar
|
|||||||
qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT;
|
qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT;
|
||||||
qDebug() << "Git refspec : " << BuildConfig.GIT_REFSPEC;
|
qDebug() << "Git refspec : " << BuildConfig.GIT_REFSPEC;
|
||||||
if (adjustedBy.size()) {
|
if (adjustedBy.size()) {
|
||||||
qDebug() << "Work dir before adjustment : " << origCwdPath;
|
qDebug() << "Data dir before adjustment : " << origCwdPath;
|
||||||
qDebug() << "Work dir after adjustment : " << QDir::currentPath();
|
qDebug() << "Data dir after adjustment : " << m_dataPath;
|
||||||
qDebug() << "Adjusted by : " << adjustedBy;
|
qDebug() << "Adjusted by : " << adjustedBy;
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "Work dir : " << QDir::currentPath();
|
qDebug() << "Data dir : " << QDir::currentPath();
|
||||||
}
|
}
|
||||||
|
qDebug() << "Work dir : " << QDir::currentPath();
|
||||||
qDebug() << "Binary path : " << binPath;
|
qDebug() << "Binary path : " << binPath;
|
||||||
qDebug() << "Application root path : " << m_rootPath;
|
qDebug() << "Application root path : " << m_rootPath;
|
||||||
|
qDebug() << "Portable install : " << m_isPortable;
|
||||||
qDebug() << "<> Paths set.";
|
qDebug() << "<> Paths set.";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,14 +449,28 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar
|
|||||||
m_network->setProxy(proxy);
|
m_network->setProxy(proxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto marker_file_path = QDir(applicationDirPath()).absoluteFilePath(".prism_launcher_updater_unpack.marker");
|
||||||
|
auto marker_file = QFileInfo(marker_file_path);
|
||||||
|
if (marker_file.exists()) {
|
||||||
|
auto target_dir = QString(FS::read(marker_file_path)).trimmed();
|
||||||
|
if (target_dir.isEmpty()) {
|
||||||
|
qWarning() << "Empty updater marker file contains no install target. making best guess of parent dir";
|
||||||
|
target_dir = QDir(applicationDirPath()).absoluteFilePath("..");
|
||||||
|
}
|
||||||
|
|
||||||
|
QMetaObject::invokeMethod(
|
||||||
|
this, [this, target_dir]() { moveAndFinishUpdate(target_dir); }, Qt::QueuedConnection);
|
||||||
|
|
||||||
|
} else {
|
||||||
QMetaObject::invokeMethod(this, &PrismUpdaterApp::loadReleaseList, Qt::QueuedConnection);
|
QMetaObject::invokeMethod(this, &PrismUpdaterApp::loadReleaseList, Qt::QueuedConnection);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PrismUpdaterApp::~PrismUpdaterApp()
|
PrismUpdaterApp::~PrismUpdaterApp()
|
||||||
{
|
{
|
||||||
|
qDebug() << "updater shutting down";
|
||||||
// Shut down logger by setting the logger function to nothing
|
// Shut down logger by setting the logger function to nothing
|
||||||
qInstallMessageHandler(nullptr);
|
qInstallMessageHandler(nullptr);
|
||||||
qDebug() << "updater shutting down";
|
|
||||||
|
|
||||||
#if defined Q_OS_WIN32
|
#if defined Q_OS_WIN32
|
||||||
// Detach from Windows console
|
// Detach from Windows console
|
||||||
@ -576,6 +597,81 @@ void PrismUpdaterApp::run()
|
|||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PrismUpdaterApp::moveAndFinishUpdate(QDir target)
|
||||||
|
{
|
||||||
|
logUpdate("Finishing update process");
|
||||||
|
auto manifest_path = FS::PathCombine(applicationDirPath(), "manifest.txt");
|
||||||
|
QFileInfo manifest(manifest_path);
|
||||||
|
|
||||||
|
auto app_dir = QDir(applicationDirPath());
|
||||||
|
|
||||||
|
QStringList file_list;
|
||||||
|
if (manifest.isFile()) {
|
||||||
|
// load manifest from file
|
||||||
|
logUpdate(tr("Reading manifest from %1").arg(manifest.absoluteFilePath()));
|
||||||
|
try {
|
||||||
|
auto contents = QString::fromUtf8(FS::read(manifest.absoluteFilePath()));
|
||||||
|
auto files = contents.split('\n');
|
||||||
|
for (auto file : files) {
|
||||||
|
file_list.append(file.trimmed());
|
||||||
|
}
|
||||||
|
} catch (FS::FileSystemException) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_list.isEmpty()) {
|
||||||
|
logUpdate(tr("Manifest empty, making best guess of the directory contents of %1").arg(applicationDirPath()));
|
||||||
|
auto entries = target.entryInfoList(QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs);
|
||||||
|
for (auto entry : entries) {
|
||||||
|
file_list.append(entry.fileName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logUpdate(tr("Installing the following to %1 :\n %2").arg(target.absolutePath()).arg(file_list.join(",\n ")));
|
||||||
|
|
||||||
|
bool error = false;
|
||||||
|
|
||||||
|
QProgressDialog progress(tr("Backing up install at %1").arg(applicationDirPath()), "", 0, file_list.length());
|
||||||
|
progress.setCancelButton(nullptr);
|
||||||
|
progress.show();
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (auto glob : file_list) {
|
||||||
|
QDirIterator iter(applicationDirPath(), QStringList({ glob }), QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
|
||||||
|
progress.setValue(i);
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
auto to_install_file = iter.next();
|
||||||
|
auto rel_path = app_dir.relativeFilePath(to_install_file);
|
||||||
|
auto install_path = FS::PathCombine(target.absolutePath(), rel_path);
|
||||||
|
logUpdate(tr("Installing %1 from %2").arg(install_path).arg(to_install_file));
|
||||||
|
FS::ensureFilePathExists(install_path);
|
||||||
|
auto result = FS::copy(to_install_file, install_path)();
|
||||||
|
if (!result) {
|
||||||
|
error = true;
|
||||||
|
logUpdate(tr("Failed copy %1 to %2").arg(to_install_file).arg(install_path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
progress.setValue(i);
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
logUpdate(tr("There were errors installing the update."));
|
||||||
|
auto fail_marker = FS::PathCombine(m_dataPath, ".prism_launcher_update.fail");
|
||||||
|
FS::move(m_updateLogPath, fail_marker);
|
||||||
|
} else {
|
||||||
|
logUpdate(tr("Update succeed."));
|
||||||
|
auto success_marker = FS::PathCombine(m_dataPath, ".prism_launcher_update.success");
|
||||||
|
FS::move(m_updateLogPath, success_marker);
|
||||||
|
}
|
||||||
|
auto update_lock_path = FS::PathCombine(m_dataPath, ".prism_launcher_update.lock");
|
||||||
|
FS::deletePath(update_lock_path);
|
||||||
|
|
||||||
|
exit(error ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
void PrismUpdaterApp::printReleases()
|
void PrismUpdaterApp::printReleases()
|
||||||
{
|
{
|
||||||
for (auto release : m_releases) {
|
for (auto release : m_releases) {
|
||||||
@ -739,24 +835,107 @@ bool PrismUpdaterApp::callAppImageUpdate()
|
|||||||
|
|
||||||
void PrismUpdaterApp::clearUpdateLog()
|
void PrismUpdaterApp::clearUpdateLog()
|
||||||
{
|
{
|
||||||
auto update_log_path = FS::PathCombine(m_dataPath, "prism_launcher_update.log");
|
QFile::remove(m_updateLogPath);
|
||||||
QFile::remove(update_log_path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrismUpdaterApp::logUpdate(const QString& msg)
|
void PrismUpdaterApp::logUpdate(const QString& msg)
|
||||||
{
|
{
|
||||||
qDebug() << qUtf8Printable(msg);
|
qDebug() << qUtf8Printable(msg);
|
||||||
auto update_log_path = FS::PathCombine(m_dataPath, "prism_launcher_update.log");
|
FS::append(m_updateLogPath, QStringLiteral("%1\n").arg(msg).toUtf8());
|
||||||
FS::append(update_log_path, QStringLiteral("%1\n").arg(msg).toUtf8());
|
}
|
||||||
|
|
||||||
|
std::tuple<QDateTime, QString, QString, QString, QString> read_lock_File(const QString& path)
|
||||||
|
{
|
||||||
|
auto contents = QString(FS::read(path));
|
||||||
|
auto lines = contents.split('\n');
|
||||||
|
|
||||||
|
QDateTime timestamp;
|
||||||
|
QString from, to, target, data_path;
|
||||||
|
for (auto line : lines) {
|
||||||
|
auto index = line.indexOf("=");
|
||||||
|
if (index < 0)
|
||||||
|
continue;
|
||||||
|
auto left = line.left(index);
|
||||||
|
auto right = line.mid(index + 1);
|
||||||
|
if (left.toLower() == "timestamp") {
|
||||||
|
timestamp = QDateTime::fromString(right, Qt::ISODate);
|
||||||
|
} else if (left.toLower() == "from") {
|
||||||
|
from = right;
|
||||||
|
} else if (left.toLower() == "to") {
|
||||||
|
to = right;
|
||||||
|
} else if (left.toLower() == "target") {
|
||||||
|
target = right;
|
||||||
|
} else if (left.toLower() == "data_path") {
|
||||||
|
data_path = right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return std::make_tuple(timestamp, from, to, target, data_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool write_lock_file(const QString& path, QDateTime timestamp, QString from, QString to, QString target, QString data_path)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
FS::write(path, QStringLiteral("TIMESTAMP=%1\nFROM=%2\nTO=%3\nTARGET=%4\nDATA_PATH=%5\n")
|
||||||
|
.arg(timestamp.toString(Qt::ISODate))
|
||||||
|
.arg(from)
|
||||||
|
.arg(to)
|
||||||
|
.arg(target)
|
||||||
|
.arg(data_path)
|
||||||
|
.toUtf8());
|
||||||
|
} catch (FS::FileSystemException err) {
|
||||||
|
qWarning() << "Error writing lockfile:" << err.what() << "\n" << err.cause();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrismUpdaterApp::performInstall(QFileInfo file)
|
void PrismUpdaterApp::performInstall(QFileInfo file)
|
||||||
{
|
{
|
||||||
qDebug() << "starting install";
|
qDebug() << "starting install";
|
||||||
auto update_lock_path = FS::PathCombine(m_dataPath, ".prism_launcher_update.lock");
|
auto update_lock_path = FS::PathCombine(m_dataPath, ".prism_launcher_update.lock");
|
||||||
FS::write(update_lock_path, QStringLiteral("FROM=%1\nTO=%2\n").arg(m_prismVersion).arg(m_install_release.tag_name).toUtf8());
|
QFileInfo update_lock(update_lock_path);
|
||||||
|
if (update_lock.exists()) {
|
||||||
|
auto [timestamp, from, to, target, data_path] = read_lock_File(update_lock_path);
|
||||||
|
auto msg = tr("Update already in progress\n");
|
||||||
|
auto infoMsg =
|
||||||
|
tr("This installation has a update lock file present at: %1\n"
|
||||||
|
"\n"
|
||||||
|
"Timestamp: %2\n"
|
||||||
|
"Updating from version %3 to %4\n"
|
||||||
|
"Target install path: %5\n"
|
||||||
|
"Data Path: %6"
|
||||||
|
"\n"
|
||||||
|
"This likely means that a previous update attempt failed. Please ensure your installation is in working order before "
|
||||||
|
"proceeding.\n"
|
||||||
|
"Check the Prism Launcher updater log at \n"
|
||||||
|
"%7\n"
|
||||||
|
"for details on the last update attempt.\n"
|
||||||
|
"\n"
|
||||||
|
"To overwrite this lock and proceed with this update anyway, select \"Ignore\" below.")
|
||||||
|
.arg(update_lock_path)
|
||||||
|
.arg(timestamp.toString(Qt::ISODate), from, to, target, data_path)
|
||||||
|
.arg(m_updateLogPath);
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setText(msg);
|
||||||
|
msgBox.setInformativeText(infoMsg);
|
||||||
|
msgBox.setStandardButtons(QMessageBox::Ignore | QMessageBox::Cancel);
|
||||||
|
msgBox.setDefaultButton(QMessageBox::Cancel);
|
||||||
|
switch (msgBox.exec()) {
|
||||||
|
case QMessageBox::Ignore:
|
||||||
|
break;
|
||||||
|
case QMessageBox::Cancel:
|
||||||
|
[[fallthrough]];
|
||||||
|
default:
|
||||||
|
return showFatalErrorMessage(tr("Update Aborted"), tr("The update attempt was aborted"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
write_lock_file(update_lock_path, QDateTime::currentDateTime(), m_prismVersion, m_install_release.tag_name, applicationDirPath(),
|
||||||
|
m_dataPath);
|
||||||
clearUpdateLog();
|
clearUpdateLog();
|
||||||
|
|
||||||
|
auto changelog_path = FS::PathCombine(m_dataPath, ".prism_launcher_update.changelog");
|
||||||
|
FS::write(changelog_path, m_install_release.body.toUtf8());
|
||||||
|
|
||||||
logUpdate(tr("Updating from %1 to %2").arg(m_prismVersion).arg(m_install_release.tag_name));
|
logUpdate(tr("Updating from %1 to %2").arg(m_prismVersion).arg(m_install_release.tag_name));
|
||||||
if (m_isPortable || file.suffix().toLower() == "zip") {
|
if (m_isPortable || file.suffix().toLower() == "zip") {
|
||||||
logUpdate(tr("Updating portable install at %1").arg(applicationDirPath()));
|
logUpdate(tr("Updating portable install at %1").arg(applicationDirPath()));
|
||||||
@ -779,14 +958,13 @@ 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 new_updater_path = loc.value().absoluteFilePath("prismlauncher_updater");
|
||||||
#if defined Q_OS_WIN32
|
#if defined Q_OS_WIN32
|
||||||
new_updater_path.append(".exe");
|
new_updater_path.append(".exe");
|
||||||
#endif
|
#endif
|
||||||
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();
|
||||||
proc.startDetached(new_updater_path, {}, loc.value().absolutePath());
|
if (!proc.startDetached(new_updater_path, { "-d", m_dataPath }, loc.value().absolutePath())) {
|
||||||
if (!proc.waitForStarted(5000)) {
|
|
||||||
logUpdate(tr("Failed to launch '%1' %2").arg(new_updater_path).arg(proc.errorString()));
|
logUpdate(tr("Failed to launch '%1' %2").arg(new_updater_path).arg(proc.errorString()));
|
||||||
return exit(10);
|
return exit(10);
|
||||||
}
|
}
|
||||||
@ -807,7 +985,10 @@ void PrismUpdaterApp::backupAppDir()
|
|||||||
logUpdate(tr("Reading manifest from %1").arg(manifest.absoluteFilePath()));
|
logUpdate(tr("Reading manifest from %1").arg(manifest.absoluteFilePath()));
|
||||||
try {
|
try {
|
||||||
auto contents = QString::fromUtf8(FS::read(manifest.absoluteFilePath()));
|
auto contents = QString::fromUtf8(FS::read(manifest.absoluteFilePath()));
|
||||||
file_list.append(contents.split('\n'));
|
auto files = contents.split('\n');
|
||||||
|
for (auto file : files) {
|
||||||
|
file_list.append(file.trimmed());
|
||||||
|
}
|
||||||
} catch (FS::FileSystemException) {
|
} catch (FS::FileSystemException) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -815,19 +996,19 @@ void PrismUpdaterApp::backupAppDir()
|
|||||||
if (file_list.isEmpty()) {
|
if (file_list.isEmpty()) {
|
||||||
// best guess
|
// best guess
|
||||||
if (BuildConfig.BUILD_PLATFORM.toLower() == "linux") {
|
if (BuildConfig.BUILD_PLATFORM.toLower() == "linux") {
|
||||||
file_list.append({ "PrismLauncher", "bin/*", "share/*", "lib/*" });
|
file_list.append({ "PrismLauncher", "bin", "share", "lib" });
|
||||||
} else { // windows by process of elimination
|
} else { // windows by process of elimination
|
||||||
file_list.append({
|
file_list.append({
|
||||||
"jars/*",
|
"jars",
|
||||||
"prismlauncher.exe",
|
"prismlauncher.exe",
|
||||||
"prismlauncher_filelink.exe",
|
"prismlauncher_filelink.exe",
|
||||||
|
"prismlauncher_updater.exe",
|
||||||
"qtlogging.ini",
|
"qtlogging.ini",
|
||||||
"imageformats/*",
|
"imageformats",
|
||||||
"iconengines/*",
|
"iconengines",
|
||||||
"platforms/*",
|
"platforms",
|
||||||
"styles/*",
|
"styles",
|
||||||
"styles/*",
|
"tls",
|
||||||
"tls/*",
|
|
||||||
"qt.conf",
|
"qt.conf",
|
||||||
"Qt*.dll",
|
"Qt*.dll",
|
||||||
});
|
});
|
||||||
@ -839,20 +1020,27 @@ void PrismUpdaterApp::backupAppDir()
|
|||||||
|
|
||||||
QDir app_dir = QCoreApplication::applicationDirPath();
|
QDir app_dir = QCoreApplication::applicationDirPath();
|
||||||
auto backup_dir = FS::PathCombine(
|
auto backup_dir = FS::PathCombine(
|
||||||
app_dir.absolutePath(), QStringLiteral("backup_") +
|
app_dir.absolutePath(),
|
||||||
QString(m_prismVersion).replace(QRegularExpression("[" + QRegularExpression::escape("\\/:*?\"<>|") + "]"), QString("_")) +
|
QStringLiteral("backup_") +
|
||||||
"-" + m_prismGitCommit);
|
QString(m_prismVersion).replace(QRegularExpression("[" + QRegularExpression::escape("\\/:*?\"<>|") + "]"), QString("_")) + "-" +
|
||||||
|
m_prismGitCommit);
|
||||||
FS::ensureFolderPathExists(backup_dir);
|
FS::ensureFolderPathExists(backup_dir);
|
||||||
|
auto backup_marker_path = FS::PathCombine(m_dataPath, ".prism_launcher_update_backup_path.txt");
|
||||||
|
FS::write(backup_marker_path, backup_dir.toUtf8());
|
||||||
|
|
||||||
|
QProgressDialog progress(tr("Backing up install at %1").arg(applicationDirPath()), "", 0, file_list.length());
|
||||||
|
progress.setCancelButton(nullptr);
|
||||||
|
progress.show();
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
int i = 0;
|
||||||
for (auto glob : file_list) {
|
for (auto glob : file_list) {
|
||||||
QDirIterator iter(app_dir.absolutePath(), QStringList({ glob }), QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot,
|
QDirIterator iter(app_dir.absolutePath(), QStringList({ glob }), QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
|
||||||
QDirIterator::Subdirectories);
|
progress.setValue(i);
|
||||||
|
QCoreApplication::processEvents();
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
auto to_bak_file = iter.next();
|
auto to_bak_file = iter.next();
|
||||||
auto rel_path = app_dir.relativeFilePath(to_bak_file);
|
auto rel_path = app_dir.relativeFilePath(to_bak_file);
|
||||||
auto bak_path = FS::PathCombine(backup_dir, rel_path);
|
auto bak_path = FS::PathCombine(backup_dir, rel_path);
|
||||||
|
|
||||||
if (QFileInfo(to_bak_file).isFile()) {
|
|
||||||
logUpdate(tr("Backing up and then removing %1").arg(to_bak_file));
|
logUpdate(tr("Backing up and then removing %1").arg(to_bak_file));
|
||||||
FS::ensureFilePathExists(bak_path);
|
FS::ensureFilePathExists(bak_path);
|
||||||
auto result = FS::copy(to_bak_file, bak_path)();
|
auto result = FS::copy(to_bak_file, bak_path)();
|
||||||
@ -863,8 +1051,10 @@ void PrismUpdaterApp::backupAppDir()
|
|||||||
logUpdate(tr("Failed to remove %1").arg(to_bak_file));
|
logUpdate(tr("Failed to remove %1").arg(to_bak_file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
}
|
progress.setValue(i);
|
||||||
|
QCoreApplication::processEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<QDir> PrismUpdaterApp::unpackArchive(QFileInfo archive)
|
std::optional<QDir> PrismUpdaterApp::unpackArchive(QFileInfo archive)
|
||||||
|
@ -85,7 +85,7 @@ class PrismUpdaterApp : public QApplication {
|
|||||||
QFileInfo downloadAsset(const GitHubReleaseAsset& asset);
|
QFileInfo downloadAsset(const GitHubReleaseAsset& asset);
|
||||||
bool callAppImageUpdate();
|
bool callAppImageUpdate();
|
||||||
|
|
||||||
void moveAndPostProcess(QDir target);
|
void moveAndFinishUpdate(QDir target);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void downloadError(QString reason);
|
void downloadError(QString reason);
|
||||||
@ -98,7 +98,6 @@ class PrismUpdaterApp : public QApplication {
|
|||||||
void clearUpdateLog();
|
void clearUpdateLog();
|
||||||
void logUpdate(const QString& msg);
|
void logUpdate(const QString& msg);
|
||||||
|
|
||||||
|
|
||||||
QString m_rootPath;
|
QString m_rootPath;
|
||||||
QString m_dataPath;
|
QString m_dataPath;
|
||||||
bool m_isPortable = false;
|
bool m_isPortable = false;
|
||||||
@ -114,6 +113,8 @@ class PrismUpdaterApp : public QApplication {
|
|||||||
bool m_selectUI;
|
bool m_selectUI;
|
||||||
bool m_allowDowngrade;
|
bool m_allowDowngrade;
|
||||||
|
|
||||||
|
QString m_updateLogPath;
|
||||||
|
|
||||||
QString m_prismBinaryName;
|
QString m_prismBinaryName;
|
||||||
QString m_prismVersion;
|
QString m_prismVersion;
|
||||||
int m_prismVersionMajor = -1;
|
int m_prismVersionMajor = -1;
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>478</width>
|
<width>468</width>
|
||||||
<height>517</height>
|
<height>385</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
Loading…
Reference in New Issue
Block a user