aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libexpr/primops/context.cc59
-rw-r--r--tests/lang/eval-okay-context-introspection.nix6
2 files changed, 61 insertions, 4 deletions
diff --git a/src/libexpr/primops/context.cc b/src/libexpr/primops/context.cc
index 6849aa261..2d79739ea 100644
--- a/src/libexpr/primops/context.cc
+++ b/src/libexpr/primops/context.cc
@@ -1,5 +1,6 @@
#include "primops.hh"
#include "eval-inline.hh"
+#include "derivations.hh"
namespace nix {
@@ -61,8 +62,7 @@ static RegisterPrimOp r3("__unsafeDiscardOutputDependency", 1, prim_unsafeDiscar
(i.e. the kind of context you get when referencing
.outPath of some derivation). Empty list if missing.
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
- than the default.
+ may be present.
*/
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);
+
+/* 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);
+
}
diff --git a/tests/lang/eval-okay-context-introspection.nix b/tests/lang/eval-okay-context-introspection.nix
index d9b2ea354..43178bd2e 100644
--- a/tests/lang/eval-okay-context-introspection.nix
+++ b/tests/lang/eval-okay-context-introspection.nix
@@ -18,5 +18,7 @@ let
};
};
- legit-context = "${path}${drv.outPath}${drv.foo.outPath}${drv.drvPath}";
-in builtins.getContext legit-context == desired-context
+ legit-context = builtins.getContext "${path}${drv.outPath}${drv.foo.outPath}${drv.drvPath}";
+
+ constructed-context = builtins.getContext (builtins.appendContext "" desired-context);
+in legit-context == constructed-context