config/File: implement the "include" directive

This is an experimental draft.  More needs to be done.
This commit is contained in:
Max Kellermann 2018-07-17 20:12:42 +02:00
parent 57729683b6
commit d06ef76e58
3 changed files with 26 additions and 2 deletions

2
NEWS
View File

@ -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

View File

@ -410,6 +410,14 @@ systemctl start mpd.socket</programlisting>
device "iec958:CARD=Intel,DEV=0"
mixer_control "PCM"
}</programlisting>
<para>
The <varname>include</varname> directive can be used to
include settings from another file; the given file name is
relative to the current file:
</para>
<programlisting>include "other.conf"</programlisting>
</section>
<section id="config_music_directory">

View File

@ -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(),