Compare commits
2 Commits
cloneable-
...
eval-coerc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97d29276b9 | ||
|
|
2545b6716a |
@@ -43,7 +43,7 @@ RC_GTEST_FIXTURE_PROP(
|
||||
|
||||
auto * v = state.allocValue();
|
||||
state.mkOutputString(*v, b, std::nullopt, mockXpSettings);
|
||||
auto [d, _] = state.coerceToSingleDerivedPathUnchecked(noPos, *v, "", mockXpSettings);
|
||||
auto d = state.coerceToSingleDerivedPath(noPos, *v, "", mockXpSettings, true);
|
||||
RC_ASSERT(SingleDerivedPath{b} == d);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ RC_GTEST_FIXTURE_PROP(
|
||||
|
||||
auto * v = state.allocValue();
|
||||
state.mkOutputString(*v, b, outPath, mockXpSettings);
|
||||
auto [d, _] = state.coerceToSingleDerivedPathUnchecked(noPos, *v, "", mockXpSettings);
|
||||
auto d = state.coerceToSingleDerivedPath(noPos, *v, "", mockXpSettings, true);
|
||||
RC_ASSERT(SingleDerivedPath{b} == d);
|
||||
}
|
||||
|
||||
|
||||
@@ -2406,7 +2406,8 @@ BackedStringView EvalState::coerceToString(
|
||||
std::string_view errorCtx,
|
||||
bool coerceMore,
|
||||
bool copyToStore,
|
||||
bool canonicalizePath)
|
||||
bool canonicalizePath,
|
||||
bool strict)
|
||||
{
|
||||
auto _level = addCallDepth(pos);
|
||||
|
||||
@@ -2433,14 +2434,28 @@ BackedStringView EvalState::coerceToString(
|
||||
auto maybeString = tryAttrsToString(pos, v, context, coerceMore, copyToStore);
|
||||
if (maybeString)
|
||||
return std::move(*maybeString);
|
||||
auto i = v.attrs()->get(s.outPath);
|
||||
if (!i) {
|
||||
auto outPathAttr = v.attrs()->get(s.outPath);
|
||||
if (!outPathAttr) {
|
||||
error<TypeError>(
|
||||
"cannot coerce %1% to a string: %2%", showType(v), ValuePrinter(*this, v, errorPrintOptions))
|
||||
.withTrace(pos, errorCtx)
|
||||
.debugThrow();
|
||||
}
|
||||
return coerceToString(pos, *i->value, context, errorCtx, coerceMore, copyToStore, canonicalizePath);
|
||||
try {
|
||||
auto derivedPath = coerceToSingleDerivedPath(pos, v, errorCtx);
|
||||
auto result = mkSingleDerivedPathStringRaw(derivedPath);
|
||||
context.insert(
|
||||
std::visit([](auto && o) -> NixStringContextElem { return std::move(o); }, std::move(derivedPath)));
|
||||
return result;
|
||||
} catch (Error & e) {
|
||||
if (strict)
|
||||
throw;
|
||||
auto info = e.info();
|
||||
info.msg = HintFmt("in a future version of Nix this will be an error: %s", Uncolored(info.msg.str()));
|
||||
logWarning(info);
|
||||
return coerceToString(
|
||||
pos, *outPathAttr->value, context, errorCtx, coerceMore, copyToStore, canonicalizePath, strict);
|
||||
}
|
||||
}
|
||||
|
||||
if (v.type() == nExternal) {
|
||||
@@ -2478,7 +2493,8 @@ BackedStringView EvalState::coerceToString(
|
||||
"while evaluating one element of the list",
|
||||
coerceMore,
|
||||
copyToStore,
|
||||
canonicalizePath);
|
||||
canonicalizePath,
|
||||
strict);
|
||||
} catch (Error & e) {
|
||||
e.addTrace(positions[pos], errorCtx);
|
||||
throw;
|
||||
@@ -2565,63 +2581,131 @@ EvalState::coerceToStorePath(const PosIdx pos, Value & v, NixStringContext & con
|
||||
error<EvalError>("path '%1%' is not in the Nix store", path).withTrace(pos, errorCtx).debugThrow();
|
||||
}
|
||||
|
||||
std::pair<SingleDerivedPath, std::string_view> EvalState::coerceToSingleDerivedPathUnchecked(
|
||||
const PosIdx pos, Value & v, std::string_view errorCtx, const ExperimentalFeatureSettings & xpSettings)
|
||||
SingleDerivedPath EvalState::coerceToSingleDerivedPath(
|
||||
const PosIdx pos,
|
||||
Value & v,
|
||||
std::string_view errorCtx,
|
||||
const ExperimentalFeatureSettings & xpSettings,
|
||||
bool skipStringValidation)
|
||||
{
|
||||
NixStringContext context;
|
||||
auto s = forceString(v, context, pos, errorCtx, xpSettings);
|
||||
auto csize = context.size();
|
||||
if (csize != 1)
|
||||
error<EvalError>("string '%s' has %d entries in its context. It should only have exactly one entry", s, csize)
|
||||
.withTrace(pos, errorCtx)
|
||||
.debugThrow();
|
||||
auto derivedPath = std::visit(
|
||||
overloaded{
|
||||
[&](NixStringContextElem::Opaque && o) -> SingleDerivedPath { return std::move(o); },
|
||||
[&](NixStringContextElem::DrvDeep &&) -> SingleDerivedPath {
|
||||
error<EvalError>(
|
||||
"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();
|
||||
},
|
||||
[&](NixStringContextElem::Built && b) -> SingleDerivedPath { return std::move(b); },
|
||||
},
|
||||
((NixStringContextElem &&) *context.begin()).raw);
|
||||
return {
|
||||
std::move(derivedPath),
|
||||
std::move(s),
|
||||
};
|
||||
}
|
||||
forceValue(v, pos);
|
||||
|
||||
SingleDerivedPath EvalState::coerceToSingleDerivedPath(const PosIdx pos, Value & v, std::string_view errorCtx)
|
||||
{
|
||||
auto [derivedPath, s_] = coerceToSingleDerivedPathUnchecked(pos, v, errorCtx);
|
||||
auto s = s_;
|
||||
auto sExpected = mkSingleDerivedPathStringRaw(derivedPath);
|
||||
if (s != sExpected) {
|
||||
/* `std::visit` is used here just to provide a more precise
|
||||
error message. */
|
||||
std::visit(
|
||||
switch (v.type()) {
|
||||
case nAttrs: {
|
||||
if (!isDerivation(v)) {
|
||||
error<TypeError>(
|
||||
"cannot coerce a set that is not a package to a single derived path: %1%",
|
||||
ValuePrinter(*this, v, errorPrintOptions))
|
||||
.withTrace(pos, errorCtx)
|
||||
.debugThrow();
|
||||
}
|
||||
|
||||
auto outPathAttr = v.attrs()->get(s.outPath);
|
||||
if (!outPathAttr) {
|
||||
error<TypeError>(
|
||||
"cannot coerce %1% to a single derived path: no 'outPath' attribute: %2%",
|
||||
showType(v),
|
||||
ValuePrinter(*this, v, errorPrintOptions))
|
||||
.withTrace(pos, errorCtx)
|
||||
.debugThrow();
|
||||
}
|
||||
|
||||
auto outPathDerivedPath =
|
||||
coerceToSingleDerivedPath(pos, *outPathAttr->value, errorCtx, xpSettings, skipStringValidation);
|
||||
|
||||
auto drvPathAttr = v.attrs()->get(s.drvPath);
|
||||
if (drvPathAttr) {
|
||||
auto drvPathDerivedPath =
|
||||
coerceToSingleDerivedPath(pos, *drvPathAttr->value, errorCtx, xpSettings, skipStringValidation);
|
||||
|
||||
std::visit(
|
||||
overloaded{
|
||||
[&](const SingleDerivedPath::Built & built) {
|
||||
if (*built.drvPath != drvPathDerivedPath) {
|
||||
error<EvalError>(
|
||||
"relative outPath '%s' does not refer to drvPath '%s'",
|
||||
outPathDerivedPath.to_string(*store),
|
||||
drvPathDerivedPath.to_string(*store))
|
||||
.withTrace(pos, errorCtx)
|
||||
.debugThrow();
|
||||
}
|
||||
},
|
||||
[&](const SingleDerivedPath::Opaque &) {
|
||||
error<EvalError>(
|
||||
"relative outPath '%s' does not refer to drvPath '%s'",
|
||||
outPathDerivedPath.to_string(*store),
|
||||
drvPathDerivedPath.to_string(*store))
|
||||
.withTrace(pos, errorCtx)
|
||||
.debugThrow();
|
||||
},
|
||||
},
|
||||
outPathDerivedPath.raw());
|
||||
}
|
||||
|
||||
return outPathDerivedPath;
|
||||
}
|
||||
|
||||
case nString: {
|
||||
auto s = v.string_view();
|
||||
NixStringContext context;
|
||||
copyContext(v, context, xpSettings);
|
||||
auto csize = context.size();
|
||||
if (csize != 1)
|
||||
error<EvalError>(
|
||||
"string '%s' has %d entries in its context. It should only have exactly one entry", s, csize)
|
||||
.withTrace(pos, errorCtx)
|
||||
.debugThrow();
|
||||
auto derivedPath = std::visit(
|
||||
overloaded{
|
||||
[&](const SingleDerivedPath::Opaque & o) {
|
||||
error<EvalError>("path string '%s' has context with the different path '%s'", s, sExpected)
|
||||
[&](NixStringContextElem::Opaque && o) -> SingleDerivedPath { return std::move(o); },
|
||||
[&](NixStringContextElem::DrvDeep &&) -> SingleDerivedPath {
|
||||
error<EvalError>(
|
||||
"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();
|
||||
},
|
||||
[&](const SingleDerivedPath::Built & b) {
|
||||
error<EvalError>(
|
||||
"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,
|
||||
b.output,
|
||||
b.drvPath->to_string(*store),
|
||||
sExpected)
|
||||
.withTrace(pos, errorCtx)
|
||||
.debugThrow();
|
||||
}},
|
||||
derivedPath.raw());
|
||||
[&](NixStringContextElem::Built && b) -> SingleDerivedPath { return std::move(b); },
|
||||
},
|
||||
((NixStringContextElem &&) *context.begin()).raw);
|
||||
|
||||
if (!skipStringValidation) {
|
||||
auto sExpected = mkSingleDerivedPathStringRaw(derivedPath);
|
||||
if (s != sExpected) {
|
||||
/* `std::visit` is used here just to provide a more precise
|
||||
error message. */
|
||||
std::visit(
|
||||
overloaded{
|
||||
[&](const SingleDerivedPath::Opaque & o) {
|
||||
error<EvalError>("path string '%s' has context with the different path '%s'", s, sExpected)
|
||||
.withTrace(pos, errorCtx)
|
||||
.debugThrow();
|
||||
},
|
||||
[&](const SingleDerivedPath::Built & b) {
|
||||
error<EvalError>(
|
||||
"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,
|
||||
b.output,
|
||||
b.drvPath->to_string(*store),
|
||||
sExpected)
|
||||
.withTrace(pos, errorCtx)
|
||||
.debugThrow();
|
||||
}},
|
||||
derivedPath.raw());
|
||||
}
|
||||
}
|
||||
|
||||
return derivedPath;
|
||||
}
|
||||
|
||||
default:
|
||||
error<TypeError>(
|
||||
"cannot coerce %1% to a single derived path: %2%", showType(v), ValuePrinter(*this, v, errorPrintOptions))
|
||||
.withTrace(pos, errorCtx)
|
||||
.debugThrow();
|
||||
}
|
||||
return derivedPath;
|
||||
}
|
||||
|
||||
// NOTE: This implementation must match eqValues!
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "nix/expr/get-drvs.hh"
|
||||
#include "nix/expr/eval-inline.hh"
|
||||
#include "nix/store/derived-path.hh"
|
||||
#include "nix/store/derivations.hh"
|
||||
#include "nix/store/store-api.hh"
|
||||
#include "nix/store/path-with-outputs.hh"
|
||||
@@ -21,13 +22,13 @@ PackageInfo::PackageInfo(EvalState & state, ref<Store> store, const std::string
|
||||
, attrs(nullptr)
|
||||
, attrPath("")
|
||||
{
|
||||
auto [drvPath, selectedOutputs] = parsePathWithOutputs(*store, drvPathWithOutputs);
|
||||
auto [drvStorePath, selectedOutputs] = parsePathWithOutputs(*store, drvPathWithOutputs);
|
||||
|
||||
this->drvPath = drvPath;
|
||||
this->drvPath = {{Path{SingleDerivedPath::Opaque{drvStorePath}, drvStorePath}}};
|
||||
|
||||
auto drv = store->derivationFromPath(drvPath);
|
||||
auto drv = store->derivationFromPath(drvStorePath);
|
||||
|
||||
name = drvPath.name();
|
||||
name = drvStorePath.name();
|
||||
|
||||
if (selectedOutputs.size() > 1)
|
||||
throw Error("building more than one derivation output is not supported, in '%s'", drvPathWithOutputs);
|
||||
@@ -36,10 +37,18 @@ PackageInfo::PackageInfo(EvalState & state, ref<Store> store, const std::string
|
||||
|
||||
auto i = drv.outputs.find(outputName);
|
||||
if (i == drv.outputs.end())
|
||||
throw Error("derivation '%s' does not have output '%s'", store->printStorePath(drvPath), outputName);
|
||||
auto & [outputName, output] = *i;
|
||||
throw Error("derivation '%s' does not have output '%s'", store->printStorePath(drvStorePath), outputName);
|
||||
auto & [outputName_, output] = *i;
|
||||
|
||||
outPath = {output.path(*store, drv.name, outputName)};
|
||||
auto outStorePath = output.path(*store, drv.name, outputName_);
|
||||
if (outStorePath) {
|
||||
outPath = Path{SingleDerivedPath::Opaque{*outStorePath}, *outStorePath};
|
||||
} else {
|
||||
// CA derivation with unknown output path
|
||||
outPath = Path{
|
||||
SingleDerivedPath::Built{makeConstantStorePathRef(drvStorePath), outputName_},
|
||||
std::nullopt};
|
||||
}
|
||||
}
|
||||
|
||||
std::string PackageInfo::queryName() const
|
||||
@@ -64,26 +73,60 @@ std::string PackageInfo::querySystem() const
|
||||
return system;
|
||||
}
|
||||
|
||||
std::optional<StorePath> PackageInfo::queryDrvPath() const
|
||||
std::optional<PackageInfo::Path> PackageInfo::queryDrvPathFlexible() const
|
||||
{
|
||||
if (!drvPath && attrs) {
|
||||
if (auto i = attrs->get(state->s.drvPath)) {
|
||||
NixStringContext context;
|
||||
auto found = state->coerceToStorePath(
|
||||
i->pos, *i->value, context, "while evaluating the 'drvPath' attribute of a derivation");
|
||||
auto i = attrs->get(state->s.drvPath);
|
||||
if (i) {
|
||||
Value v;
|
||||
v.mkAttrs(const_cast<Bindings *>(attrs));
|
||||
std::optional<SingleDerivedPath> outPathDerivedPath;
|
||||
try {
|
||||
found.requireDerivation();
|
||||
// Validate derivation structure
|
||||
outPathDerivedPath = state->coerceToSingleDerivedPath(
|
||||
noPos, v, "while evaluating the derivation");
|
||||
} catch (Error & e) {
|
||||
e.addTrace(state->positions[i->pos], "while evaluating the 'drvPath' attribute of a derivation");
|
||||
throw;
|
||||
auto info = e.info();
|
||||
info.msg = HintFmt("in a future version of Nix this will be an error: %s", Uncolored(info.msg.str()));
|
||||
logWarning(info);
|
||||
}
|
||||
if (outPathDerivedPath) {
|
||||
// Validation passed. Now get drvPath.
|
||||
auto drvPathDerivedPath = state->coerceToSingleDerivedPath(
|
||||
i->pos, *i->value, "while evaluating the 'drvPath' attribute of a derivation");
|
||||
if (auto * opaque = std::get_if<SingleDerivedPath::Opaque>(&drvPathDerivedPath.raw())) {
|
||||
opaque->path.requireDerivation();
|
||||
drvPath = {{Path{std::move(drvPathDerivedPath), opaque->path}}};
|
||||
} else {
|
||||
// Dynamic derivation - drvPath is itself a derivation output
|
||||
drvPath = {{Path{std::move(drvPathDerivedPath), std::nullopt}}};
|
||||
}
|
||||
} else {
|
||||
// Fall back to old behavior
|
||||
NixStringContext context;
|
||||
auto found = state->coerceToStorePath(
|
||||
i->pos, *i->value, context, "while evaluating the 'drvPath' attribute of a derivation");
|
||||
try {
|
||||
found.requireDerivation();
|
||||
} catch (Error & e) {
|
||||
e.addTrace(state->positions[i->pos], "while evaluating the 'drvPath' attribute of a derivation");
|
||||
throw;
|
||||
}
|
||||
drvPath = {{Path{SingleDerivedPath::Opaque{found}, std::move(found)}}};
|
||||
}
|
||||
drvPath = {std::move(found)};
|
||||
} else
|
||||
drvPath = {std::nullopt};
|
||||
}
|
||||
return drvPath.value_or(std::nullopt);
|
||||
}
|
||||
|
||||
std::optional<StorePath> PackageInfo::queryDrvPath() const
|
||||
{
|
||||
if (auto path = queryDrvPathFlexible())
|
||||
return path->storePath;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
StorePath PackageInfo::requireDrvPath() const
|
||||
{
|
||||
if (auto drvPath = queryDrvPath())
|
||||
@@ -91,20 +134,51 @@ StorePath PackageInfo::requireDrvPath() const
|
||||
throw Error("derivation does not contain a 'drvPath' attribute");
|
||||
}
|
||||
|
||||
StorePath PackageInfo::queryOutPath() const
|
||||
PackageInfo::Path PackageInfo::queryOutPathFlexible() const
|
||||
{
|
||||
if (!outPath && attrs) {
|
||||
auto i = attrs->get(state->s.outPath);
|
||||
NixStringContext context;
|
||||
if (i)
|
||||
outPath = state->coerceToStorePath(
|
||||
i->pos, *i->value, context, "while evaluating the output path of a derivation");
|
||||
Value v;
|
||||
v.mkAttrs(const_cast<Bindings *>(attrs));
|
||||
std::optional<SingleDerivedPath> derivedPath;
|
||||
try {
|
||||
derivedPath = state->coerceToSingleDerivedPath(
|
||||
noPos, v, "while evaluating the derivation");
|
||||
} catch (Error & e) {
|
||||
auto info = e.info();
|
||||
info.msg = HintFmt("in a future version of Nix this will be an error: %s", Uncolored(info.msg.str()));
|
||||
logWarning(info);
|
||||
}
|
||||
if (derivedPath) {
|
||||
if (auto * opaque = std::get_if<SingleDerivedPath::Opaque>(&derivedPath->raw())) {
|
||||
outPath = Path{std::move(*derivedPath), opaque->path};
|
||||
} else {
|
||||
// Built path - no concrete output path available (placeholder)
|
||||
outPath = Path{std::move(*derivedPath), std::nullopt};
|
||||
}
|
||||
} else {
|
||||
// Fall back to old behavior
|
||||
auto i = attrs->get(state->s.outPath);
|
||||
NixStringContext context;
|
||||
if (i) {
|
||||
auto path = state->coerceToStorePath(
|
||||
i->pos, *i->value, context, "while evaluating the output path of a derivation");
|
||||
outPath = Path{SingleDerivedPath::Opaque{path}, std::move(path)};
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!outPath)
|
||||
throw UnimplementedError("CA derivations are not yet supported");
|
||||
throw Error("derivation does not have an 'outPath' attribute");
|
||||
return *outPath;
|
||||
}
|
||||
|
||||
StorePath PackageInfo::queryOutPath() const
|
||||
{
|
||||
auto path = queryOutPathFlexible();
|
||||
if (!path.storePath)
|
||||
throw UnimplementedError("CA derivations are not yet supported");
|
||||
return *path.storePath;
|
||||
}
|
||||
|
||||
PackageInfo::Outputs PackageInfo::queryOutputs(bool withPaths, bool onlyOutputsToInstall)
|
||||
{
|
||||
if (outputs.empty()) {
|
||||
|
||||
@@ -715,6 +715,9 @@ public:
|
||||
* string. If `coerceMore` is set, also converts nulls, integers,
|
||||
* booleans and lists to a string. If `copyToStore` is set,
|
||||
* referenced paths are copied to the Nix store as a side effect.
|
||||
* If `strict` is set, ensures that when coercing an attrset with
|
||||
* both `outPath` and `drvPath`, the string context for `outPath`
|
||||
* agrees with the `drvPath` attribute.
|
||||
*/
|
||||
BackedStringView coerceToString(
|
||||
const PosIdx pos,
|
||||
@@ -723,7 +726,8 @@ public:
|
||||
std::string_view errorCtx,
|
||||
bool coerceMore = false,
|
||||
bool copyToStore = true,
|
||||
bool canonicalizePath = true);
|
||||
bool canonicalizePath = true,
|
||||
bool strict = false);
|
||||
|
||||
StorePath copyPathToStore(NixStringContext & context, const SourcePath & path);
|
||||
|
||||
@@ -742,30 +746,33 @@ public:
|
||||
StorePath coerceToStorePath(const PosIdx pos, Value & v, NixStringContext & context, std::string_view errorCtx);
|
||||
|
||||
/**
|
||||
* Part of `coerceToSingleDerivedPath()` without any store IO which is exposed for unit testing only.
|
||||
* Coerce to `SingleDerivedPath`.
|
||||
*
|
||||
* For strings: must be either a literal store path or a
|
||||
* placeholder (see `DownstreamPlaceholder`). The string context
|
||||
* must be exactly one element, which is either a
|
||||
* `NixStringContextElem::Opaque` or `NixStringContextElem::Built`.
|
||||
* (`NixStringContextElem::DrvDeep` is not permitted). The string
|
||||
* is parsed based on the context --- the context is the source of
|
||||
* truth, and ultimately tells us what we want, and then we ensure
|
||||
* the string corresponds to it.
|
||||
*
|
||||
* For attrsets: must have an `outPath` attribute which is
|
||||
* recursively coerced. If a `drvPath` attribute is present, it is
|
||||
* also coerced and validated to agree with the `outPath` context.
|
||||
*
|
||||
* @param xpSettings Stop-gap to avoid globals during unit tests.
|
||||
*
|
||||
* @param skipStringValidation Skip validating that the string
|
||||
* matches the expected placeholder for the context. This is
|
||||
* exposed for unit testing only to avoid store IO.
|
||||
*/
|
||||
std::pair<SingleDerivedPath, std::string_view> coerceToSingleDerivedPathUnchecked(
|
||||
SingleDerivedPath coerceToSingleDerivedPath(
|
||||
const PosIdx pos,
|
||||
Value & v,
|
||||
std::string_view errorCtx,
|
||||
const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings);
|
||||
|
||||
/**
|
||||
* Coerce to `SingleDerivedPath`.
|
||||
*
|
||||
* Must be a string which is either a literal store path or a
|
||||
* "placeholder (see `DownstreamPlaceholder`).
|
||||
*
|
||||
* Even more importantly, the string context must be exactly one
|
||||
* element, which is either a `NixStringContextElem::Opaque` or
|
||||
* `NixStringContextElem::Built`. (`NixStringContextEleme::DrvDeep`
|
||||
* is not permitted).
|
||||
*
|
||||
* The string is parsed based on the context --- the context is the
|
||||
* source of truth, and ultimately tells us what we want, and then
|
||||
* we ensure the string corresponds to it.
|
||||
*/
|
||||
SingleDerivedPath coerceToSingleDerivedPath(const PosIdx pos, Value & v, std::string_view errorCtx);
|
||||
const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings,
|
||||
bool skipStringValidation = false);
|
||||
|
||||
#if NIX_USE_BOEHMGC
|
||||
/** A GC root for the baseEnv reference. */
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
///@file
|
||||
|
||||
#include "nix/expr/eval.hh"
|
||||
#include "nix/store/derived-path.hh"
|
||||
#include "nix/store/path.hh"
|
||||
|
||||
#include <string>
|
||||
@@ -20,10 +21,23 @@ public:
|
||||
private:
|
||||
EvalState * state;
|
||||
|
||||
struct Path {
|
||||
/**
|
||||
* Underlying semantic path, valid in CA and IA cases.
|
||||
*/
|
||||
SingleDerivedPath derivedPath;
|
||||
|
||||
/**
|
||||
* If we don't need a placeholder, we'll have a real store path, which we can remember here.
|
||||
* For CA derivations using placeholders, this will be std::nullopt.
|
||||
*/
|
||||
std::optional<StorePath> storePath;
|
||||
};
|
||||
|
||||
mutable std::string name;
|
||||
mutable std::string system;
|
||||
mutable std::optional<std::optional<StorePath>> drvPath;
|
||||
mutable std::optional<StorePath> outPath;
|
||||
mutable std::optional<std::optional<Path>> drvPath;
|
||||
mutable std::optional<Path> outPath;
|
||||
mutable std::string outputName;
|
||||
Outputs outputs;
|
||||
|
||||
@@ -52,8 +66,10 @@ public:
|
||||
std::string queryName() const;
|
||||
std::string querySystem() const;
|
||||
std::optional<StorePath> queryDrvPath() const;
|
||||
std::optional<Path> queryDrvPathFlexible() const;
|
||||
StorePath requireDrvPath() const;
|
||||
StorePath queryOutPath() const;
|
||||
Path queryOutPathFlexible() const;
|
||||
std::string queryOutputName() const;
|
||||
/**
|
||||
* Return the unordered map of output names to (optional) output paths.
|
||||
@@ -81,12 +97,12 @@ public:
|
||||
|
||||
void setDrvPath(StorePath path)
|
||||
{
|
||||
drvPath = {{std::move(path)}};
|
||||
drvPath = {{Path{SingleDerivedPath::Opaque{path}, std::move(path)}}};
|
||||
}
|
||||
|
||||
void setOutPath(StorePath path)
|
||||
{
|
||||
outPath = {{std::move(path)}};
|
||||
outPath = Path{SingleDerivedPath::Opaque{path}, std::move(path)};
|
||||
}
|
||||
|
||||
void setFailed()
|
||||
|
||||
4
tests/functional/lang/eval-okay-pathexists.err.exp
Normal file
4
tests/functional/lang/eval-okay-pathexists.err.exp
Normal file
@@ -0,0 +1,4 @@
|
||||
warning:
|
||||
… while evaluating the first argument passed to builtins.toPath
|
||||
|
||||
warning: in a future version of Nix this will be an error: cannot coerce a set that is not a package to a single derived path: { outPath = «thunk»; }
|
||||
@@ -0,0 +1 @@
|
||||
warning: in a future version of Nix this will be an error: derivation '/nix/store/y1s2fiq89v2h9vkb38w508ir20dwv6v2-test.drv' is not valid
|
||||
Reference in New Issue
Block a user