aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/config.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libutil/config.cc')
-rw-r--r--src/libutil/config.cc94
1 files changed, 55 insertions, 39 deletions
diff --git a/src/libutil/config.cc b/src/libutil/config.cc
index a42f3a849..085a884dc 100644
--- a/src/libutil/config.cc
+++ b/src/libutil/config.cc
@@ -3,6 +3,8 @@
#include "abstract-setting-to-json.hh"
#include "experimental-features.hh"
+#include "config-impl.hh"
+
#include <nlohmann/json.hpp>
namespace nix {
@@ -80,6 +82,8 @@ void Config::getSettings(std::map<std::string, SettingInfo> & res, bool overridd
void AbstractConfig::applyConfig(const std::string & contents, const std::string & path) {
unsigned int pos = 0;
+ std::vector<std::pair<std::string, std::string>> parsedContents;
+
while (pos < contents.size()) {
std::string line;
while (pos < contents.size() && contents[pos] != '\n')
@@ -125,8 +129,21 @@ void AbstractConfig::applyConfig(const std::string & contents, const std::string
auto i = tokens.begin();
advance(i, 2);
- set(name, concatStringsSep(" ", Strings(i, tokens.end()))); // FIXME: slow
+ parsedContents.push_back({
+ name,
+ concatStringsSep(" ", Strings(i, tokens.end())),
+ });
};
+
+ // First apply experimental-feature related settings
+ for (auto & [name, value] : parsedContents)
+ if (name == "experimental-features" || name == "extra-experimental-features")
+ set(name, value);
+
+ // Then apply other settings
+ for (auto & [name, value] : parsedContents)
+ if (name != "experimental-features" && name != "extra-experimental-features")
+ set(name, value);
}
void AbstractConfig::applyConfigFile(const Path & path)
@@ -203,12 +220,6 @@ void AbstractSetting::convertToArg(Args & args, const std::string & category)
}
template<typename T>
-bool BaseSetting<T>::isAppendable()
-{
- return false;
-}
-
-template<typename T>
void BaseSetting<T>::convertToArg(Args & args, const std::string & category)
{
args.addFlag({
@@ -231,9 +242,9 @@ void BaseSetting<T>::convertToArg(Args & args, const std::string & category)
});
}
-template<> void BaseSetting<std::string>::set(const std::string & str, bool append)
+template<> std::string BaseSetting<std::string>::parse(const std::string & str) const
{
- value = str;
+ return str;
}
template<> std::string BaseSetting<std::string>::to_string() const
@@ -242,11 +253,11 @@ template<> std::string BaseSetting<std::string>::to_string() const
}
template<typename T>
-void BaseSetting<T>::set(const std::string & str, bool append)
+T BaseSetting<T>::parse(const std::string & str) const
{
static_assert(std::is_integral<T>::value, "Integer required.");
if (auto n = string2Int<T>(str))
- value = *n;
+ return *n;
else
throw UsageError("setting '%s' has invalid value '%s'", name, str);
}
@@ -258,12 +269,12 @@ std::string BaseSetting<T>::to_string() const
return std::to_string(value);
}
-template<> void BaseSetting<bool>::set(const std::string & str, bool append)
+template<> bool BaseSetting<bool>::parse(const std::string & str) const
{
if (str == "true" || str == "yes" || str == "1")
- value = true;
+ return true;
else if (str == "false" || str == "no" || str == "0")
- value = false;
+ return false;
else
throw UsageError("Boolean setting '%s' has invalid value '%s'", name, str);
}
@@ -291,16 +302,15 @@ template<> void BaseSetting<bool>::convertToArg(Args & args, const std::string &
});
}
-template<> void BaseSetting<Strings>::set(const std::string & str, bool append)
+template<> Strings BaseSetting<Strings>::parse(const std::string & str) const
{
- auto ss = tokenizeString<Strings>(str);
- if (!append) value.clear();
- for (auto & s : ss) value.push_back(std::move(s));
+ return tokenizeString<Strings>(str);
}
-template<> bool BaseSetting<Strings>::isAppendable()
+template<> void BaseSetting<Strings>::appendOrSet(Strings && newValue, bool append)
{
- return true;
+ if (!append) value.clear();
+ for (auto && s : std::move(newValue)) value.push_back(std::move(s));
}
template<> std::string BaseSetting<Strings>::to_string() const
@@ -308,16 +318,16 @@ template<> std::string BaseSetting<Strings>::to_string() const
return concatStringsSep(" ", value);
}
-template<> void BaseSetting<StringSet>::set(const std::string & str, bool append)
+template<> StringSet BaseSetting<StringSet>::parse(const std::string & str) const
{
- if (!append) value.clear();
- for (auto & s : tokenizeString<StringSet>(str))
- value.insert(s);
+ return tokenizeString<StringSet>(str);
}
-template<> bool BaseSetting<StringSet>::isAppendable()
+template<> void BaseSetting<StringSet>::appendOrSet(StringSet && newValue, bool append)
{
- return true;
+ if (!append) value.clear();
+ for (auto && s : std::move(newValue))
+ value.insert(s);
}
template<> std::string BaseSetting<StringSet>::to_string() const
@@ -325,21 +335,24 @@ template<> std::string BaseSetting<StringSet>::to_string() const
return concatStringsSep(" ", value);
}
-template<> void BaseSetting<std::set<ExperimentalFeature>>::set(const std::string & str, bool append)
+template<> std::set<ExperimentalFeature> BaseSetting<std::set<ExperimentalFeature>>::parse(const std::string & str) const
{
- if (!append) value.clear();
+ std::set<ExperimentalFeature> res;
for (auto & s : tokenizeString<StringSet>(str)) {
auto thisXpFeature = parseExperimentalFeature(s);
if (thisXpFeature)
- value.insert(thisXpFeature.value());
+ res.insert(thisXpFeature.value());
else
warn("unknown experimental feature '%s'", s);
}
+ return res;
}
-template<> bool BaseSetting<std::set<ExperimentalFeature>>::isAppendable()
+template<> void BaseSetting<std::set<ExperimentalFeature>>::appendOrSet(std::set<ExperimentalFeature> && newValue, bool append)
{
- return true;
+ if (!append) value.clear();
+ for (auto && s : std::move(newValue))
+ value.insert(s);
}
template<> std::string BaseSetting<std::set<ExperimentalFeature>>::to_string() const
@@ -350,20 +363,23 @@ template<> std::string BaseSetting<std::set<ExperimentalFeature>>::to_string() c
return concatStringsSep(" ", stringifiedXpFeatures);
}
-template<> void BaseSetting<StringMap>::set(const std::string & str, bool append)
+template<> StringMap BaseSetting<StringMap>::parse(const std::string & str) const
{
- if (!append) value.clear();
+ StringMap res;
for (auto & s : tokenizeString<Strings>(str)) {
auto eq = s.find_first_of('=');
if (std::string::npos != eq)
- value.emplace(std::string(s, 0, eq), std::string(s, eq + 1));
+ res.emplace(std::string(s, 0, eq), std::string(s, eq + 1));
// else ignored
}
+ return res;
}
-template<> bool BaseSetting<StringMap>::isAppendable()
+template<> void BaseSetting<StringMap>::appendOrSet(StringMap && newValue, bool append)
{
- return true;
+ if (!append) value.clear();
+ for (auto && [k, v] : std::move(newValue))
+ value.emplace(std::move(k), std::move(v));
}
template<> std::string BaseSetting<StringMap>::to_string() const
@@ -387,15 +403,15 @@ template class BaseSetting<StringSet>;
template class BaseSetting<StringMap>;
template class BaseSetting<std::set<ExperimentalFeature>>;
-void PathSetting::set(const std::string & str, bool append)
+Path PathSetting::parse(const std::string & str) const
{
if (str == "") {
if (allowEmpty)
- value = "";
+ return "";
else
throw UsageError("setting '%s' cannot be empty", name);
} else
- value = canonPath(str);
+ return canonPath(str);
}
bool GlobalConfig::set(const std::string & name, const std::string & value)