aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSulfurNitride <SulfurNitride@users.noreply.github.com>2026-05-31 13:20:21 -0500
committerSulfurNitride <SulfurNitride@users.noreply.github.com>2026-05-31 13:27:20 -0500
commit51419a3aa4f037869e2c9dd52377277bc4695010 (patch)
tree21798001a460f24638911a5ccf98bfff53e2b50e /src
parent5c4603f12a727625ece236fc43846330fad3b9f2 (diff)
fix updater restart and log cleanup
Diffstat (limited to 'src')
-rw-r--r--src/src/mainwindow.cpp2
-rw-r--r--src/src/organizercore.cpp91
-rw-r--r--src/src/organizercore.h12
-rw-r--r--src/src/settingsdialogupdates.cpp41
4 files changed, 130 insertions, 16 deletions
diff --git a/src/src/mainwindow.cpp b/src/src/mainwindow.cpp
index f8f7e97..ca92499 100644
--- a/src/src/mainwindow.cpp
+++ b/src/src/mainwindow.cpp
@@ -1457,6 +1457,8 @@ void MainWindow::paintEvent(QPaintEvent* event)
void MainWindow::onBeforeClose()
{
storeSettings();
+ m_ArchiveListWriter.writeImmediately(true);
+ m_OrganizerCore.pluginsWriter().writeImmediately(true);
}
void MainWindow::closeEvent(QCloseEvent* event)
diff --git a/src/src/organizercore.cpp b/src/src/organizercore.cpp
index d8e6da4..3721cf4 100644
--- a/src/src/organizercore.cpp
+++ b/src/src/organizercore.cpp
@@ -52,9 +52,12 @@
#include <thread>
#include <QApplication>
#include <QCoreApplication>
+#include <QDateTime>
#include <QDialog>
#include <QDialogButtonBox>
+#include <QDirIterator>
#include <QFile>
+#include <QFileInfo>
#include <QMessageBox>
#include <QNetworkInterface>
#include <QProcess>
@@ -91,6 +94,41 @@ using namespace MOBase;
static env::CoreDumpTypes g_coreDumpType = env::CoreDumpTypes::Mini;
+namespace
+{
+
+QString uniqueFilePath(const QDir& dir, const QString& fileName)
+{
+ QString candidate = dir.filePath(fileName);
+ if (!QFileInfo::exists(candidate)) {
+ return candidate;
+ }
+
+ const QFileInfo info(fileName);
+ const QString base = info.completeBaseName();
+ const QString suffix = info.suffix();
+ const QString timestamp =
+ QDateTime::currentDateTime().toString(QStringLiteral("yyyyMMdd_hhmmss"));
+
+ for (int i = 1; i < 1000; ++i) {
+ const QString numbered =
+ suffix.isEmpty()
+ ? QStringLiteral("%1_%2_%3").arg(base, timestamp).arg(i)
+ : QStringLiteral("%1_%2_%3.%4").arg(base, timestamp).arg(i).arg(suffix);
+ candidate = dir.filePath(numbered);
+ if (!QFileInfo::exists(candidate)) {
+ return candidate;
+ }
+ }
+
+ return dir.filePath(
+ suffix.isEmpty()
+ ? QStringLiteral("%1_%2").arg(base, timestamp)
+ : QStringLiteral("%1_%2.%3").arg(base, timestamp, suffix));
+}
+
+} // namespace
+
template <typename InputIterator>
QStringList toStringList(InputIterator current, InputIterator end)
{
@@ -756,6 +794,58 @@ void OrganizerCore::prepareVFS()
void OrganizerCore::unmountVFS()
{
m_USVFS.unmount();
+ movePGPatcherLogsToLogsFolder();
+}
+
+void OrganizerCore::movePGPatcherLogsToLogsFolder()
+{
+ const QString dataPath = qApp->property("dataPath").toString();
+ if (dataPath.isEmpty()) {
+ log::warn("PGPatcher log cleanup skipped: dataPath is not set");
+ return;
+ }
+
+ QDir logsDir(QDir(dataPath).filePath(QString::fromStdWString(AppConfig::logPath())));
+ if (!logsDir.exists() && !QDir().mkpath(logsDir.absolutePath())) {
+ log::warn("PGPatcher log cleanup skipped: failed to create '{}'",
+ logsDir.absolutePath());
+ return;
+ }
+
+ const QStringList roots = {
+ QDir::fromNativeSeparators(m_Settings.paths().overwrite()),
+ QDir::fromNativeSeparators(m_Settings.paths().mods()),
+ };
+
+ int moved = 0;
+ for (const QString& root : roots) {
+ if (root.isEmpty() || !QDir(root).exists()) {
+ continue;
+ }
+
+ QDirIterator it(root, QStringList{QStringLiteral("PGPatcher.log")},
+ QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot,
+ QDirIterator::Subdirectories);
+ while (it.hasNext()) {
+ const QString source = it.next();
+ const QString destination =
+ uniqueFilePath(logsDir, QFileInfo(source).fileName());
+
+ if (QFile::rename(source, destination) ||
+ (QFile::copy(source, destination) && QFile::remove(source))) {
+ ++moved;
+ log::info("Moved PGPatcher log '{}' -> '{}'", source, destination);
+ } else {
+ log::warn("Failed to move PGPatcher log '{}' -> '{}'", source,
+ destination);
+ }
+ }
+ }
+
+ if (moved > 0) {
+ log::info("PGPatcher log cleanup moved {} file(s) to '{}'", moved,
+ logsDir.absolutePath());
+ }
}
void OrganizerCore::trackOverwriteMove(const QString& relativePath,
@@ -2770,6 +2860,7 @@ void OrganizerCore::afterRun(const QFileInfo& binary, DWORD exitCode)
// and tears down the FUSE session. This mirrors Windows behaviour where
// USVFS is only active while a hooked process is running.
m_USVFS.unmount();
+ movePGPatcherLogsToLogsFolder();
// Restore write permissions on the game directory. In rare cases
// (crashes, unclean Wine shutdown) file permissions can be changed to
diff --git a/src/src/organizercore.h b/src/src/organizercore.h
index 494e835..973ee64 100644
--- a/src/src/organizercore.h
+++ b/src/src/organizercore.h
@@ -534,11 +534,13 @@ private:
const QString& customOverwrite);
std::vector<Mapping> fileMapping(const QString& dataPath, const QString& relPath,
- const MOShared::DirectoryEntry* base,
- const MOShared::DirectoryEntry* directoryEntry,
- int createDestination);
-
-private slots:
+ const MOShared::DirectoryEntry* base,
+ const MOShared::DirectoryEntry* directoryEntry,
+ int createDestination);
+
+ void movePGPatcherLogsToLogsFolder();
+
+private slots:
void onDirectoryRefreshed();
void downloadRequested(QNetworkReply* reply, QString gameName, int modID,
diff --git a/src/src/settingsdialogupdates.cpp b/src/src/settingsdialogupdates.cpp
index 8f76bae..57f5957 100644
--- a/src/src/settingsdialogupdates.cpp
+++ b/src/src/settingsdialogupdates.cpp
@@ -2,6 +2,7 @@
#include "fluorineupdater.h"
#include "settings.h"
+#include "shared/util.h"
#include "ui_settingsdialog.h"
#include <fluorine_build_info.h>
@@ -10,7 +11,6 @@
#include <QApplication>
#include <QCheckBox>
#include <QComboBox>
-#include <QCoreApplication>
#include <QDir>
#include <QFile>
#include <QFileInfo>
@@ -36,6 +36,17 @@
#include <algorithm>
+namespace
+{
+
+bool isLauncherFile(const QString& path)
+{
+ const QFileInfo info(path);
+ return info.isFile();
+}
+
+} // namespace
+
UpdatesSettingsTab::UpdatesSettingsTab(Settings& s, SettingsDialog& d)
: SettingsTab(s, d)
{
@@ -324,22 +335,29 @@ void UpdatesSettingsTab::onInstall()
QDir extract(extractDir);
QString newLauncher =
extract.absoluteFilePath(QStringLiteral("fluorine-manager"));
- if (!QFileInfo::exists(newLauncher)) {
+ if (!isLauncherFile(newLauncher)) {
const QStringList tops = extract.entryList(
QDir::Dirs | QDir::NoDotAndDotDot);
for (const QString& top : tops) {
const QString candidate = extract.absoluteFilePath(
top + QStringLiteral("/fluorine-manager"));
- if (QFileInfo::exists(candidate)) {
+ if (isLauncherFile(candidate)) {
newLauncher = candidate;
break;
}
}
}
- if (!QFileInfo::exists(newLauncher)) {
+ if (isLauncherFile(newLauncher)) {
+ QFile::setPermissions(
+ newLauncher,
+ QFile::permissions(newLauncher) | QFile::ExeOwner |
+ QFile::ExeGroup | QFile::ExeOther);
+ }
+ if (!isLauncherFile(newLauncher) ||
+ !QFileInfo(newLauncher).isExecutable()) {
m_statusLabel->setText(
tr("<i>Install failed:</i> launcher not found in "
- "extracted archive"));
+ "extracted archive, or it is not executable"));
m_progressBar->setVisible(false);
m_installButton->setEnabled(true);
m_checkNowButton->setEnabled(true);
@@ -367,14 +385,13 @@ void UpdatesSettingsTab::onInstall()
QStringLiteral(
"#!/usr/bin/env bash\n"
"set -u\n"
- "OLD_PID=%1\n"
- "NEW_LAUNCHER=%2\n"
+ "OLD_PID=\"$1\"\n"
+ "NEW_LAUNCHER=\"$2\"\n"
"for _ in $(seq 1 200); do\n"
" if ! kill -0 \"$OLD_PID\" 2>/dev/null; then break; fi\n"
" sleep 0.1\n"
"done\n"
- "exec \"$NEW_LAUNCHER\"\n")
- .arg(QString::number(currentPid), newLauncher);
+ "exec \"$NEW_LAUNCHER\"\n");
helper.write(script.toUtf8());
helper.close();
QFile::setPermissions(
@@ -388,7 +405,9 @@ void UpdatesSettingsTab::onInstall()
// Detach the helper so it survives our exit.
QProcess::startDetached(QStringLiteral("/usr/bin/env"),
- {QStringLiteral("bash"), helperPath});
+ {QStringLiteral("bash"), helperPath,
+ QString::number(currentPid),
+ newLauncher});
MOBase::log::info(
"update installer: spawned helper to restart into {}",
@@ -396,7 +415,7 @@ void UpdatesSettingsTab::onInstall()
// Give the signal a beat to propagate, then quit cleanly.
QTimer::singleShot(250, qApp,
- []() { QCoreApplication::quit(); });
+ []() { ExitModOrganizer(Exit::Force); });
});
extractor->start();
});