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:
parent
646883174b
commit
4bb9eab0d0
7 changed files with 63 additions and 46 deletions
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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_);
|
||||||
|
|
Loading…
Reference in a new issue