feat: command-line arguments for setting portable directory (#7093)

Reviewed-by: Nerixyz <nerixdev@outlook.de>
Reviewed-by: pajlada <rasmus.karlsson@pajlada.com>
This commit is contained in:
teknsl
2026-07-18 11:53:18 +00:00
committed by GitHub
parent 14bf8c6fad
commit 78e856f7c9
13 changed files with 61 additions and 39 deletions
+1 -1
View File
@@ -27,7 +27,7 @@ int main(int argc, char **argv)
// Ensure settings are initialized before any benchmarks are run
QTemporaryDir settingsDir;
settingsDir.setAutoRemove(false); // we'll remove it manually
chatterino::Settings settings(Modes(), args, settingsDir.path());
chatterino::Settings settings(Modes(args), args, settingsDir.path());
QTimer::singleShot(0, [&]() {
::benchmark::RunSpecifiedBenchmarks();
+2 -2
View File
@@ -294,9 +294,9 @@ public:
}
QTemporaryDir settingsDir;
Modes modes_;
Paths paths_ = {modes_};
Args args_;
Modes modes_{args_};
Paths paths_ = {args_, modes_};
};
} // namespace chatterino::mock
+19
View File
@@ -188,6 +188,12 @@ Args::Args(const QApplication &app)
"like you have to use this, please reach out to our issue tracker at "
"https://github.com/Chatterino/chatterino2/issues");
QCommandLineOption portableEnable("portable", "Enable portable mode.");
QCommandLineOption portableDirectory(
"portable-dir", "Directory to use when portable mode is enabled.",
"directory");
#ifndef NDEBUG
QCommandLineOption useLocalEventsubOption(
"use-local-eventsub",
@@ -207,6 +213,8 @@ Args::Args(const QApplication &app)
channelLayout,
activateOption,
useOldScalingOption,
portableEnable,
portableDirectory,
#ifndef NDEBUG
useLocalEventsubOption,
#endif
@@ -283,6 +291,17 @@ Args::Args(const QApplication &app)
this->useOldScaling = true;
}
if (parser.isSet(portableEnable))
{
this->portableEnable = true;
}
if (parser.isSet(portableDirectory))
{
this->portableDirectory =
QDir(parser.value(portableDirectory)).absolutePath();
}
#ifndef NDEBUG
if (parser.isSet(useLocalEventsubOption))
{
+3
View File
@@ -68,6 +68,9 @@ public:
bool verbose{};
bool safeMode{};
bool portableEnable{};
std::optional<QString> portableDirectory;
bool useOldScaling = false;
#ifndef NDEBUG
+7 -1
View File
@@ -4,14 +4,20 @@
#include "common/Modes.hpp"
#include "common/Args.hpp"
#include "util/CombinePath.hpp"
#include <QCoreApplication>
namespace chatterino {
Modes::Modes()
Modes::Modes(const Args &args)
{
if (args.portableEnable)
{
this->isPortable = true;
}
QFile file(combinePath(QCoreApplication::applicationDirPath(), "modes"));
if (!file.open(QIODevice::ReadOnly))
{
+4 -1
View File
@@ -6,11 +6,14 @@
namespace chatterino {
class Args;
class Modes
{
public:
Modes();
explicit Modes(const Args &args);
/// Marked by the line `portable` or `portableEnable` from `Args`
bool isPortable{};
/// Marked by the line `externally-packaged`
+3 -4
View File
@@ -50,7 +50,8 @@ int main(int argc, char **argv)
Version::instance().appUserModelID().c_str());
#endif
const Modes modes;
const Args args(a);
const Modes modes(args);
std::unique_ptr<Paths> paths;
// Optional logger override that logs to a file
@@ -58,7 +59,7 @@ int main(int argc, char **argv)
try
{
paths = std::make_unique<Paths>(modes);
paths = std::make_unique<Paths>(args, modes);
}
catch (std::runtime_error &error)
{
@@ -85,8 +86,6 @@ int main(int argc, char **argv)
}
ipc::initPaths(paths.get());
const Args args(a);
#ifdef CHATTERINO_WITH_CRASHPAD
const auto crashpadHandler = installCrashHandler(args, *paths);
#endif
+10 -15
View File
@@ -4,6 +4,7 @@
#include "singletons/Paths.hpp"
#include "common/Args.hpp"
#include "common/Modes.hpp"
#include "singletons/Settings.hpp"
#include "util/CombinePath.hpp"
@@ -19,12 +20,11 @@ using namespace std::literals;
namespace chatterino {
Paths::Paths(const Modes &modes)
Paths::Paths(const Args &args, const Modes &modes)
{
this->initAppFilePathHash();
this->initCheckPortable();
this->initRootDirectory(modes);
this->initRootDirectory(args, modes);
this->initSubDirectories();
}
@@ -75,23 +75,18 @@ void Paths::initAppFilePathHash()
.replace("/", "x");
}
void Paths::initCheckPortable()
void Paths::initRootDirectory(const Args &args, const Modes &modes)
{
this->portable_ = QFileInfo::exists(
combinePath(QCoreApplication::applicationDirPath(), "portable"));
}
void Paths::initRootDirectory(const Modes &modes)
{
assert(this->portable_.has_value());
// Root path = %APPDATA%/Chatterino or the folder that the executable
// resides in
this->rootAppDataDirectory = [&]() -> QString {
// portable
if (modes.isPortable)
{
// override
if (args.portableDirectory.has_value())
{
return args.portableDirectory.value();
}
return QCoreApplication::applicationDirPath();
}
+3 -7
View File
@@ -6,16 +6,15 @@
#include <QString>
#include <optional>
namespace chatterino {
class Modes;
class Args;
class Paths
{
public:
Paths(const Modes &modes);
Paths(const Args &args, const Modes &modes);
// Root directory for the configuration files. %APPDATA%/chatterino or
// ExecutablePath for portable mode
@@ -64,12 +63,9 @@ public:
private:
void initAppFilePathHash();
void initCheckPortable();
void initRootDirectory(const Modes &modes);
void initRootDirectory(const Args &args, const Modes &modes);
void initSubDirectories();
std::optional<bool> portable_;
// Directory for cache files. Same as <appDataDirectory>/Misc
QString cacheDirectory_;
};
+3 -3
View File
@@ -206,7 +206,7 @@ void Updates::installUpdates()
file.flush();
file.close();
auto updaterPath = Updates::portableUpdaterPath();
auto updaterPath = Updates::portableUpdaterPath(this->paths);
if (!QFile::exists(updaterPath))
{
this->setStatus_(MissingPortableUpdater);
@@ -410,9 +410,9 @@ Updates::Status Updates::getStatus() const
return this->status_;
}
QString Updates::portableUpdaterPath()
QString Updates::portableUpdaterPath(const Paths &paths)
{
return combinePath(QCoreApplication::applicationDirPath(),
return combinePath(paths.rootAppDataDirectory,
"updater.1/ChatterinoUpdater.exe");
}
+1 -1
View File
@@ -55,7 +55,7 @@ public:
void installUpdates();
Status getStatus() const;
static QString portableUpdaterPath();
static QString portableUpdaterPath(const Paths &paths);
bool shouldShowUpdateButton() const;
bool isError() const;
+4 -3
View File
@@ -99,9 +99,10 @@ void UpdateDialog::updateStatusChanged(Updates::Status status)
break;
case Updates::MissingPortableUpdater: {
this->ui_.label->setText("The portable updater (expected in " %
Updates::portableUpdaterPath() %
") was not found.");
this->ui_.label->setText(
"The portable updater (expected in " %
Updates::portableUpdaterPath(getApp()->getPaths()) %
") was not found.");
}
break;
+1 -1
View File
@@ -43,7 +43,7 @@ int main(int argc, char **argv)
// Ensure settings are initialized before any tests are run
QTemporaryDir settingsDir;
settingsDir.setAutoRemove(false); // we'll remove it manually
chatterino::Settings settings(Modes(), args, settingsDir.path());
chatterino::Settings settings(Modes(args), args, settingsDir.path());
QTimer::singleShot(0, [&]() {
auto res = RUN_ALL_TESTS();