1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-09 12:06:01 +01:00

Create EvalState::coerceToDerivedPath

This gives us some round trips to test.

`EvalState::coerceToDerivedPathUnchecked` is a factored out helper just
for unit testing.
This commit is contained in:
John Ericson 2023-05-10 19:25:52 -04:00
parent 8e1a990268
commit 5a23b80b0a
3 changed files with 162 additions and 0 deletions

View file

@ -2318,6 +2318,80 @@ StorePath EvalState::coerceToStorePath(const PosIdx pos, Value & v, NixStringCon
}
std::pair<DerivedPath, std::string_view> EvalState::coerceToDerivedPathUnchecked(const PosIdx pos, Value & v, std::string_view errorCtx)
{
NixStringContext context;
auto s = forceString(v, context, pos, errorCtx);
auto csize = context.size();
if (csize != 1)
error(
"string '%s' has %d entries in its context. It should only have exactly one entry",
s, csize)
.withTrace(pos, errorCtx).debugThrow<EvalError>();
auto derivedPath = std::visit(overloaded {
[&](NixStringContextElem::Opaque && o) -> DerivedPath {
return DerivedPath::Opaque {
.path = std::move(o.path),
};
},
[&](NixStringContextElem::DrvDeep &&) -> DerivedPath {
error(
"string '%s' has a context which refers to a complete source and binary closure. This is not supported at this time",
s).withTrace(pos, errorCtx).debugThrow<EvalError>();
},
[&](NixStringContextElem::Built && b) -> DerivedPath {
return DerivedPath::Built {
.drvPath = std::move(b.drvPath),
.outputs = OutputsSpec::Names { std::move(b.output) },
};
},
}, ((NixStringContextElem &&) *context.begin()).raw());
return {
std::move(derivedPath),
std::move(s),
};
}
DerivedPath EvalState::coerceToDerivedPath(const PosIdx pos, Value & v, std::string_view errorCtx)
{
auto [derivedPath, s_] = coerceToDerivedPathUnchecked(pos, v, errorCtx);
auto s = s_;
std::visit(overloaded {
[&](const DerivedPath::Opaque & o) {
auto sExpected = store->printStorePath(o.path);
if (s != sExpected)
error(
"path string '%s' has context with the different path '%s'",
s, sExpected)
.withTrace(pos, errorCtx).debugThrow<EvalError>();
},
[&](const DerivedPath::Built & b) {
// TODO need derived path with single output to make this
// total. Will add as part of RFC 92 work and then this is
// cleaned up.
auto output = *std::get<OutputsSpec::Names>(b.outputs).begin();
auto drv = store->readDerivation(b.drvPath);
auto i = drv.outputs.find(output);
if (i == drv.outputs.end())
throw Error("derivation '%s' does not have output '%s'", store->printStorePath(b.drvPath), output);
auto optOutputPath = i->second.path(*store, drv.name, output);
// This is testing for the case of CA derivations
auto sExpected = optOutputPath
? store->printStorePath(*optOutputPath)
: downstreamPlaceholder(*store, b.drvPath, output);
if (s != sExpected)
error(
"string '%s' has context with the output '%s' from derivation '%s', but the string is not the right placeholder for this derivation output. It should be '%s'",
s, output, store->printStorePath(b.drvPath), sExpected)
.withTrace(pos, errorCtx).debugThrow<EvalError>();
}
}, derivedPath.raw());
return derivedPath;
}
bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_view errorCtx)
{
forceValue(v1, noPos);