Add builtins.appendContext.

A partner of builtins.getContext, useful for the same reasons.
This commit is contained in:
Shea Levy 2019-01-14 11:34:54 -05:00
parent 1d757292d0
commit b30be6b450
No known key found for this signature in database
GPG key ID: 5C0BD6957D86FE27
2 changed files with 61 additions and 4 deletions

View file

@ -1,5 +1,6 @@
#include "primops.hh" #include "primops.hh"
#include "eval-inline.hh" #include "eval-inline.hh"
#include "derivations.hh"
namespace nix { namespace nix {
@ -61,8 +62,7 @@ static RegisterPrimOp r3("__unsafeDiscardOutputDependency", 1, prim_unsafeDiscar
(i.e. the kind of context you get when referencing (i.e. the kind of context you get when referencing
.outPath of some derivation). Empty list if missing. .outPath of some derivation). Empty list if missing.
Note that for a given path any combination of the above attributes Note that for a given path any combination of the above attributes
may be present, but at least one must be set to something other may be present.
than the default.
*/ */
static void prim_getContext(EvalState & state, const Pos & pos, Value * * args, Value & v) static void prim_getContext(EvalState & state, const Pos & pos, Value * * args, Value & v)
{ {
@ -129,4 +129,59 @@ static void prim_getContext(EvalState & state, const Pos & pos, Value * * args,
static RegisterPrimOp r4("__getContext", 1, prim_getContext); static RegisterPrimOp r4("__getContext", 1, prim_getContext);
/* Append the given context to a given string.
See the commentary above unsafeGetContext for details of the
context representation.
*/
static void prim_appendContext(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
PathSet context;
auto orig = state.forceString(*args[0], context, pos);
state.forceAttrs(*args[1], pos);
auto sPath = state.symbols.create("path");
auto sAllOutputs = state.symbols.create("allOutputs");
for (auto & i : *args[1]->attrs) {
if (!state.store->isStorePath(i.name))
throw EvalError("Context key '%s' is not a store path, at %s", i.name, i.pos);
if (!settings.readOnlyMode)
state.store->ensurePath(i.name);
state.forceAttrs(*i.value, *i.pos);
auto iter = i.value->attrs->find(sPath);
if (iter != i.value->attrs->end()) {
if (state.forceBool(*iter->value, *iter->pos))
context.insert(i.name);
}
iter = i.value->attrs->find(sAllOutputs);
if (iter != i.value->attrs->end()) {
if (state.forceBool(*iter->value, *iter->pos)) {
if (!isDerivation(i.name)) {
throw EvalError("Tried to add all-outputs context of %s, which is not a derivation, to a string, at %s", i.name, i.pos);
}
context.insert("=" + string(i.name));
}
}
iter = i.value->attrs->find(state.sOutputs);
if (iter != i.value->attrs->end()) {
state.forceList(*iter->value, *iter->pos);
if (iter->value->listSize() && !isDerivation(i.name)) {
throw EvalError("Tried to add derivation output context of %s, which is not a derivation, to a string, at %s", i.name, i.pos);
}
for (unsigned int n = 0; n < iter->value->listSize(); ++n) {
auto name = state.forceStringNoCtx(*iter->value->listElems()[n], *iter->pos);
context.insert("!" + name + "!" + string(i.name));
}
}
}
mkString(v, orig, context);
}
static RegisterPrimOp r5("__appendContext", 2, prim_appendContext);
} }

View file

@ -18,5 +18,7 @@ let
}; };
}; };
legit-context = "${path}${drv.outPath}${drv.foo.outPath}${drv.drvPath}"; legit-context = builtins.getContext "${path}${drv.outPath}${drv.foo.outPath}${drv.drvPath}";
in builtins.getContext legit-context == desired-context
constructed-context = builtins.getContext (builtins.appendContext "" desired-context);
in legit-context == constructed-context