Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 43 additions & 42 deletions src/libstore/derivations.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1425,12 +1425,8 @@ void adl_serializer<DerivationOutput>::to_json(json & res, const DerivationOutpu
DerivationOutput
adl_serializer<DerivationOutput>::from_json(const json & _json, const ExperimentalFeatureSettings & xpSettings)
{
std::set<std::string_view> keys;
auto & json = getObject(_json);

for (const auto & [key, _] : json)
keys.insert(key);

auto methodAlgo = [&]() -> std::pair<ContentAddressMethod, HashAlgorithm> {
ContentAddressMethod method = ContentAddressMethod::parse(getString(valueAt(json, "method")));
if (method == ContentAddressMethod::Raw::Text)
Expand All @@ -1440,52 +1436,57 @@ adl_serializer<DerivationOutput>::from_json(const json & _json, const Experiment
return {std::move(method), std::move(hashAlgo)};
};

if (keys == (std::set<std::string_view>{"path"})) {
return DerivationOutput::InputAddressed{
.path = valueAt(json, "path"),
};
}
switch (json.size()) {
case 0:
return DerivationOutput::Deferred{};
case 1:
if (auto * path = optionalValueAt(json, "path"))
return DerivationOutput::InputAddressed{
.path = *path,
};
break;
case 2: {
const bool hasMethod = optionalValueAt(json, "method");

else if (keys == (std::set<std::string_view>{"method", "hash"})) {
auto dof = DerivationOutput::CAFixed{
.ca = static_cast<ContentAddress>(_json),
};
if (dof.ca.method == ContentAddressMethod::Raw::Text)
xpSettings.require(Xp::DynamicDerivations, "text-hashed derivation output in JSON");
/* We no longer produce this (denormalized) field (for the
reasons described above), so we don't need to check it. */
if (hasMethod && optionalValueAt(json, "hash")) {
auto dof = DerivationOutput::CAFixed{
.ca = static_cast<ContentAddress>(_json),
};
if (dof.ca.method == ContentAddressMethod::Raw::Text)
xpSettings.require(Xp::DynamicDerivations, "text-hashed derivation output in JSON");
/* We no longer produce this (denormalized) field (for the
reasons described above), so we don't need to check it. */
#if 0
if (dof.path(store, drvName, outputName) != static_cast<StorePath>(valueAt(json, "path")))
throw Error("Path doesn't match derivation output");
if (dof.path(store, drvName, outputName) != static_cast<StorePath>(valueAt(json, "path")))
throw Error("Path doesn't match derivation output");
#endif
return dof;
}
return dof;
}

else if (keys == (std::set<std::string_view>{"method", "hashAlgo"})) {
xpSettings.require(Xp::CaDerivations);
auto [method, hashAlgo] = methodAlgo();
return DerivationOutput::CAFloating{
.method = std::move(method),
.hashAlgo = std::move(hashAlgo),
};
}
if (hasMethod && optionalValueAt(json, "hashAlgo")) {
xpSettings.require(Xp::CaDerivations);
auto [method, hashAlgo] = methodAlgo();
return DerivationOutput::CAFloating{
.method = std::move(method),
.hashAlgo = std::move(hashAlgo),
};
}

else if (keys == (std::set<std::string_view>{})) {
return DerivationOutput::Deferred{};
break;
}

else if (keys == (std::set<std::string_view>{"method", "hashAlgo", "impure"})) {
xpSettings.require(Xp::ImpureDerivations);
auto [method, hashAlgo] = methodAlgo();
return DerivationOutput::Impure{
.method = std::move(method),
.hashAlgo = hashAlgo,
};
case 3:
if (optionalValueAt(json, "method") && optionalValueAt(json, "hashAlgo") && optionalValueAt(json, "impure")) {
xpSettings.require(Xp::ImpureDerivations);
auto [method, hashAlgo] = methodAlgo();
return DerivationOutput::Impure{
.method = std::move(method),
.hashAlgo = hashAlgo,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should presumably also be std::move(hashAlgo). I realise this is unrelated to the main change of this PR

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's an enum, so that's pointless.

};
}
break;
}

else {
throw Error("invalid JSON for derivation output");
}
throw Error("invalid JSON for derivation output");
}

void adl_serializer<Derivation>::to_json(json & res, const Derivation & d)
Expand Down
Loading