diff --git a/src/libstore/derivation-options.cc b/src/libstore/derivation-options.cc index f4faca3915c..7bb2ffb2496 100644 --- a/src/libstore/derivation-options.cc +++ b/src/libstore/derivation-options.cc @@ -21,76 +21,53 @@ static std::optional getStringAttr(const StringMap & env, const StructuredAttrs * parsed, const std::string & name) { if (parsed) { - auto i = parsed->structuredAttrs.find(name); - if (i == parsed->structuredAttrs.end()) - return {}; - else { - if (!i->second.is_string()) - throw Error("attribute '%s' of must be a string", name); - return i->second.get(); - } + if (auto * i = get(parsed->structuredAttrs, name)) + try { + return getString(*i); + } catch (Error & e) { + e.addTrace({}, "while parsing attribute \"%s\"", name); + throw; + } } else { - auto i = env.find(name); - if (i == env.end()) - return {}; - else - return i->second; + if (auto * i = get(env, name)) + return *i; } + return {}; } static bool getBoolAttr(const StringMap & env, const StructuredAttrs * parsed, const std::string & name, bool def) { if (parsed) { - auto i = parsed->structuredAttrs.find(name); - if (i == parsed->structuredAttrs.end()) - return def; - else { - if (!i->second.is_boolean()) - throw Error("attribute '%s' must be a Boolean", name); - return i->second.get(); - } + if (auto * i = get(parsed->structuredAttrs, name)) + try { + return getBoolean(*i); + } catch (Error & e) { + e.addTrace({}, "while parsing attribute \"%s\"", name); + throw; + } } else { - auto i = env.find(name); - if (i == env.end()) - return def; - else - return i->second == "1"; + if (auto * i = get(env, name)) + return *i == "1"; } + return def; } -static std::optional -getStringsAttr(const StringMap & env, const StructuredAttrs * parsed, const std::string & name) +static std::optional +getStringSetAttr(const StringMap & env, const StructuredAttrs * parsed, const std::string & name) { if (parsed) { - auto i = parsed->structuredAttrs.find(name); - if (i == parsed->structuredAttrs.end()) - return {}; - else { - if (!i->second.is_array()) - throw Error("attribute '%s' must be a list of strings", name); - auto & a = getArray(i->second); - Strings res; - for (auto j = a.begin(); j != a.end(); ++j) { - if (!j->is_string()) - throw Error("attribute '%s' must be a list of strings", name); - res.push_back(j->get()); + if (auto * i = get(parsed->structuredAttrs, name)) + try { + return getStringSet(*i); + } catch (Error & e) { + e.addTrace({}, "while parsing attribute \"%s\"", name); + throw; } - return res; - } } else { - auto i = env.find(name); - if (i == env.end()) - return {}; - else - return tokenizeString(i->second); + if (auto * i = get(env, name)) + return tokenizeString(*i); } -} - -static std::optional -getStringSetAttr(const StringMap & env, const StructuredAttrs * parsed, const std::string & name) -{ - auto ss = getStringsAttr(env, parsed, name); - return ss ? (std::optional{StringSet{ss->begin(), ss->end()}}) : (std::optional{}); + return {}; } template @@ -233,26 +210,21 @@ DerivationOptions derivationOptionsFromStructuredAttrs( std::map> res; if (auto * outputChecks = get(structuredAttrs, "outputChecks")) { for (auto & [outputName, output_] : getObject(*outputChecks)) { - OutputChecks checks; - auto & output = getObject(output_); - if (auto maxSize = get(output, "maxSize")) - checks.maxSize = maxSize->get(); - - if (auto maxClosureSize = get(output, "maxClosureSize")) - checks.maxClosureSize = maxClosureSize->get(); - auto get_ = [&](const std::string & name) -> std::optional>> { - if (auto i = get(output, name)) { - std::set> res; - for (auto j = i->begin(); j != i->end(); ++j) { - if (!j->is_string()) - throw Error("attribute '%s' must be a list of strings", name); - res.insert(parseRef(j->get())); + if (auto * i = get(output, name)) { + try { + std::set> res; + for (auto & s : getStringList(*i)) + res.insert(parseRef(s)); + return res; + } catch (Error & e) { + e.addTrace( + {}, "while parsing attribute 'outputChecks.\"%s\".%s'", outputName, name); + throw; } - return res; } return {}; }; @@ -260,18 +232,8 @@ DerivationOptions derivationOptionsFromStructuredAttrs( res.insert_or_assign( outputName, OutputChecks{ - .maxSize = [&]() -> std::optional { - if (auto maxSize = get(output, "maxSize")) - return maxSize->get(); - else - return std::nullopt; - }(), - .maxClosureSize = [&]() -> std::optional { - if (auto maxClosureSize = get(output, "maxClosureSize")) - return maxClosureSize->get(); - else - return std::nullopt; - }(), + .maxSize = ptrToOwned(get(output, "maxSize")), + .maxClosureSize = ptrToOwned(get(output, "maxClosureSize")), .allowedReferences = get_("allowedReferences"), .disallowedReferences = get_("disallowedReferences").value_or(std::set>{}), @@ -307,13 +269,13 @@ DerivationOptions derivationOptionsFromStructuredAttrs( std::map res; if (parsed) { - auto & structuredAttrs = parsed->structuredAttrs; - - if (auto * udr = get(structuredAttrs, "unsafeDiscardReferences")) { - for (auto & [outputName, output] : getObject(*udr)) { - if (!output.is_boolean()) - throw Error("attribute 'unsafeDiscardReferences.\"%s\"' must be a Boolean", outputName); - res.insert_or_assign(outputName, output.get()); + if (auto * udr = get(parsed->structuredAttrs, "unsafeDiscardReferences")) { + try { + for (auto & [outputName, output] : getObject(*udr)) + res.insert_or_assign(outputName, getBoolean(output)); + } catch (Error & e) { + e.addTrace({}, "while parsing attribute 'unsafeDiscardReferences'"); + throw; } } } @@ -340,7 +302,7 @@ DerivationOptions derivationOptionsFromStructuredAttrs( std::map> ret; if (parsed) { - auto * e = optionalValueAt(parsed->structuredAttrs, "exportReferencesGraph"); + auto * e = get(parsed->structuredAttrs, "exportReferencesGraph"); if (!e) return ret; if (!e->is_object()) { @@ -595,8 +557,8 @@ DerivationOptions adl_serializer OutputChecksVariant { auto outputChecks = getObject(valueAt(json, "outputChecks")); - auto forAllOutputsOpt = optionalValueAt(outputChecks, "forAllOutputs"); - auto perOutputOpt = optionalValueAt(outputChecks, "perOutput"); + auto forAllOutputsOpt = get(outputChecks, "forAllOutputs"); + auto perOutputOpt = get(outputChecks, "perOutput"); if (forAllOutputsOpt && !perOutputOpt) { return static_cast>(*forAllOutputsOpt); diff --git a/src/libutil/include/nix/util/json-utils.hh b/src/libutil/include/nix/util/json-utils.hh index ec513ca25d6..555c982cc6e 100644 --- a/src/libutil/include/nix/util/json-utils.hh +++ b/src/libutil/include/nix/util/json-utils.hh @@ -75,6 +75,15 @@ Strings getStringList(const nlohmann::json & value); StringMap getStringMap(const nlohmann::json & value); StringSet getStringSet(const nlohmann::json & value); +template +static inline std::optional ptrToOwned(const nlohmann::json * ptr) +{ + if (ptr) + return std::optional{*ptr}; + else + return std::nullopt; +} + } // namespace nix namespace nlohmann { @@ -114,13 +123,4 @@ struct adl_serializer> } }; -template -static inline std::optional ptrToOwned(const json * ptr) -{ - if (ptr) - return std::optional{*ptr}; - else - return std::nullopt; -} - } // namespace nlohmann