diff --git a/NEWS b/NEWS index e586519e3..97499a0b3 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,6 @@ ver 0.21 (not yet released) +* configuration + - add "include" directive, allows including config files * protocol - "tagtypes" can be used to hide tags - "find" and "search" can sort diff --git a/doc/user.xml b/doc/user.xml index dad61f286..a2d7a3d04 100644 --- a/doc/user.xml +++ b/doc/user.xml @@ -410,6 +410,14 @@ systemctl start mpd.socket device "iec958:CARD=Intel,DEV=0" mixer_control "PCM" } + + + The include directive can be used to + include settings from another file; the given file name is + relative to the current file: + + + include "other.conf"
diff --git a/src/config/File.cxx b/src/config/File.cxx index 29c073f3b..7b6838bf2 100644 --- a/src/config/File.cxx +++ b/src/config/File.cxx @@ -25,6 +25,7 @@ #include "Templates.hxx" #include "util/Tokenizer.hxx" #include "util/StringStrip.hxx" +#include "util/StringAPI.hxx" #include "util/Domain.hxx" #include "util/RuntimeError.hxx" #include "fs/Path.hxx" @@ -152,8 +153,11 @@ ReadConfigParam(ConfigData &config_data, BufferedReader &reader, reader.GetLineNumber())); } +/** + * @param directory the directory used to resolve relative paths + */ static void -ReadConfigFile(ConfigData &config_data, BufferedReader &reader) +ReadConfigFile(ConfigData &config_data, BufferedReader &reader, Path directory) { while (true) { char *line = reader.ReadLine(); @@ -171,6 +175,16 @@ ReadConfigFile(ConfigData &config_data, BufferedReader &reader) const char *name = tokenizer.NextWord(); assert(name != nullptr); + if (StringIsEqual(name, "include")) { + // TODO: allow absolute path specifications + // TODO: detect recusion + // TODO: Config{Block,Param} have only line number but no file name + // TODO: support wildcards (include "conf.d/*.conf") + // TODO: add "include_optional" + ReadConfigFile(config_data, directory / AllocatedPath::FromUTF8Throw(ExpectValueAndEnd(tokenizer))); + continue; + } + /* get the definition of that option, and check the "repeatable" flag */ @@ -202,7 +216,7 @@ ReadConfigFile(ConfigData &config_data, Path path) BufferedReader reader(file); try { - ReadConfigFile(config_data, reader); + ReadConfigFile(config_data, reader, path.GetDirectoryName()); } catch (...) { std::throw_with_nested(FormatRuntimeError("Error in %s line %u", path_utf8.c_str(),