diff options
Diffstat (limited to 'src/libutil/config.cc')
-rw-r--r-- | src/libutil/config.cc | 94 |
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) |