Add detailed error mesage for coerceTo{String,Path}
This commit is contained in:
parent
be1f069746
commit
3a5855353e
14 changed files with 79 additions and 66 deletions
|
@ -1775,7 +1775,7 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
|
||||||
/* skip canonization of first path, which would only be not
|
/* skip canonization of first path, which would only be not
|
||||||
canonized in the first place if it's coming from a ./${foo} type
|
canonized in the first place if it's coming from a ./${foo} type
|
||||||
path */
|
path */
|
||||||
auto part = state.coerceToString(i_pos, vTmp, context, false, firstType == nString, !first);
|
auto part = state.coerceToString(i_pos, vTmp, context, false, firstType == nString, !first, "");
|
||||||
sSize += part->size();
|
sSize += part->size();
|
||||||
s.emplace_back(std::move(part));
|
s.emplace_back(std::move(part));
|
||||||
}
|
}
|
||||||
|
@ -1958,14 +1958,15 @@ std::optional<std::string> EvalState::tryAttrsToString(const Pos & pos, Value &
|
||||||
if (i != v.attrs->end()) {
|
if (i != v.attrs->end()) {
|
||||||
Value v1;
|
Value v1;
|
||||||
callFunction(*i->value, v, v1, pos);
|
callFunction(*i->value, v, v1, pos);
|
||||||
return coerceToString(pos, v1, context, coerceMore, copyToStore).toOwned();
|
return coerceToString(pos, v1, context, coerceMore, copyToStore,
|
||||||
|
"While evaluating the result of the `toString` attribute").toOwned();
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
BackedStringView EvalState::coerceToString(const Pos & pos, Value & v, PathSet & context,
|
BackedStringView EvalState::coerceToString(const Pos & pos, Value & v, PathSet & context,
|
||||||
bool coerceMore, bool copyToStore, bool canonicalizePath)
|
bool coerceMore, bool copyToStore, bool canonicalizePath, const std::string & errorCtx)
|
||||||
{
|
{
|
||||||
forceValue(v, pos);
|
forceValue(v, pos);
|
||||||
|
|
||||||
|
@ -1988,12 +1989,12 @@ BackedStringView EvalState::coerceToString(const Pos & pos, Value & v, PathSet &
|
||||||
if (maybeString)
|
if (maybeString)
|
||||||
return std::move(*maybeString);
|
return std::move(*maybeString);
|
||||||
auto i = v.attrs->find(sOutPath);
|
auto i = v.attrs->find(sOutPath);
|
||||||
if (i == v.attrs->end()) throwTypeError(pos, "cannot coerce a set to a string");
|
if (i == v.attrs->end()) throwTypeError(pos, "%2%: cannot coerce %1% to a string", v, errorCtx);
|
||||||
return coerceToString(pos, *i->value, context, coerceMore, copyToStore);
|
return coerceToString(pos, *i->value, context, coerceMore, copyToStore, canonicalizePath, errorCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v.type() == nExternal)
|
if (v.type() == nExternal)
|
||||||
return v.external->coerceToString(pos, context, coerceMore, copyToStore);
|
return v.external->coerceToString(pos, context, coerceMore, copyToStore, errorCtx);
|
||||||
|
|
||||||
if (coerceMore) {
|
if (coerceMore) {
|
||||||
|
|
||||||
|
@ -2008,7 +2009,8 @@ BackedStringView EvalState::coerceToString(const Pos & pos, Value & v, PathSet &
|
||||||
if (v.isList()) {
|
if (v.isList()) {
|
||||||
std::string result;
|
std::string result;
|
||||||
for (auto [n, v2] : enumerate(v.listItems())) {
|
for (auto [n, v2] : enumerate(v.listItems())) {
|
||||||
result += *coerceToString(pos, *v2, context, coerceMore, copyToStore);
|
result += *coerceToString(pos, *v2, context, coerceMore, copyToStore, canonicalizePath,
|
||||||
|
errorCtx + ": While evaluating one element of the list");
|
||||||
if (n < v.listSize() - 1
|
if (n < v.listSize() - 1
|
||||||
/* !!! not quite correct */
|
/* !!! not quite correct */
|
||||||
&& (!v2->isList() || v2->listSize() != 0))
|
&& (!v2->isList() || v2->listSize() != 0))
|
||||||
|
@ -2018,7 +2020,7 @@ BackedStringView EvalState::coerceToString(const Pos & pos, Value & v, PathSet &
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throwTypeError(pos, "cannot coerce %1% to a string", v);
|
throwTypeError(pos, "%2%: cannot coerce %1% to a string", v, errorCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2046,22 +2048,22 @@ std::string EvalState::copyPathToStore(PathSet & context, const Path & path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Path EvalState::coerceToPath(const Pos & pos, Value & v, PathSet & context)
|
Path EvalState::coerceToPath(const Pos & pos, Value & v, PathSet & context, const std::string & errorCtx)
|
||||||
{
|
{
|
||||||
auto path = coerceToString(pos, v, context, false, false).toOwned();
|
auto path = coerceToString(pos, v, context, false, false, true, errorCtx).toOwned();
|
||||||
if (path == "" || path[0] != '/')
|
if (path == "" || path[0] != '/')
|
||||||
throwEvalError(pos, "string '%1%' doesn't represent an absolute path", path);
|
throwEvalError(pos, "%2%: string '%1%' doesn't represent an absolute path", path, errorCtx);
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
StorePath EvalState::coerceToStorePath(const Pos & pos, Value & v, PathSet & context)
|
StorePath EvalState::coerceToStorePath(const Pos & pos, Value & v, PathSet & context, const std::string & errorCtx)
|
||||||
{
|
{
|
||||||
auto path = coerceToString(pos, v, context, false, false).toOwned();
|
auto path = coerceToString(pos, v, context, false, false, errorCtx).toOwned();
|
||||||
if (auto storePath = store->maybeParseStorePath(path))
|
if (auto storePath = store->maybeParseStorePath(path))
|
||||||
return *storePath;
|
return *storePath;
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.msg = hintfmt("path '%1%' is not in the Nix store", path),
|
.msg = hintfmt("%2%: path '%1%' is not in the Nix store", path, errorCtx),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2263,10 +2265,10 @@ void EvalState::printStats()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string ExternalValueBase::coerceToString(const Pos & pos, PathSet & context, bool copyMore, bool copyToStore) const
|
std::string ExternalValueBase::coerceToString(const Pos & pos, PathSet & context, bool copyMore, bool copyToStore, const std::string & errorCtx) const
|
||||||
{
|
{
|
||||||
throw TypeError({
|
throw TypeError({
|
||||||
.msg = hintfmt("cannot coerce %1% to a string", showType()),
|
.msg = hintfmt("%2%: cannot coerce %1% to a string", showType(), errorCtx),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -262,17 +262,18 @@ public:
|
||||||
referenced paths are copied to the Nix store as a side effect. */
|
referenced paths are copied to the Nix store as a side effect. */
|
||||||
BackedStringView coerceToString(const Pos & pos, Value & v, PathSet & context,
|
BackedStringView coerceToString(const Pos & pos, Value & v, PathSet & context,
|
||||||
bool coerceMore = false, bool copyToStore = true,
|
bool coerceMore = false, bool copyToStore = true,
|
||||||
bool canonicalizePath = true);
|
bool canonicalizePath = true,
|
||||||
|
const std::string & errorCtx = "");
|
||||||
|
|
||||||
std::string copyPathToStore(PathSet & context, const Path & path);
|
std::string copyPathToStore(PathSet & context, const Path & path);
|
||||||
|
|
||||||
/* Path coercion. Converts strings, paths and derivations to a
|
/* Path coercion. Converts strings, paths and derivations to a
|
||||||
path. The result is guaranteed to be a canonicalised, absolute
|
path. The result is guaranteed to be a canonicalised, absolute
|
||||||
path. Nothing is copied to the store. */
|
path. Nothing is copied to the store. */
|
||||||
Path coerceToPath(const Pos & pos, Value & v, PathSet & context);
|
Path coerceToPath(const Pos & pos, Value & v, PathSet & context, const std::string & errorCtx);
|
||||||
|
|
||||||
/* Like coerceToPath, but the result must be a store path. */
|
/* Like coerceToPath, but the result must be a store path. */
|
||||||
StorePath coerceToStorePath(const Pos & pos, Value & v, PathSet & context);
|
StorePath coerceToStorePath(const Pos & pos, Value & v, PathSet & context, const std::string & errorCtx);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -260,7 +260,7 @@ static Flake getFlake(
|
||||||
PathSet emptyContext = {};
|
PathSet emptyContext = {};
|
||||||
flake.config.settings.emplace(
|
flake.config.settings.emplace(
|
||||||
setting.name,
|
setting.name,
|
||||||
state.coerceToString(*setting.pos, *setting.value, emptyContext, false, true, true) .toOwned());
|
state.coerceToString(*setting.pos, *setting.value, emptyContext, false, true, true, "") .toOwned());
|
||||||
}
|
}
|
||||||
else if (setting.value->type() == nInt)
|
else if (setting.value->type() == nInt)
|
||||||
flake.config.settings.insert({setting.name, state.forceInt(*setting.value, *setting.pos, "")});
|
flake.config.settings.insert({setting.name, state.forceInt(*setting.value, *setting.pos, "")});
|
||||||
|
|
|
@ -74,7 +74,7 @@ std::optional<StorePath> DrvInfo::queryDrvPath() const
|
||||||
if (i == attrs->end())
|
if (i == attrs->end())
|
||||||
drvPath = {std::nullopt};
|
drvPath = {std::nullopt};
|
||||||
else
|
else
|
||||||
drvPath = {state->coerceToStorePath(*i->pos, *i->value, context)};
|
drvPath = {state->coerceToStorePath(*i->pos, *i->value, context, "Whyle evaluating the drv path of a DrvInfo")};
|
||||||
}
|
}
|
||||||
return drvPath.value_or(std::nullopt);
|
return drvPath.value_or(std::nullopt);
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ StorePath DrvInfo::queryOutPath() const
|
||||||
Bindings::iterator i = attrs->find(state->sOutPath);
|
Bindings::iterator i = attrs->find(state->sOutPath);
|
||||||
PathSet context;
|
PathSet context;
|
||||||
if (i != attrs->end())
|
if (i != attrs->end())
|
||||||
outPath = state->coerceToStorePath(*i->pos, *i->value, context);
|
outPath = state->coerceToStorePath(*i->pos, *i->value, context, "While evaluating the output path of a DrvInfo");
|
||||||
}
|
}
|
||||||
if (!outPath)
|
if (!outPath)
|
||||||
throw UnimplementedError("CA derivations are not yet supported");
|
throw UnimplementedError("CA derivations are not yet supported");
|
||||||
|
@ -122,7 +122,7 @@ DrvInfo::Outputs DrvInfo::queryOutputs(bool onlyOutputsToInstall)
|
||||||
Bindings::iterator outPath = out->value->attrs->find(state->sOutPath);
|
Bindings::iterator outPath = out->value->attrs->find(state->sOutPath);
|
||||||
if (outPath == out->value->attrs->end()) continue; // FIXME: throw error?
|
if (outPath == out->value->attrs->end()) continue; // FIXME: throw error?
|
||||||
PathSet context;
|
PathSet context;
|
||||||
outputs.emplace(name, state->coerceToStorePath(*outPath->pos, *outPath->value, context));
|
outputs.emplace(name, state->coerceToStorePath(*outPath->pos, *outPath->value, context, "While evaluating the outPath of an output path of a DrvInfo"));
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
outputs.emplace("out", queryOutPath());
|
outputs.emplace("out", queryOutPath());
|
||||||
|
|
|
@ -103,7 +103,7 @@ static Path realisePath(EvalState & state, const Pos & pos, Value & v, const Rea
|
||||||
auto path = [&]()
|
auto path = [&]()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return state.coerceToPath(pos, v, context);
|
return state.coerceToPath(pos, v, context, "While realising the context of a path");
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
e.addTrace(pos, "while realising the context of a path");
|
e.addTrace(pos, "while realising the context of a path");
|
||||||
throw;
|
throw;
|
||||||
|
@ -350,10 +350,12 @@ void prim_exec(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
PathSet context;
|
PathSet context;
|
||||||
auto program = state.coerceToString(pos, *elems[0], context, false, false).toOwned();
|
auto program = state.coerceToString(pos, *elems[0], context, false, false,
|
||||||
|
"While evaluating the first element of the argument passed to builtins.exec").toOwned();
|
||||||
Strings commandArgs;
|
Strings commandArgs;
|
||||||
for (unsigned int i = 1; i < args[0]->listSize(); ++i) {
|
for (unsigned int i = 1; i < args[0]->listSize(); ++i) {
|
||||||
commandArgs.push_back(state.coerceToString(pos, *elems[i], context, false, false).toOwned());
|
commandArgs.push_back(state.coerceToString(pos, *elems[i], context, false, false,
|
||||||
|
"While evaluating an element of the argument passed to builtins.exec").toOwned());
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
auto _ = state.realiseContext(context); // FIXME: Handle CA derivations
|
auto _ = state.realiseContext(context); // FIXME: Handle CA derivations
|
||||||
|
@ -714,7 +716,8 @@ static RegisterPrimOp primop_abort({
|
||||||
.fun = [](EvalState & state, const Pos & pos, Value * * args, Value & v)
|
.fun = [](EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
PathSet context;
|
PathSet context;
|
||||||
auto s = state.coerceToString(pos, *args[0], context).toOwned();
|
auto s = state.coerceToString(pos, *args[0], context,
|
||||||
|
"While evaluating the error message passed to builtins.abort").toOwned();
|
||||||
throw Abort("evaluation aborted with the following error message: '%1%'", s);
|
throw Abort("evaluation aborted with the following error message: '%1%'", s);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -732,7 +735,8 @@ static RegisterPrimOp primop_throw({
|
||||||
.fun = [](EvalState & state, const Pos & pos, Value * * args, Value & v)
|
.fun = [](EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
PathSet context;
|
PathSet context;
|
||||||
auto s = state.coerceToString(pos, *args[0], context).toOwned();
|
auto s = state.coerceToString(pos, *args[0], context,
|
||||||
|
"While evaluating the error message passed to builtin.throw").toOwned();
|
||||||
throw ThrownError(s);
|
throw ThrownError(s);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -744,7 +748,8 @@ static void prim_addErrorContext(EvalState & state, const Pos & pos, Value * * a
|
||||||
v = *args[1];
|
v = *args[1];
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
PathSet context;
|
PathSet context;
|
||||||
e.addTrace(std::nullopt, state.coerceToString(pos, *args[0], context).toOwned());
|
e.addTrace(std::nullopt, state.coerceToString(pos, *args[0], context,
|
||||||
|
"While evaluating the error message passed to builtins.addErrorContext").toOwned());
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -757,7 +762,8 @@ static RegisterPrimOp primop_addErrorContext(RegisterPrimOp::Info {
|
||||||
|
|
||||||
static void prim_ceil(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_ceil(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
auto value = state.forceFloat(*args[0], args[0]->determinePos(pos), "While evaluating the first argument passed to builtins.ceil");
|
auto value = state.forceFloat(*args[0], args[0]->determinePos(pos),
|
||||||
|
"While evaluating the first argument passed to builtins.ceil");
|
||||||
v.mkInt(ceil(value));
|
v.mkInt(ceil(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1028,7 +1034,8 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i->name == state.sContentAddressed) {
|
if (i->name == state.sContentAddressed) {
|
||||||
contentAddressed = state.forceBool(*i->value, pos, "While evaluating the `__contentAddressed` attribute passed to builtins.derivationStrict");
|
contentAddressed = state.forceBool(*i->value, pos,
|
||||||
|
"While evaluating the `__contentAddressed` attribute passed to builtins.derivationStrict");
|
||||||
if (contentAddressed)
|
if (contentAddressed)
|
||||||
settings.requireExperimentalFeature(Xp::CaDerivations);
|
settings.requireExperimentalFeature(Xp::CaDerivations);
|
||||||
}
|
}
|
||||||
|
@ -1036,9 +1043,11 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
|
||||||
/* The `args' attribute is special: it supplies the
|
/* The `args' attribute is special: it supplies the
|
||||||
command-line arguments to the builder. */
|
command-line arguments to the builder. */
|
||||||
else if (i->name == state.sArgs) {
|
else if (i->name == state.sArgs) {
|
||||||
state.forceList(*i->value, pos, "While evaluating the `args` attribute passed to builtins.derivationStrict");
|
state.forceList(*i->value, pos,
|
||||||
|
"While evaluating the `args` attribute passed to builtins.derivationStrict");
|
||||||
for (auto elem : i->value->listItems()) {
|
for (auto elem : i->value->listItems()) {
|
||||||
auto s = state.coerceToString(posDrvName, *elem, context, true).toOwned();
|
auto s = state.coerceToString(posDrvName, *elem, context, true,
|
||||||
|
"While evaluating an element of the `args` argument passed to builtins.derivationStrict").toOwned();
|
||||||
drv.args.push_back(s);
|
drv.args.push_back(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1074,7 +1083,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
auto s = state.coerceToString(*i->pos, *i->value, context, true).toOwned();
|
auto s = state.coerceToString(*i->pos, *i->value, context, true, "While evaluating an attribute passed to builtins.derivationStrict").toOwned();
|
||||||
drv.env.emplace(key, s);
|
drv.env.emplace(key, s);
|
||||||
if (i->name == state.sBuilder) drv.builder = std::move(s);
|
if (i->name == state.sBuilder) drv.builder = std::move(s);
|
||||||
else if (i->name == state.sSystem) drv.platform = std::move(s);
|
else if (i->name == state.sSystem) drv.platform = std::move(s);
|
||||||
|
@ -1306,7 +1315,7 @@ static RegisterPrimOp primop_placeholder({
|
||||||
static void prim_toPath(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_toPath(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
PathSet context;
|
PathSet context;
|
||||||
Path path = state.coerceToPath(pos, *args[0], context);
|
Path path = state.coerceToPath(pos, *args[0], context, "While evaluating the first argument passed to builtins.toPath");
|
||||||
v.mkString(canonPath(path), context);
|
v.mkString(canonPath(path), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1337,7 +1346,7 @@ static void prim_storePath(EvalState & state, const Pos & pos, Value * * args, V
|
||||||
});
|
});
|
||||||
|
|
||||||
PathSet context;
|
PathSet context;
|
||||||
Path path = state.checkSourcePath(state.coerceToPath(pos, *args[0], context));
|
Path path = state.checkSourcePath(state.coerceToPath(pos, *args[0], context, "While evaluating the first argument passed to builtins.storePath"));
|
||||||
/* Resolve symlinks in ‘path’, unless ‘path’ itself is a symlink
|
/* Resolve symlinks in ‘path’, unless ‘path’ itself is a symlink
|
||||||
directly in the store. The latter condition is necessary so
|
directly in the store. The latter condition is necessary so
|
||||||
e.g. nix-push does the right thing. */
|
e.g. nix-push does the right thing. */
|
||||||
|
@ -1407,7 +1416,7 @@ static RegisterPrimOp primop_pathExists({
|
||||||
static void prim_baseNameOf(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_baseNameOf(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
PathSet context;
|
PathSet context;
|
||||||
v.mkString(baseNameOf(*state.coerceToString(pos, *args[0], context, false, false)), context);
|
v.mkString(baseNameOf(*state.coerceToString(pos, *args[0], context, false, false, "While evaluating the first argument passed to builtins.baseNameOf")), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_baseNameOf({
|
static RegisterPrimOp primop_baseNameOf({
|
||||||
|
@ -1427,7 +1436,7 @@ static RegisterPrimOp primop_baseNameOf({
|
||||||
static void prim_dirOf(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_dirOf(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
PathSet context;
|
PathSet context;
|
||||||
auto path = state.coerceToString(pos, *args[0], context, false, false);
|
auto path = state.coerceToString(pos, *args[0], context, false, false, "While evaluating the first argument passed to builtins.dirOf");
|
||||||
auto dir = dirOf(*path);
|
auto dir = dirOf(*path);
|
||||||
if (args[0]->type() == nPath) v.mkPath(dir); else v.mkString(dir, context);
|
if (args[0]->type() == nPath) v.mkPath(dir); else v.mkString(dir, context);
|
||||||
}
|
}
|
||||||
|
@ -1484,7 +1493,7 @@ static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Va
|
||||||
std::string prefix;
|
std::string prefix;
|
||||||
Bindings::iterator i = v2->attrs->find(state.sPrefix);
|
Bindings::iterator i = v2->attrs->find(state.sPrefix);
|
||||||
if (i != v2->attrs->end())
|
if (i != v2->attrs->end())
|
||||||
prefix = state.forceStringNoCtx(*i->value, pos, "While evaluating the `prefix` attribute passed to an element of the list passed to builtins.findFile");
|
prefix = state.forceStringNoCtx(*i->value, pos, "While evaluating the `prefix` attribute of an element of the list passed to builtins.findFile");
|
||||||
|
|
||||||
i = getAttr(
|
i = getAttr(
|
||||||
state,
|
state,
|
||||||
|
@ -1495,7 +1504,8 @@ static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Va
|
||||||
);
|
);
|
||||||
|
|
||||||
PathSet context;
|
PathSet context;
|
||||||
auto path = state.coerceToString(pos, *i->value, context, false, false).toOwned();
|
auto path = state.coerceToString(pos, *i->value, context, false, false,
|
||||||
|
"While evaluating the `path` attribute of an element of the list passed to builtins.findFile").toOwned();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto rewrites = state.realiseContext(context);
|
auto rewrites = state.realiseContext(context);
|
||||||
|
@ -1945,7 +1955,7 @@ static void addPath(
|
||||||
static void prim_filterSource(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_filterSource(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
PathSet context;
|
PathSet context;
|
||||||
Path path = state.coerceToPath(pos, *args[1], context);
|
Path path = state.coerceToPath(pos, *args[1], context, "While evaluating the second argument (the path to filter) passed to builtins.filterSource");
|
||||||
|
|
||||||
state.forceValue(*args[0], pos);
|
state.forceValue(*args[0], pos);
|
||||||
if (args[0]->type() != nFunction)
|
if (args[0]->type() != nFunction)
|
||||||
|
@ -2027,7 +2037,7 @@ static void prim_path(EvalState & state, const Pos & pos, Value * * args, Value
|
||||||
for (auto & attr : *args[0]->attrs) {
|
for (auto & attr : *args[0]->attrs) {
|
||||||
auto & n(attr.name);
|
auto & n(attr.name);
|
||||||
if (n == "path")
|
if (n == "path")
|
||||||
path = state.coerceToPath(*attr.pos, *attr.value, context);
|
path = state.coerceToPath(*attr.pos, *attr.value, context, "While evaluating the `path` attribute passed to builtins.path");
|
||||||
else if (attr.name == state.sName)
|
else if (attr.name == state.sName)
|
||||||
name = state.forceStringNoCtx(*attr.value, *attr.pos, "while evaluating the `name` attribute passed to builtins.path");
|
name = state.forceStringNoCtx(*attr.value, *attr.pos, "while evaluating the `name` attribute passed to builtins.path");
|
||||||
else if (n == "filter") {
|
else if (n == "filter") {
|
||||||
|
@ -2045,7 +2055,7 @@ static void prim_path(EvalState & state, const Pos & pos, Value * * args, Value
|
||||||
}
|
}
|
||||||
if (path.empty())
|
if (path.empty())
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.msg = hintfmt("'path' required"),
|
.msg = hintfmt("Missing required 'path' attribute in the first argument to builtins.path"),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
if (name.empty())
|
if (name.empty())
|
||||||
|
@ -3318,7 +3328,7 @@ static RegisterPrimOp primop_lessThan({
|
||||||
static void prim_toString(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_toString(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
PathSet context;
|
PathSet context;
|
||||||
auto s = state.coerceToString(pos, *args[0], context, true, false);
|
auto s = state.coerceToString(pos, *args[0], context, true, false, "While evaluating the first argument passed to builtins.toString");
|
||||||
v.mkString(*s, context);
|
v.mkString(*s, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3352,10 +3362,10 @@ static RegisterPrimOp primop_toString({
|
||||||
non-negative. */
|
non-negative. */
|
||||||
static void prim_substring(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_substring(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
int start = state.forceInt(*args[0], pos, "While evaluating the first argument passed to builtins.substring");
|
int start = state.forceInt(*args[0], pos, "While evaluating the first argument (the start offset) passed to builtins.substring");
|
||||||
int len = state.forceInt(*args[1], pos, "While evaluating the second argument passed to builtins.substring");
|
int len = state.forceInt(*args[1], pos, "While evaluating the second argument (the substring length) passed to builtins.substring");
|
||||||
PathSet context;
|
PathSet context;
|
||||||
auto s = state.coerceToString(pos, *args[2], context);
|
auto s = state.coerceToString(pos, *args[2], context, "While evaluating the third argument (the string) passed to builtins.substring");
|
||||||
|
|
||||||
if (start < 0)
|
if (start < 0)
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
|
@ -3389,7 +3399,7 @@ static RegisterPrimOp primop_substring({
|
||||||
static void prim_stringLength(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_stringLength(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
PathSet context;
|
PathSet context;
|
||||||
auto s = state.coerceToString(pos, *args[0], context);
|
auto s = state.coerceToString(pos, *args[0], context, "While evaluating the argument passed to builtins.stringLength");
|
||||||
v.mkInt(s->size());
|
v.mkInt(s->size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3641,8 +3651,8 @@ static void prim_concatStringsSep(EvalState & state, const Pos & pos, Value * *
|
||||||
{
|
{
|
||||||
PathSet context;
|
PathSet context;
|
||||||
|
|
||||||
auto sep = state.forceString(*args[0], context, pos, "While evaluating the first argument passed to builtins.concatStringsSep");
|
auto sep = state.forceString(*args[0], context, pos, "While evaluating the first argument (the separator string) passed to builtins.concatStringsSep");
|
||||||
state.forceList(*args[1], pos, "While evaluating the second argument passed to builtins.concatStringsSep");
|
state.forceList(*args[1], pos, "While evaluating the second argument (the list of strings to concat) passed to builtins.concatStringsSep");
|
||||||
|
|
||||||
std::string res;
|
std::string res;
|
||||||
res.reserve((args[1]->listSize() + 32) * sep.size());
|
res.reserve((args[1]->listSize() + 32) * sep.size());
|
||||||
|
@ -3650,7 +3660,7 @@ static void prim_concatStringsSep(EvalState & state, const Pos & pos, Value * *
|
||||||
|
|
||||||
for (auto elem : args[1]->listItems()) {
|
for (auto elem : args[1]->listItems()) {
|
||||||
if (first) first = false; else res += sep;
|
if (first) first = false; else res += sep;
|
||||||
res += *state.coerceToString(pos, *elem, context);
|
res += *state.coerceToString(pos, *elem, context, "While evaluating one element of the list of strings to concat passed to builtins.concatStringsSep");
|
||||||
}
|
}
|
||||||
|
|
||||||
v.mkString(res, context);
|
v.mkString(res, context);
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace nix {
|
||||||
static void prim_unsafeDiscardStringContext(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_unsafeDiscardStringContext(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
PathSet context;
|
PathSet context;
|
||||||
auto s = state.coerceToString(pos, *args[0], context);
|
auto s = state.coerceToString(pos, *args[0], context, "While evaluating the argument passed to builtins.unsafeDiscardStringContext");
|
||||||
v.mkString(*s);
|
v.mkString(*s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ static RegisterPrimOp primop_hasContext("__hasContext", 1, prim_hasContext);
|
||||||
static void prim_unsafeDiscardOutputDependency(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_unsafeDiscardOutputDependency(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
PathSet context;
|
PathSet context;
|
||||||
auto s = state.coerceToString(pos, *args[0], context);
|
auto s = state.coerceToString(pos, *args[0], context, "While evaluating the argument passed to builtins.unsafeDiscardOutputDependency");
|
||||||
|
|
||||||
PathSet context2;
|
PathSet context2;
|
||||||
for (auto & p : context)
|
for (auto & p : context)
|
||||||
|
|
|
@ -22,7 +22,7 @@ static void prim_fetchMercurial(EvalState & state, const Pos & pos, Value * * ar
|
||||||
for (auto & attr : *args[0]->attrs) {
|
for (auto & attr : *args[0]->attrs) {
|
||||||
std::string_view n(attr.name);
|
std::string_view n(attr.name);
|
||||||
if (n == "url")
|
if (n == "url")
|
||||||
url = state.coerceToString(*attr.pos, *attr.value, context, false, false).toOwned();
|
url = state.coerceToString(*attr.pos, *attr.value, context, false, false, "While evaluating the `url` attribute passed to builtins.fetchMercurial").toOwned();
|
||||||
else if (n == "rev") {
|
else if (n == "rev") {
|
||||||
// Ugly: unlike fetchGit, here the "rev" attribute can
|
// Ugly: unlike fetchGit, here the "rev" attribute can
|
||||||
// be both a revision or a branch/tag name.
|
// be both a revision or a branch/tag name.
|
||||||
|
@ -48,7 +48,7 @@ static void prim_fetchMercurial(EvalState & state, const Pos & pos, Value * * ar
|
||||||
});
|
});
|
||||||
|
|
||||||
} else
|
} else
|
||||||
url = state.coerceToString(pos, *args[0], context, false, false).toOwned();
|
url = state.coerceToString(pos, *args[0], context, false, false, "While evaluating the first argument passed to builtins.fetchMercurial").toOwned();
|
||||||
|
|
||||||
// FIXME: git externals probably can be used to bypass the URI
|
// FIXME: git externals probably can be used to bypass the URI
|
||||||
// whitelist. Ah well.
|
// whitelist. Ah well.
|
||||||
|
|
|
@ -125,7 +125,7 @@ static void fetchTree(
|
||||||
if (attr.name == state.sType) continue;
|
if (attr.name == state.sType) continue;
|
||||||
state.forceValue(*attr.value, *attr.pos);
|
state.forceValue(*attr.value, *attr.pos);
|
||||||
if (attr.value->type() == nPath || attr.value->type() == nString) {
|
if (attr.value->type() == nPath || attr.value->type() == nString) {
|
||||||
auto s = state.coerceToString(*attr.pos, *attr.value, context, false, false).toOwned();
|
auto s = state.coerceToString(*attr.pos, *attr.value, context, false, false, "").toOwned();
|
||||||
attrs.emplace(attr.name,
|
attrs.emplace(attr.name,
|
||||||
attr.name == "url"
|
attr.name == "url"
|
||||||
? type == "git"
|
? type == "git"
|
||||||
|
@ -151,7 +151,7 @@ static void fetchTree(
|
||||||
|
|
||||||
input = fetchers::Input::fromAttrs(std::move(attrs));
|
input = fetchers::Input::fromAttrs(std::move(attrs));
|
||||||
} else {
|
} else {
|
||||||
auto url = state.coerceToString(pos, *args[0], context, false, false).toOwned();
|
auto url = state.coerceToString(pos, *args[0], context, false, false, "While evaluating the first argument passed to the fetcher").toOwned();
|
||||||
|
|
||||||
if (type == "git") {
|
if (type == "git") {
|
||||||
fetchers::Attrs attrs;
|
fetchers::Attrs attrs;
|
||||||
|
|
|
@ -85,7 +85,7 @@ class ExternalValueBase
|
||||||
/* Coerce the value to a string. Defaults to uncoercable, i.e. throws an
|
/* Coerce the value to a string. Defaults to uncoercable, i.e. throws an
|
||||||
* error.
|
* error.
|
||||||
*/
|
*/
|
||||||
virtual std::string coerceToString(const Pos & pos, PathSet & context, bool copyMore, bool copyToStore) const;
|
virtual std::string coerceToString(const Pos & pos, PathSet & context, bool copyMore, bool copyToStore, const std::string & errorCtx) const;
|
||||||
|
|
||||||
/* Compare to another value of the same type. Defaults to uncomparable,
|
/* Compare to another value of the same type. Defaults to uncomparable,
|
||||||
* i.e. always false.
|
* i.e. always false.
|
||||||
|
|
|
@ -132,9 +132,9 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
|
||||||
state.forceValue(topLevel, [&]() { return topLevel.determinePos(noPos); });
|
state.forceValue(topLevel, [&]() { return topLevel.determinePos(noPos); });
|
||||||
PathSet context;
|
PathSet context;
|
||||||
Attr & aDrvPath(*topLevel.attrs->find(state.sDrvPath));
|
Attr & aDrvPath(*topLevel.attrs->find(state.sDrvPath));
|
||||||
auto topLevelDrv = state.coerceToStorePath(*aDrvPath.pos, *aDrvPath.value, context);
|
auto topLevelDrv = state.coerceToStorePath(*aDrvPath.pos, *aDrvPath.value, context, "");
|
||||||
Attr & aOutPath(*topLevel.attrs->find(state.sOutPath));
|
Attr & aOutPath(*topLevel.attrs->find(state.sOutPath));
|
||||||
auto topLevelOut = state.coerceToStorePath(*aOutPath.pos, *aOutPath.value, context);
|
auto topLevelOut = state.coerceToStorePath(*aOutPath.pos, *aOutPath.value, context, "");
|
||||||
|
|
||||||
/* Realise the resulting store expression. */
|
/* Realise the resulting store expression. */
|
||||||
debug("building user environment");
|
debug("building user environment");
|
||||||
|
|
|
@ -97,13 +97,13 @@ struct CmdBundle : InstallableCommand
|
||||||
throw Error("the bundler '%s' does not produce a derivation", bundler.what());
|
throw Error("the bundler '%s' does not produce a derivation", bundler.what());
|
||||||
|
|
||||||
PathSet context2;
|
PathSet context2;
|
||||||
auto drvPath = evalState->coerceToStorePath(*attr1->pos, *attr1->value, context2);
|
auto drvPath = evalState->coerceToStorePath(*attr1->pos, *attr1->value, context2, "");
|
||||||
|
|
||||||
auto attr2 = vRes->attrs->get(evalState->sOutPath);
|
auto attr2 = vRes->attrs->get(evalState->sOutPath);
|
||||||
if (!attr2)
|
if (!attr2)
|
||||||
throw Error("the bundler '%s' does not produce a derivation", bundler.what());
|
throw Error("the bundler '%s' does not produce a derivation", bundler.what());
|
||||||
|
|
||||||
auto outPath = evalState->coerceToStorePath(*attr2->pos, *attr2->value, context2);
|
auto outPath = evalState->coerceToStorePath(*attr2->pos, *attr2->value, context2, "");
|
||||||
|
|
||||||
store->buildPaths({ DerivedPath::Built { drvPath } });
|
store->buildPaths({ DerivedPath::Built { drvPath } });
|
||||||
|
|
||||||
|
|
|
@ -107,7 +107,7 @@ struct CmdEval : MixJSON, InstallableCommand
|
||||||
|
|
||||||
else if (raw) {
|
else if (raw) {
|
||||||
stopProgressBar();
|
stopProgressBar();
|
||||||
std::cout << *state->coerceToString(noPos, *v, context);
|
std::cout << *state->coerceToString(noPos, *v, context, "While generating the eval command output");
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (json) {
|
else if (json) {
|
||||||
|
|
|
@ -448,7 +448,7 @@ struct CmdFlakeCheck : FlakeCommand
|
||||||
if (auto attr = v.attrs->get(state->symbols.create("path"))) {
|
if (auto attr = v.attrs->get(state->symbols.create("path"))) {
|
||||||
if (attr->name == state->symbols.create("path")) {
|
if (attr->name == state->symbols.create("path")) {
|
||||||
PathSet context;
|
PathSet context;
|
||||||
auto path = state->coerceToPath(*attr->pos, *attr->value, context);
|
auto path = state->coerceToPath(*attr->pos, *attr->value, context, "");
|
||||||
if (!store->isInStore(path))
|
if (!store->isInStore(path))
|
||||||
throw Error("template '%s' has a bad 'path' attribute");
|
throw Error("template '%s' has a bad 'path' attribute");
|
||||||
// TODO: recursively check the flake in 'path'.
|
// TODO: recursively check the flake in 'path'.
|
||||||
|
|
|
@ -461,7 +461,7 @@ bool NixRepl::processLine(std::string line)
|
||||||
|
|
||||||
if (v.type() == nPath || v.type() == nString) {
|
if (v.type() == nPath || v.type() == nString) {
|
||||||
PathSet context;
|
PathSet context;
|
||||||
auto filename = state->coerceToString(noPos, v, context);
|
auto filename = state->coerceToString(noPos, v, context, "While evaluating the filename to edit");
|
||||||
pos.file = state->symbols.create(*filename);
|
pos.file = state->symbols.create(*filename);
|
||||||
} else if (v.isLambda()) {
|
} else if (v.isLambda()) {
|
||||||
pos = v.lambda.fun->pos;
|
pos = v.lambda.fun->pos;
|
||||||
|
@ -780,7 +780,7 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m
|
||||||
Bindings::iterator i = v.attrs->find(state->sDrvPath);
|
Bindings::iterator i = v.attrs->find(state->sDrvPath);
|
||||||
PathSet context;
|
PathSet context;
|
||||||
if (i != v.attrs->end())
|
if (i != v.attrs->end())
|
||||||
str << state->store->printStorePath(state->coerceToStorePath(*i->pos, *i->value, context));
|
str << state->store->printStorePath(state->coerceToStorePath(*i->pos, *i->value, context, "While evaluating the drvPath of a derivation"));
|
||||||
else
|
else
|
||||||
str << "???";
|
str << "???";
|
||||||
str << "»";
|
str << "»";
|
||||||
|
|
Loading…
Reference in a new issue