about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--doc/manual/command-ref/conf-file.xml7
-rw-r--r--src/libutil/config.cc26
-rw-r--r--tests/init.sh5
3 files changed, 36 insertions, 2 deletions
diff --git a/doc/manual/command-ref/conf-file.xml b/doc/manual/command-ref/conf-file.xml
index 5c4561f66d86..8ed614963a4b 100644
--- a/doc/manual/command-ref/conf-file.xml
+++ b/doc/manual/command-ref/conf-file.xml
@@ -40,7 +40,12 @@
 
 <para>The configuration files consist of
 <literal><replaceable>name</replaceable> =
-<replaceable>value</replaceable></literal> pairs, one per line.
+<replaceable>value</replaceable></literal> pairs, one per line. Other
+files can be included with a line like <literal>include
+<replaceable>path</replaceable></literal>, where
+<replaceable>path</replaceable> is interpreted relative to the current
+conf file and a missing file is an error unless
+<literal>!include</literal> is used instead.
 Comments start with a <literal>#</literal> character.  Here is an
 example configuration file:</para>
 
diff --git a/src/libutil/config.cc b/src/libutil/config.cc
index d46ca65a3863..0e502769edf8 100644
--- a/src/libutil/config.cc
+++ b/src/libutil/config.cc
@@ -80,7 +80,31 @@ void Config::applyConfigFile(const Path & path, bool fatal)
             vector<string> tokens = tokenizeString<vector<string> >(line);
             if (tokens.empty()) continue;
 
-            if (tokens.size() < 2 || tokens[1] != "=")
+            if (tokens.size() < 2)
+                throw UsageError("illegal configuration line '%1%' in '%2%'", line, path);
+
+            auto include = false;
+            auto ignoreMissing = false;
+            if (tokens[0] == "include")
+                include = true;
+            else if (tokens[0] == "!include") {
+                include = true;
+                ignoreMissing = true;
+            }
+
+            if (include) {
+                if (tokens.size() != 2)
+                    throw UsageError("illegal configuration line '%1%' in '%2%'", line, path);
+                auto p = absPath(tokens[1], dirOf(path));
+                if (pathExists(p)) {
+                    applyConfigFile(p, fatal);
+                } else if (!ignoreMissing) {
+                    throw Error("file '%1%' included from '%2%' not found", p, path);
+                }
+                continue;
+            }
+
+            if (tokens[1] != "=")
                 throw UsageError("illegal configuration line '%1%' in '%2%'", line, path);
 
             string name = tokens[0];
diff --git a/tests/init.sh b/tests/init.sh
index 41cca047d8fb..e5353598bcc4 100644
--- a/tests/init.sh
+++ b/tests/init.sh
@@ -16,7 +16,12 @@ mkdir "$NIX_CONF_DIR"
 cat > "$NIX_CONF_DIR"/nix.conf <<EOF
 build-users-group =
 keep-derivations = false
+include nix.conf.extra
+EOF
+
+cat > "$NIX_CONF_DIR"/nix.conf.extra <<EOF
 fsync-metadata = false
+!include nix.conf.extra.not-there
 EOF
 
 # Initialise the database.