1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-16 07:22:43 +01:00

Store StructuredAttrs directly in Derivation

Instead of parsing a structured attrs at some later point, we parsed it
right away when parsing the A-Term format, and likewise serialize it to
`__json = <JSON dump>` when serializing a derivation to A-Term.

The JSON format can directly contain the JSON structured attrs without
so encoding it, so we just do that.
This commit is contained in:
John Ericson 2025-05-25 20:01:20 -04:00
parent b062730665
commit 8652b6b417
16 changed files with 177 additions and 109 deletions

View file

@ -452,6 +452,7 @@ Derivation parseDerivation(
expect(str, ")");
drv.env.insert_or_assign(std::move(name), std::move(value));
}
drv.structuredAttrs = StructuredAttrs::tryExtract(drv.env);
expect(str, ")");
return drv;
@ -685,16 +686,28 @@ std::string Derivation::unparse(
s += ",[";
first = true;
for (auto & i : env) {
if (first)
first = false;
else
auto unparseEnv = [&](const StringPairs atermEnv) {
for (auto & i : atermEnv) {
if (first)
first = false;
else
s += ',';
s += '(';
printString(s, i.first);
s += ',';
s += '(';
printString(s, i.first);
s += ',';
printString(s, maskOutputs && outputs.count(i.first) ? "" : i.second);
s += ')';
printString(s, maskOutputs && outputs.count(i.first) ? "" : i.second);
s += ')';
}
};
StructuredAttrs::checkKeyNotInUse(env);
if (structuredAttrs) {
StringPairs scratch = env;
scratch.insert(structuredAttrs->unparse());
unparseEnv(scratch);
} else {
unparseEnv(env);
}
s += "])";
@ -948,6 +961,7 @@ Source & readDerivation(Source & in, const StoreDirConfig & store, BasicDerivati
auto value = readString(in);
drv.env[key] = value;
}
drv.structuredAttrs = StructuredAttrs::tryExtract(drv.env);
return in;
}
@ -983,9 +997,21 @@ void writeDerivation(Sink & out, const StoreDirConfig & store, const BasicDeriva
}
CommonProto::write(store, CommonProto::WriteConn{.to = out}, drv.inputSrcs);
out << drv.platform << drv.builder << drv.args;
out << drv.env.size();
for (auto & i : drv.env)
out << i.first << i.second;
auto writeEnv = [&](const StringPairs atermEnv) {
out << atermEnv.size();
for (auto & [k, v] : atermEnv)
out << k << v;
};
StructuredAttrs::checkKeyNotInUse(drv.env);
if (drv.structuredAttrs) {
StringPairs scratch = drv.env;
scratch.insert(drv.structuredAttrs->unparse());
writeEnv(scratch);
} else {
writeEnv(drv.env);
}
}
std::string hashPlaceholder(const OutputNameView outputName)
@ -1017,6 +1043,17 @@ void BasicDerivation::applyRewrites(const StringMap & rewrites)
newEnv.emplace(envName, envValue);
}
env = std::move(newEnv);
if (structuredAttrs) {
// TODO rewrite the JSON AST properly, rather than dump parse round trip.
auto [k, jsonS] = structuredAttrs->unparse();
jsonS = rewriteStrings(jsonS, rewrites);
StringPairs newEnv;
newEnv.insert(std::pair{k, std::move(jsonS)});
auto newStructuredAttrs = StructuredAttrs::tryExtract(newEnv);
assert(newStructuredAttrs);
structuredAttrs = std::move(*newStructuredAttrs);
}
}
static void rewriteDerivation(Store & store, BasicDerivation & drv, const StringMap & rewrites)
@ -1338,10 +1375,8 @@ nlohmann::json Derivation::toJSON(const StoreDirConfig & store) const
res["args"] = args;
res["env"] = env;
if (auto it = env.find("__json"); it != env.end()) {
res["env"].erase("__json");
res["structuredAttrs"] = nlohmann::json::parse(it->second);
}
if (structuredAttrs)
res["structuredAttrs"] = structuredAttrs->structuredAttrs;
return res;
}
@ -1411,7 +1446,7 @@ Derivation Derivation::fromJSON(
}
if (auto structuredAttrs = get(json, "structuredAttrs"))
res.env.insert_or_assign("__json", structuredAttrs->dump());
res.structuredAttrs = StructuredAttrs{*structuredAttrs};
return res;
}