config/File: support resetting repeatable params

This allows resetting bind_to_address to override the default value in a
included config.
This commit is contained in:
Jochen Sprickerhof 2025-02-21 13:52:44 +01:00
parent 9d87fb5e09
commit d822685c53
No known key found for this signature in database
GPG Key ID: 5BFFDCC258E69433
2 changed files with 19 additions and 6 deletions
doc
src/config

@ -795,6 +795,10 @@ brackets if you want to configure a port::
bind_to_address "[::1]:6602" bind_to_address "[::1]:6602"
To reset the previous assignments just set an empty value:
bind_to_address
To bind to a local socket (UNIX domain socket), specify an absolute To bind to a local socket (UNIX domain socket), specify an absolute
path or a path starting with a tilde (~). Some clients default to path or a path starting with a tilde (~). Some clients default to
connecting to :file:`/run/mpd/socket` so this may be a good connecting to :file:`/run/mpd/socket` so this may be a good

@ -30,10 +30,10 @@ static constexpr Domain config_file_domain("config_file");
* Read a string value as the last token of a line. Throws on error. * Read a string value as the last token of a line. Throws on error.
*/ */
static auto static auto
ExpectValueAndEnd(Tokenizer &tokenizer) ExpectValueAndEnd(Tokenizer &tokenizer, bool repeatable)
{ {
auto value = tokenizer.NextString(); auto value = tokenizer.NextString();
if (!value) if (!repeatable && !value)
throw std::runtime_error("Value missing"); throw std::runtime_error("Value missing");
if (!tokenizer.IsEnd() && tokenizer.CurrentChar() != CONF_COMMENT) if (!tokenizer.IsEnd() && tokenizer.CurrentChar() != CONF_COMMENT)
@ -50,7 +50,7 @@ config_read_name_value(ConfigBlock &block, char *input, unsigned line)
const char *name = tokenizer.NextWord(); const char *name = tokenizer.NextWord();
assert(name != nullptr); assert(name != nullptr);
auto value = ExpectValueAndEnd(tokenizer); auto value = ExpectValueAndEnd(tokenizer, false);
const BlockParam *bp = block.GetBlockParam(name); const BlockParam *bp = block.GetBlockParam(name);
if (bp != nullptr) if (bp != nullptr)
@ -137,14 +137,23 @@ ReadConfigParam(ConfigData &config_data, BufferedReader &reader,
"config parameter {:?} on line {} is deprecated", "config parameter {:?} on line {} is deprecated",
name, reader.GetLineNumber()); name, reader.GetLineNumber());
auto value = ExpectValueAndEnd(tokenizer, option.repeatable);
if (!option.repeatable) if (!option.repeatable)
/* if the option is not repeatable, override the old /* if the option is not repeatable, override the old
value by removing it first */ value by removing it first */
config_data.GetParamList(o).clear(); config_data.GetParamList(o).clear();
else if(!value)
{
/* if it is a repeatable param and the value is empty
clear the old values to allow resetting it */
config_data.GetParamList(o).clear();
return;
}
/* now parse the block or the value */ /* now parse the block or the value */
config_data.AddParam(o, ConfigParam(ExpectValueAndEnd(tokenizer), config_data.AddParam(o, ConfigParam(value,
reader.GetLineNumber())); reader.GetLineNumber()));
} }
@ -174,7 +183,7 @@ ReadConfigFile(ConfigData &config_data, BufferedReader &reader, Path directory)
// TODO: detect recursion // TODO: detect recursion
// TODO: Config{Block,Param} have only line number but no file name // TODO: Config{Block,Param} have only line number but no file name
const auto pattern = AllocatedPath::Apply(directory, const auto pattern = AllocatedPath::Apply(directory,
AllocatedPath::FromUTF8Throw(ExpectValueAndEnd(tokenizer))); AllocatedPath::FromUTF8Throw(ExpectValueAndEnd(tokenizer, false)));
for (const auto &path : ListWildcard(pattern)) for (const auto &path : ListWildcard(pattern))
ReadConfigFile(config_data, path); ReadConfigFile(config_data, path);
continue; continue;
@ -182,7 +191,7 @@ ReadConfigFile(ConfigData &config_data, BufferedReader &reader, Path directory)
if (StringIsEqual(name, "include_optional")) { if (StringIsEqual(name, "include_optional")) {
const auto pattern = AllocatedPath::Apply(directory, const auto pattern = AllocatedPath::Apply(directory,
AllocatedPath::FromUTF8Throw(ExpectValueAndEnd(tokenizer))); AllocatedPath::FromUTF8Throw(ExpectValueAndEnd(tokenizer, false)));
std::forward_list<AllocatedPath> l; std::forward_list<AllocatedPath> l;
try { try {