1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2025-01-03 05:25:52 +00:00

fix: app defaults should override libtransmission defaults (#6495)

This commit is contained in:
Yat Ho 2024-01-07 00:10:14 +08:00 committed by GitHub
parent 646883174b
commit 4bb9eab0d0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 63 additions and 46 deletions

View file

@ -321,7 +321,7 @@ int tr_main(int argc, char* argv[])
/* load the defaults from config file + libtransmission defaults */ /* load the defaults from config file + libtransmission defaults */
auto const config_dir = getConfigDir(argc, (char const**)argv); auto const config_dir = getConfigDir(argc, (char const**)argv);
auto settings = tr_sessionLoadSettings(config_dir.c_str(), MyConfigName); auto settings = tr_sessionLoadSettings(nullptr, config_dir.c_str(), MyConfigName);
/* the command line overrides defaults */ /* the command line overrides defaults */
if (parseCommandLine(&settings, argc, (char const**)argv) != 0) if (parseCommandLine(&settings, argc, (char const**)argv) != 0)

View file

@ -6,7 +6,6 @@
#include <array> #include <array>
#include <cerrno> #include <cerrno>
#include <cstdio> /* printf */ #include <cstdio> /* printf */
#include <cstdlib> /* atoi */
#include <iostream> #include <iostream>
#include <iterator> /* std::back_inserter */ #include <iterator> /* std::back_inserter */
#include <memory> #include <memory>
@ -360,6 +359,14 @@ tr_rpc_callback_status on_rpc_callback(tr_session* /*session*/, tr_rpc_callback_
} }
return TR_RPC_OK; return TR_RPC_OK;
} }
tr_variant load_settings(char const* config_dir)
{
auto app_defaults = tr_variant::make_map();
tr_variantDictAddBool(&app_defaults, TR_KEY_rpc_enabled, true);
return tr_sessionLoadSettings(&app_defaults, config_dir, MyName);
}
} // namespace } // namespace
bool tr_daemon::reopen_log_file(char const* filename) bool tr_daemon::reopen_log_file(char const* filename)
@ -394,7 +401,7 @@ bool tr_daemon::reopen_log_file(char const* filename)
return true; return true;
} }
void tr_daemon::report_status(void) void tr_daemon::report_status()
{ {
double const up = tr_sessionGetRawSpeed_KBps(my_session_, TR_UP); double const up = tr_sessionGetRawSpeed_KBps(my_session_, TR_UP);
double const dn = tr_sessionGetRawSpeed_KBps(my_session_, TR_DOWN); double const dn = tr_sessionGetRawSpeed_KBps(my_session_, TR_DOWN);
@ -409,7 +416,7 @@ void tr_daemon::report_status(void)
} }
} }
void tr_daemon::periodic_update(void) void tr_daemon::periodic_update()
{ {
pumpLogMessages(logfile_, logfile_flush_); pumpLogMessages(logfile_, logfile_flush_);
report_status(); report_status();
@ -498,7 +505,10 @@ bool tr_daemon::parse_args(int argc, char const* const* argv, bool* dump_setting
break; break;
case 'p': case 'p':
tr_variantDictAddInt(&settings_, TR_KEY_rpc_port, atoi(optstr)); if (auto const rpc_port = tr_num_parse<uint16_t>(optstr); rpc_port)
{
tr_variantDictAddInt(&settings_, TR_KEY_rpc_port, *rpc_port);
}
break; break;
case 't': case 't':
@ -522,7 +532,10 @@ bool tr_daemon::parse_args(int argc, char const* const* argv, bool* dump_setting
break; break;
case 'P': case 'P':
tr_variantDictAddInt(&settings_, TR_KEY_peer_port, atoi(optstr)); if (auto const peer_port = tr_num_parse<uint16_t>(optstr); peer_port)
{
tr_variantDictAddInt(&settings_, TR_KEY_peer_port, *peer_port);
}
break; break;
case 'm': case 'm':
@ -534,11 +547,17 @@ bool tr_daemon::parse_args(int argc, char const* const* argv, bool* dump_setting
break; break;
case 'L': case 'L':
tr_variantDictAddInt(&settings_, TR_KEY_peer_limit_global, atoi(optstr)); if (auto const peer_limit_global = tr_num_parse<int64_t>(optstr); peer_limit_global && *peer_limit_global >= 0)
{
tr_variantDictAddInt(&settings_, TR_KEY_peer_limit_global, *peer_limit_global);
}
break; break;
case 'l': case 'l':
tr_variantDictAddInt(&settings_, TR_KEY_peer_limit_per_torrent, atoi(optstr)); if (auto const peer_limit_tor = tr_num_parse<int64_t>(optstr); peer_limit_tor && *peer_limit_tor >= 0)
{
tr_variantDictAddInt(&settings_, TR_KEY_peer_limit_per_torrent, *peer_limit_tor);
}
break; break;
case 800: case 800:
@ -570,7 +589,10 @@ bool tr_daemon::parse_args(int argc, char const* const* argv, bool* dump_setting
break; break;
case 953: case 953:
tr_variantDictAddReal(&settings_, TR_KEY_ratio_limit, atof(optstr)); if (auto const ratio_limit = tr_num_parse<double>(optstr); optstr)
{
tr_variantDictAddReal(&settings_, TR_KEY_ratio_limit, *ratio_limit);
}
tr_variantDictAddBool(&settings_, TR_KEY_ratio_limit_enabled, true); tr_variantDictAddBool(&settings_, TR_KEY_ratio_limit_enabled, true);
break; break;
@ -640,7 +662,7 @@ bool tr_daemon::parse_args(int argc, char const* const* argv, bool* dump_setting
return true; return true;
} }
void tr_daemon::reconfigure(void) void tr_daemon::reconfigure()
{ {
if (my_session_ == nullptr) if (my_session_ == nullptr)
{ {
@ -660,35 +682,24 @@ void tr_daemon::reconfigure(void)
configDir = tr_sessionGetConfigDir(my_session_); configDir = tr_sessionGetConfigDir(my_session_);
tr_logAddInfo(fmt::format(_("Reloading settings from '{path}'"), fmt::arg("path", configDir))); tr_logAddInfo(fmt::format(_("Reloading settings from '{path}'"), fmt::arg("path", configDir)));
auto newsettings = tr_variant::make_map(); tr_sessionSet(my_session_, load_settings(configDir));
tr_variantDictAddBool(&newsettings, TR_KEY_rpc_enabled, true);
newsettings.merge(tr_sessionLoadSettings(configDir, MyName));
tr_sessionSet(my_session_, newsettings);
tr_sessionReloadBlocklists(my_session_); tr_sessionReloadBlocklists(my_session_);
} }
} }
void tr_daemon::stop(void) void tr_daemon::stop()
{ {
event_base_loopexit(ev_base_, nullptr); event_base_loopexit(ev_base_, nullptr);
} }
int tr_daemon::start([[maybe_unused]] bool foreground) int tr_daemon::start([[maybe_unused]] bool foreground)
{ {
bool boolVal;
bool pidfile_created = false;
tr_session* session = nullptr;
struct event* status_ev = nullptr;
struct event* sig_ev = nullptr;
auto watchdir = std::unique_ptr<Watchdir>{};
char const* const cdir = this->config_dir_.c_str();
sd_notifyf(0, "MAINPID=%d\n", (int)getpid()); sd_notifyf(0, "MAINPID=%d\n", (int)getpid());
/* setup event state */ /* setup event state */
ev_base_ = event_base_new(); ev_base_ = event_base_new();
event* sig_ev = nullptr;
if (ev_base_ == nullptr || !setup_signals(sig_ev)) if (ev_base_ == nullptr || !setup_signals(sig_ev))
{ {
auto const error_code = errno; auto const error_code = errno;
@ -702,7 +713,8 @@ int tr_daemon::start([[maybe_unused]] bool foreground)
} }
/* start the session */ /* start the session */
session = tr_sessionInit(cdir, true, settings_); auto const* const cdir = this->config_dir_.c_str();
auto* session = tr_sessionInit(cdir, true, settings_);
tr_sessionSetRPCCallback(session, on_rpc_callback, this); tr_sessionSetRPCCallback(session, on_rpc_callback, this);
tr_logAddInfo(fmt::format(_("Loading settings from '{path}'"), fmt::arg("path", cdir))); tr_logAddInfo(fmt::format(_("Loading settings from '{path}'"), fmt::arg("path", cdir)));
tr_sessionSaveSettings(session, cdir, settings_); tr_sessionSaveSettings(session, cdir, settings_);
@ -710,6 +722,7 @@ int tr_daemon::start([[maybe_unused]] bool foreground)
auto sv = std::string_view{}; auto sv = std::string_view{};
(void)tr_variantDictFindStrView(&settings_, key_pidfile_, &sv); (void)tr_variantDictFindStrView(&settings_, key_pidfile_, &sv);
auto const sz_pid_filename = std::string{ sv }; auto const sz_pid_filename = std::string{ sv };
auto pidfile_created = false;
if (!std::empty(sz_pid_filename)) if (!std::empty(sz_pid_filename))
{ {
auto error = tr_error{}; auto error = tr_error{};
@ -737,7 +750,7 @@ int tr_daemon::start([[maybe_unused]] bool foreground)
} }
} }
if (tr_variantDictFindBool(&settings_, TR_KEY_rpc_authentication_required, &boolVal) && boolVal) if (auto tmp_bool = false; tr_variantDictFindBool(&settings_, TR_KEY_rpc_authentication_required, &tmp_bool) && tmp_bool)
{ {
tr_logAddInfo(_("Requiring authentication")); tr_logAddInfo(_("Requiring authentication"));
} }
@ -751,7 +764,8 @@ int tr_daemon::start([[maybe_unused]] bool foreground)
} }
/* maybe add a watchdir */ /* maybe add a watchdir */
if (tr_variantDictFindBool(&settings_, TR_KEY_watch_dir_enabled, &boolVal) && boolVal) auto watchdir = std::unique_ptr<Watchdir>{};
if (auto tmp_bool = false; tr_variantDictFindBool(&settings_, TR_KEY_watch_dir_enabled, &tmp_bool) && tmp_bool)
{ {
auto force_generic = bool{ false }; auto force_generic = bool{ false };
(void)tr_variantDictFindBool(&settings_, key_watch_dir_force_generic_, &force_generic); (void)tr_variantDictFindBool(&settings_, key_watch_dir_force_generic_, &force_generic);
@ -796,6 +810,7 @@ int tr_daemon::start([[maybe_unused]] bool foreground)
#endif #endif
/* Create new timer event to report daemon status */ /* Create new timer event to report daemon status */
event* status_ev;
{ {
constexpr auto one_sec = timeval{ 1, 0 }; // 1 second constexpr auto one_sec = timeval{ 1, 0 }; // 1 second
status_ev = event_new(ev_base_, -1, EV_PERSIST, &::periodic_update, this); status_ev = event_new(ev_base_, -1, EV_PERSIST, &::periodic_update, this);
@ -882,9 +897,7 @@ bool tr_daemon::init(int argc, char const* const argv[], bool* foreground, int*
config_dir_ = getConfigDir(argc, argv); config_dir_ = getConfigDir(argc, argv);
/* load settings from defaults + config file */ /* load settings from defaults + config file */
settings_ = tr_variant::make_map(); settings_ = load_settings(config_dir_.c_str());
tr_variantDictAddBool(&settings_, TR_KEY_rpc_enabled, true);
settings_.merge(tr_sessionLoadSettings(config_dir_.c_str(), MyName));
bool dumpSettings; bool dumpSettings;
@ -893,7 +906,7 @@ bool tr_daemon::init(int argc, char const* const argv[], bool* foreground, int*
/* overwrite settings from the command line */ /* overwrite settings from the command line */
if (!parse_args(argc, argv, &dumpSettings, foreground, ret)) if (!parse_args(argc, argv, &dumpSettings, foreground, ret))
{ {
goto EXIT_EARLY; return false;
} }
if (*foreground && logfile_ == TR_BAD_SYS_FILE) if (*foreground && logfile_ == TR_BAD_SYS_FILE)
@ -905,13 +918,10 @@ bool tr_daemon::init(int argc, char const* const argv[], bool* foreground, int*
if (dumpSettings) if (dumpSettings)
{ {
fmt::print("{:s}\n", tr_variant_serde::json().to_string(settings_)); fmt::print("{:s}\n", tr_variant_serde::json().to_string(settings_));
goto EXIT_EARLY; return false;
} }
return true; return true;
EXIT_EARLY:
return false;
} }
void tr_daemon::handle_error(tr_error const& error) const void tr_daemon::handle_error(tr_error const& error) const

View file

@ -108,8 +108,8 @@ tr_variant& getPrefs()
if (!settings.has_value()) if (!settings.has_value())
{ {
settings = get_default_app_settings(); auto const app_defaults = get_default_app_settings();
settings.merge(tr_sessionLoadSettings(gl_confdir.c_str(), nullptr)); settings.merge(tr_sessionLoadSettings(&app_defaults, gl_confdir.c_str(), nullptr));
ensure_sound_cmd_is_a_list(&settings); ensure_sound_cmd_is_a_list(&settings);
} }

View file

@ -476,10 +476,16 @@ tr_variant tr_sessionGetSettings(tr_session const* session)
return settings; return settings;
} }
tr_variant tr_sessionLoadSettings(char const* config_dir, char const* app_name) tr_variant tr_sessionLoadSettings(tr_variant const* app_defaults, char const* config_dir, char const* app_name)
{ {
auto settings = tr_sessionGetDefaultSettings(); auto settings = tr_sessionGetDefaultSettings();
// if app defaults are provided, override libtransmission defaults
if (app_defaults != nullptr && app_defaults->holds_alternative<tr_variant::Map>())
{
settings.merge(*app_defaults);
}
// if a settings file exists, use it to override the defaults // if a settings file exists, use it to override the defaults
if (auto const filename = fmt::format( if (auto const filename = fmt::format(
"{:s}/settings.json", "{:s}/settings.json",
@ -554,11 +560,11 @@ tr_session* tr_sessionInit(char const* config_dir, bool message_queueing_enabled
// - client settings // - client settings
// - previous session's values in settings.json // - previous session's values in settings.json
// - hardcoded defaults // - hardcoded defaults
auto settings = tr_sessionLoadSettings(config_dir, nullptr); auto settings = tr_sessionLoadSettings(nullptr, config_dir, nullptr);
settings.merge(client_settings); settings.merge(client_settings);
// if logging is desired, start it now before doing more work // if logging is desired, start it now before doing more work
if (auto const* settings_map = client_settings.get_if<tr_variant::Map>(); settings_map != nullptr) if (auto const* settings_map = settings.get_if<tr_variant::Map>(); settings_map != nullptr)
{ {
if (auto const* val = settings_map->find_if<bool>(TR_KEY_message_level); val != nullptr) if (auto const* val = settings_map->find_if<bool>(TR_KEY_message_level); val != nullptr)
{ {

View file

@ -175,6 +175,7 @@ tr_variant tr_sessionGetSettings(tr_session const* session);
* *
* TODO: if we ever make libtransmissionapp, this would go there. * TODO: if we ever make libtransmissionapp, this would go there.
* *
* @param app_defaults tr_variant containing the app defaults
* @param config_dir the configuration directory to find settings.json * @param config_dir the configuration directory to find settings.json
* @param app_name if config_dir is empty, app_name is used to find the default dir. * @param app_name if config_dir is empty, app_name is used to find the default dir.
* @return the loaded settings * @return the loaded settings
@ -182,7 +183,7 @@ tr_variant tr_sessionGetSettings(tr_session const* session);
* @see `tr_sessionInit()` * @see `tr_sessionInit()`
* @see `tr_sessionSaveSettings()` * @see `tr_sessionSaveSettings()`
*/ */
tr_variant tr_sessionLoadSettings(char const* config_dir, char const* app_name); tr_variant tr_sessionLoadSettings(tr_variant const* app_defaults, char const* config_dir, char const* app_name);
/** /**
* Add the session's configuration settings to the benc dictionary * Add the session's configuration settings to the benc dictionary

View file

@ -227,13 +227,13 @@ Prefs::Prefs(QString config_dir)
// when the application exits. // when the application exits.
temporary_prefs_.insert(FILTER_TEXT); temporary_prefs_.insert(FILTER_TEXT);
auto top = get_default_app_settings(); auto const app_defaults = get_default_app_settings();
top.merge(tr_sessionLoadSettings(config_dir_.toUtf8().constData(), nullptr)); auto settings = tr_sessionLoadSettings(&app_defaults, config_dir_.toUtf8().constData(), nullptr);
ensureSoundCommandIsAList(&top); ensureSoundCommandIsAList(&settings);
for (int i = 0; i < PREFS_COUNT; ++i) for (int i = 0; i < PREFS_COUNT; ++i)
{ {
tr_variant const* b = tr_variantDictFind(&top, Items[i].key); tr_variant const* b = tr_variantDictFind(&settings, Items[i].key);
switch (Items[i].type) switch (Items[i].type)
{ {

View file

@ -357,7 +357,7 @@ void Session::start()
} }
else else
{ {
auto const settings = tr_sessionLoadSettings(config_dir_.toUtf8().constData(), "qt"); auto const settings = tr_sessionLoadSettings(nullptr, config_dir_.toUtf8().constData(), "qt");
session_ = tr_sessionInit(config_dir_.toUtf8().constData(), true, settings); session_ = tr_sessionInit(config_dir_.toUtf8().constData(), true, settings);
rpc_.start(session_); rpc_.start(session_);