From 1ebd95314d6801d305d00bf30dc0f4dce596e7d0 Mon Sep 17 00:00:00 2001 From: WhiredPlanck Date: Sun, 6 Mar 2022 13:03:23 +0800 Subject: [PATCH 1/2] Basically support XDG Base Directory specification --- libaegisub/unix/path.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/libaegisub/unix/path.cpp b/libaegisub/unix/path.cpp index 0541e0dbe4..b477c8f784 100644 --- a/libaegisub/unix/path.cpp +++ b/libaegisub/unix/path.cpp @@ -35,6 +35,14 @@ std::string home_dir() { throw agi::EnvironmentError("Could not get home directory. Make sure HOME is set."); } + +std::string xdg_dir(const std::string &environment_variable, + const std::string &fallback_directory) +{ + const char *env = getenv(environment_variable.c_str()); + if (env && *env) return env; + return fallback_directory; +} #endif } @@ -42,8 +50,17 @@ namespace agi { void Path::FillPlatformSpecificPaths() { #ifndef __APPLE__ agi::fs::path home = home_dir(); - SetToken("?user", home/".aegisub"); - SetToken("?local", home/".aegisub"); + agi::fs::path prev_dir = home/".aegisub"; + if (!boost::filesystem::exists(prev_dir)) + { + agi::fs::path xdg_config_home = xdg_dir("XDG_CONFIG_HOME", (home/".config").string()); + agi::fs::path xdg_cache_home = xdg_dir("XDG_CACHE_HOME", (home/".cache").string()); + SetToken("?user", xdg_config_home/"Aegisub"); + SetToken("?local", xdg_cache_home/"Aegisub"); + } else { + SetToken("?user", prev_dir); + SetToken("?local", prev_dir); + } SetToken("?data", P_DATA); SetToken("?dictionary", "/usr/share/hunspell"); #else From 6fba9a6b69cd0eeedb72c869303a3232d546ad00 Mon Sep 17 00:00:00 2001 From: WhiredPlanck Date: Sun, 14 Jan 2024 15:50:52 +0800 Subject: [PATCH 2/2] Split out state dir to save history/log/autoback/autosave files --- libaegisub/common/path.cpp | 8 +++++--- libaegisub/unix/path.cpp | 4 ++++ libaegisub/windows/path_win.cpp | 1 + src/dialog_autosave.cpp | 2 +- src/dialog_shift_times.cpp | 2 +- src/libresrc/default_config.json | 4 ++-- src/libresrc/osx/default_config.json | 4 ++-- src/main.cpp | 9 +++++---- 8 files changed, 21 insertions(+), 13 deletions(-) diff --git a/libaegisub/common/path.cpp b/libaegisub/common/path.cpp index cca7302cc5..c76b4b2975 100644 --- a/libaegisub/common/path.cpp +++ b/libaegisub/common/path.cpp @@ -28,6 +28,7 @@ static const char *tokens[] = { "?dictionary", "?local", "?script", + "?state", "?temp", "?user", "?video" @@ -42,9 +43,10 @@ int find_token(const char *str, size_t len) { case 'd' + 't': idx = 2; break; case 'l' + 'a': idx = 3; break; case 's' + 'i': idx = 4; break; - case 't' + 'p': idx = 5; break; - case 'u' + 'r': idx = 6; break; - case 'v' + 'e': idx = 7; break; + case 's' + 't': idx = 5; break; + case 't' + 'p': idx = 6; break; + case 'u' + 'r': idx = 7; break; + case 'v' + 'e': idx = 8; break; default: return -1; } diff --git a/libaegisub/unix/path.cpp b/libaegisub/unix/path.cpp index b477c8f784..e4fb6e8ea3 100644 --- a/libaegisub/unix/path.cpp +++ b/libaegisub/unix/path.cpp @@ -55,11 +55,14 @@ void Path::FillPlatformSpecificPaths() { { agi::fs::path xdg_config_home = xdg_dir("XDG_CONFIG_HOME", (home/".config").string()); agi::fs::path xdg_cache_home = xdg_dir("XDG_CACHE_HOME", (home/".cache").string()); + agi::fs::path xdg_state_home = xdg_dir("XDG_STATE_HOME", (home/".local/state").string()); SetToken("?user", xdg_config_home/"Aegisub"); SetToken("?local", xdg_cache_home/"Aegisub"); + SetToken("?state", xdg_state_home/"Aegisub"); } else { SetToken("?user", prev_dir); SetToken("?local", prev_dir); + SetToken("?state", prev_dir); } SetToken("?data", P_DATA); SetToken("?dictionary", "/usr/share/hunspell"); @@ -67,6 +70,7 @@ void Path::FillPlatformSpecificPaths() { agi::fs::path app_support = agi::util::GetApplicationSupportDirectory(); SetToken("?user", app_support/"Aegisub"); SetToken("?local", app_support/"Aegisub"); + SetToken("?state", app_support/"Aegisub"); SetToken("?data", agi::util::GetBundleSharedSupportDirectory()); SetToken("?dictionary", agi::util::GetBundleSharedSupportDirectory() + "/dictionaries"); #endif diff --git a/libaegisub/windows/path_win.cpp b/libaegisub/windows/path_win.cpp index 387cf1cdd3..65b2c0e9b4 100644 --- a/libaegisub/windows/path_win.cpp +++ b/libaegisub/windows/path_win.cpp @@ -44,6 +44,7 @@ void Path::FillPlatformSpecificPaths() { SetToken("?user", WinGetFolderPath(CSIDL_APPDATA)/"Aegisub"); SetToken("?local", WinGetFolderPath(CSIDL_LOCAL_APPDATA)/"Aegisub"); + SetToken("?state", WinGetFolderPath(CSIDL_APPDATA)/"Aegisub"); std::wstring filename(MAX_PATH + 1, L'\0'); while (static_cast(filename.size()) == GetModuleFileNameW(nullptr, &filename[0], filename.size())) diff --git a/src/dialog_autosave.cpp b/src/dialog_autosave.cpp index 7b215b3908..1d75eb8511 100644 --- a/src/dialog_autosave.cpp +++ b/src/dialog_autosave.cpp @@ -92,7 +92,7 @@ DialogAutosave::DialogAutosave(wxWindow *parent) std::map files_map; Populate(files_map, OPT_GET("Path/Auto/Save")->GetString(), ".AUTOSAVE.ass", "%s"); Populate(files_map, OPT_GET("Path/Auto/Backup")->GetString(), ".ORIGINAL.ass", _("%s [ORIGINAL BACKUP]")); - Populate(files_map, "?user/recovered", ".ass", _("%s [RECOVERED]")); + Populate(files_map, "?state/recovered", ".ass", _("%s [RECOVERED]")); for (auto& file : files_map | boost::adaptors::map_values) files.emplace_back(std::move(file)); diff --git a/src/dialog_shift_times.cpp b/src/dialog_shift_times.cpp index 07dbed59af..92e13c7ad2 100644 --- a/src/dialog_shift_times.cpp +++ b/src/dialog_shift_times.cpp @@ -134,7 +134,7 @@ static wxString get_history_string(json::Object &obj) { DialogShiftTimes::DialogShiftTimes(agi::Context *context) : wxDialog(context->parent, -1, _("Shift Times")) , context(context) -, history_filename(config::path->Decode("?user/shift_history.json")) +, history_filename(config::path->Decode("?state/shift_history.json")) , timecodes_loaded_slot(context->project->AddTimecodesListener(&DialogShiftTimes::OnTimecodesLoaded, this)) , selected_set_changed_slot(context->selectionController->AddSelectionListener(&DialogShiftTimes::OnSelectedSetChanged, this)) { diff --git a/src/libresrc/default_config.json b/src/libresrc/default_config.json index 8a648fa47c..6230bc09c7 100644 --- a/src/libresrc/default_config.json +++ b/src/libresrc/default_config.json @@ -284,8 +284,8 @@ "Path" : { "Auto" : { - "Backup" : "?user/autoback", - "Save" : "?user/autosave" + "Backup" : "?state/autoback", + "Save" : "?state/autosave" }, "Automation" : { "Autoload" : "?user/automation/autoload/|?data/automation/autoload/", diff --git a/src/libresrc/osx/default_config.json b/src/libresrc/osx/default_config.json index 82223cf484..3c85c6ca17 100644 --- a/src/libresrc/osx/default_config.json +++ b/src/libresrc/osx/default_config.json @@ -284,8 +284,8 @@ "Path" : { "Auto" : { - "Backup" : "?user/autoback", - "Save" : "?user/autosave" + "Backup" : "?state/autoback", + "Save" : "?state/autosave" }, "Automation" : { "Autoload" : "?user/automation/autoload/|?data/automation/autoload/", diff --git a/src/main.cpp b/src/main.cpp index e2f8b5a7b1..b64668616d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -167,7 +167,7 @@ bool AegisubApp::OnInit() { }); config::path = new agi::Path; - crash_writer::Initialize(config::path->Decode("?user")); + crash_writer::Initialize(config::path->Decode("?state")); agi::log::log = new agi::log::LogSink; #ifdef _DEBUG @@ -186,7 +186,8 @@ bool AegisubApp::OnInit() { // Local config, make ?user mean ?data so all user settings are placed in install dir config::path->SetToken("?user", config::path->Decode("?data")); config::path->SetToken("?local", config::path->Decode("?data")); - crash_writer::Initialize(config::path->Decode("?user")); + config::path->SetToken("?state", config::path->Decode("?data")); + crash_writer::Initialize(config::path->Decode("?state")); } catch (agi::fs::FileSystemError const&) { // File doesn't exist or we can't read it // Might be worth displaying an error in the second case @@ -194,7 +195,7 @@ bool AegisubApp::OnInit() { #endif StartupLog("Create log writer"); - auto path_log = config::path->Decode("?user/log/"); + auto path_log = config::path->Decode("?state/log/"); agi::fs::CreateDirectory(path_log); agi::log::log->Subscribe(agi::make_unique(path_log)); CleanCache(path_log, "*.json", 10, 100); @@ -405,7 +406,7 @@ void AegisubApp::UnhandledException(bool stackWalk) { auto c = frame->context.get(); if (!c || !c->ass || !c->subsController) continue; - path = config::path->Decode("?user/recovered"); + path = config::path->Decode("?state/recovered"); agi::fs::CreateDirectory(path); auto filename = c->subsController->Filename().stem();