1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-07-06 21:41:48 +02:00

Merge remote-tracking branch 'upstream/master' into path-info

This commit is contained in:
John Ericson 2023-04-07 20:39:04 -04:00
commit fd21f9d76e
211 changed files with 3961 additions and 1506 deletions

View file

@ -889,6 +889,67 @@ std::optional<BasicDerivation> Derivation::tryResolve(
return resolved;
}
void Derivation::checkInvariants(Store & store, const StorePath & drvPath) const
{
assert(drvPath.isDerivation());
std::string drvName(drvPath.name());
drvName = drvName.substr(0, drvName.size() - drvExtension.size());
if (drvName != name) {
throw Error("Derivation '%s' has name '%s' which does not match its path", store.printStorePath(drvPath), name);
}
auto envHasRightPath = [&](const StorePath & actual, const std::string & varName)
{
auto j = env.find(varName);
if (j == env.end() || store.parseStorePath(j->second) != actual)
throw Error("derivation '%s' has incorrect environment variable '%s', should be '%s'",
store.printStorePath(drvPath), varName, store.printStorePath(actual));
};
// Don't need the answer, but do this anyways to assert is proper
// combination. The code below is more general and naturally allows
// combinations that are currently prohibited.
type();
std::optional<DrvHash> hashesModulo;
for (auto & i : outputs) {
std::visit(overloaded {
[&](const DerivationOutput::InputAddressed & doia) {
if (!hashesModulo) {
// somewhat expensive so we do lazily
hashesModulo = hashDerivationModulo(store, *this, true);
}
auto currentOutputHash = get(hashesModulo->hashes, i.first);
if (!currentOutputHash)
throw Error("derivation '%s' has unexpected output '%s' (local-store / hashesModulo) named '%s'",
store.printStorePath(drvPath), store.printStorePath(doia.path), i.first);
StorePath recomputed = store.makeOutputPath(i.first, *currentOutputHash, drvName);
if (doia.path != recomputed)
throw Error("derivation '%s' has incorrect output '%s', should be '%s'",
store.printStorePath(drvPath), store.printStorePath(doia.path), store.printStorePath(recomputed));
envHasRightPath(doia.path, i.first);
},
[&](const DerivationOutput::CAFixed & dof) {
StorePath path = store.makeFixedOutputPath(drvName, { dof.hash, {} });
envHasRightPath(path, i.first);
},
[&](const DerivationOutput::CAFloating &) {
/* Nothing to check */
},
[&](const DerivationOutput::Deferred &) {
/* Nothing to check */
},
[&](const DerivationOutput::Impure &) {
/* Nothing to check */
},
}, i.second.raw());
}
}
const Hash impureOutputHash = hashString(htSHA256, "impure");
nlohmann::json DerivationOutput::toJSON(
@ -916,10 +977,79 @@ nlohmann::json DerivationOutput::toJSON(
return res;
}
DerivationOutput DerivationOutput::fromJSON(
const Store & store, std::string_view drvName, std::string_view outputName,
const nlohmann::json & _json)
{
std::set<std::string_view> keys;
auto json = (std::map<std::string, nlohmann::json>) _json;
for (const auto & [key, _] : json)
keys.insert(key);
auto methodAlgo = [&]() -> std::pair<FileIngestionMethod, HashType> {
std::string hashAlgo = json["hashAlgo"];
auto method = FileIngestionMethod::Flat;
if (hashAlgo.substr(0, 2) == "r:") {
method = FileIngestionMethod::Recursive;
hashAlgo = hashAlgo.substr(2);
}
auto hashType = parseHashType(hashAlgo);
return { method, hashType };
};
if (keys == (std::set<std::string_view> { "path" })) {
return DerivationOutput::InputAddressed {
.path = store.parseStorePath((std::string) json["path"]),
};
}
else if (keys == (std::set<std::string_view> { "path", "hashAlgo", "hash" })) {
auto [method, hashType] = methodAlgo();
auto dof = DerivationOutput::CAFixed {
.hash = {
.method = method,
.hash = Hash::parseNonSRIUnprefixed((std::string) json["hash"], hashType),
},
};
if (dof.path(store, drvName, outputName) != store.parseStorePath((std::string) json["path"]))
throw Error("Path doesn't match derivation output");
return dof;
}
else if (keys == (std::set<std::string_view> { "hashAlgo" })) {
auto [method, hashType] = methodAlgo();
return DerivationOutput::CAFloating {
.method = method,
.hashType = hashType,
};
}
else if (keys == (std::set<std::string_view> { })) {
return DerivationOutput::Deferred {};
}
else if (keys == (std::set<std::string_view> { "hashAlgo", "impure" })) {
auto [method, hashType] = methodAlgo();
return DerivationOutput::Impure {
.method = method,
.hashType = hashType,
};
}
else {
throw Error("invalid JSON for derivation output");
}
}
nlohmann::json Derivation::toJSON(const Store & store) const
{
nlohmann::json res = nlohmann::json::object();
res["name"] = name;
{
nlohmann::json & outputsObj = res["outputs"];
outputsObj = nlohmann::json::object();
@ -950,4 +1080,43 @@ nlohmann::json Derivation::toJSON(const Store & store) const
return res;
}
Derivation Derivation::fromJSON(
const Store & store,
const nlohmann::json & json)
{
Derivation res;
res.name = json["name"];
{
auto & outputsObj = json["outputs"];
for (auto & [outputName, output] : outputsObj.items()) {
res.outputs.insert_or_assign(
outputName,
DerivationOutput::fromJSON(store, res.name, outputName, output));
}
}
{
auto & inputsList = json["inputSrcs"];
for (auto & input : inputsList)
res.inputSrcs.insert(store.parseStorePath(static_cast<const std::string &>(input)));
}
{
auto & inputDrvsObj = json["inputDrvs"];
for (auto & [inputDrvPath, inputOutputs] : inputDrvsObj.items())
res.inputDrvs[store.parseStorePath(inputDrvPath)] =
static_cast<const StringSet &>(inputOutputs);
}
res.platform = json["system"];
res.builder = json["builder"];
res.args = json["args"];
res.env = json["env"];
return res;
}
}