Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions src/libexpr/primops.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5453,4 +5453,61 @@ void EvalState::createBaseEnv(const EvalSettings & evalSettings)
evalFile(derivationInternal, *vDerivation);
}

static void prim_derivationOf(EvalState & state, const PosIdx pos, Value ** args, Value & v)
{
NixStringContext context;
auto s = state.coerceToString(pos, *args[0], context,
"while evaluating the argument passed to builtins.derivationOf",
false, false).toOwned();

if (s.empty() || !state.store->isStorePath(s)) {
state.error<EvalError>("'%s' is not a valid store path", s)
.atPos(pos)
.debugThrow();
}

if (context.empty()) {
state.error<EvalError>("'%s' has no derivation in its context", s)
.atPos(pos)
.debugThrow();
}

if (context.size() > 1) {
state.error<EvalError>("'%s' has more than one item in its context", s)
.atPos(pos)
.debugThrow();
}

// we have exactly one context item.
auto & c = *context.begin();
if (auto * b = std::get_if<NixStringContextElem::Built>(&c.raw)) {
auto drvPath = b->drvPath->getBaseStorePath();
v.mkString(state.store->printStorePath(drvPath),
NixStringContext{NixStringContextElem::Opaque{.path = drvPath}},
state.mem);
return;
}
if (auto * d = std::get_if<NixStringContextElem::DrvDeep>(&c.raw)) {
v.mkString(state.store->printStorePath(d->drvPath),
NixStringContext{NixStringContextElem::Opaque{.path = d->drvPath}},
state.mem);
return;
}

// Context item exists but is not a derivation
state.error<EvalError>("'%s' has no derivation in its context", s)
.atPos(pos)
.debugThrow();
}

static RegisterPrimOp primop_derivationOf({
.name = "derivationOf",
.args = {"s"},
.doc = R"(
Return the store path of the derivation that produces the given output path.
The string must have a derivation in its string context.
)",
.fun = prim_derivationOf,
});

} // namespace nix
10 changes: 10 additions & 0 deletions tests/functional/lang/eval-fail-derivationOf-attrset.err.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error:
… while calling the 'derivationOf' builtin
at /pwd/lang/eval-fail-derivationOf-attrset.nix:1:1:
1| builtins.derivationOf { foo = "bar"; }
| ^
2|

… while evaluating the argument passed to builtins.derivationOf

error: cannot coerce a set to a string: { foo = "bar"; }
1 change: 1 addition & 0 deletions tests/functional/lang/eval-fail-derivationOf-attrset.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
builtins.derivationOf { foo = "bar"; }
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error:
… while calling the 'derivationOf' builtin
at /pwd/lang/eval-fail-derivationOf-empty-string.nix:1:1:
1| builtins.derivationOf ""
| ^
2|

error: '' is not a valid store path
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
builtins.derivationOf ""
10 changes: 10 additions & 0 deletions tests/functional/lang/eval-fail-derivationOf-list.err.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error:
… while calling the 'derivationOf' builtin
at /pwd/lang/eval-fail-derivationOf-list.nix:1:1:
1| builtins.derivationOf [ "foo" "bar" ]
| ^
2|

… while evaluating the argument passed to builtins.derivationOf

error: cannot coerce a list to a string: [ "foo" "bar" ]
1 change: 1 addition & 0 deletions tests/functional/lang/eval-fail-derivationOf-list.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
builtins.derivationOf [ "foo" "bar" ]
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error:
… while calling the 'derivationOf' builtin
at /pwd/lang/eval-fail-derivationOf-multiple-contexts.nix:15:1:
14| in
15| builtins.derivationOf multipleContexts
| ^
16|

error: '/nix/store/w190vpfkz3a127yhsd3z35rh02nra1l8-test1/nix/store/8xsds8xaq3yf169w0k54j23ir24gnmwi-test2' is not a valid store path
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
let
drv1 = derivation {
name = "test1";
builder = "/bin/false";
system = "x86_64-linux";
};
drv2 = derivation {
name = "test2";
builder = "/bin/false";
system = "x86_64-linux";
};
# Create a string with multiple context items by concatenating paths from different derivations
multipleContexts = "${drv1.outPath}${drv2.outPath}";
in
builtins.derivationOf multipleContexts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error:
… while calling the 'derivationOf' builtin
at /pwd/lang/eval-fail-derivationOf-nix-path.nix:1:1:
1| builtins.derivationOf ./.
| ^
2|

error: '/pwd/lang' is not a valid store path
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
builtins.derivationOf ./.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error:
… while calling the 'derivationOf' builtin
at /pwd/lang/eval-fail-derivationOf-no-context-store-path.nix:1:1:
1| builtins.derivationOf "/nix/store/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-test"
| ^
2|

error: '/nix/store/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-test' has no derivation in its context
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
builtins.derivationOf "/nix/store/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-test"
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error:
… while calling the 'derivationOf' builtin
at /pwd/lang/eval-fail-derivationOf-no-context.nix:1:1:
1| builtins.derivationOf "foo"
| ^
2|

error: 'foo' is not a valid store path
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
builtins.derivationOf "foo"
10 changes: 10 additions & 0 deletions tests/functional/lang/eval-fail-derivationOf-number.err.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error:
… while calling the 'derivationOf' builtin
at /pwd/lang/eval-fail-derivationOf-number.nix:1:1:
1| builtins.derivationOf 42
| ^
2|

… while evaluating the argument passed to builtins.derivationOf

error: cannot coerce an integer to a string: 42
1 change: 1 addition & 0 deletions tests/functional/lang/eval-fail-derivationOf-number.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
builtins.derivationOf 42
8 changes: 8 additions & 0 deletions tests/functional/lang/eval-fail-derivationOf-path.err.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error:
… while calling the 'derivationOf' builtin
at /pwd/lang/eval-fail-derivationOf-path.nix:1:1:
1| builtins.derivationOf /tmp/foo
| ^
2|

error: '/tmp/foo' is not a valid store path
1 change: 1 addition & 0 deletions tests/functional/lang/eval-fail-derivationOf-path.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
builtins.derivationOf /tmp/foo
1 change: 1 addition & 0 deletions tests/functional/lang/eval-okay-derivationOf-coerce.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
true
8 changes: 8 additions & 0 deletions tests/functional/lang/eval-okay-derivationOf-coerce.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
let
pkg = derivation {
name = "test";
builder = "/bin/false";
system = "x86_64-linux";
};
in
builtins.derivationOf pkg.outPath == drv.drvPath
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
true
10 changes: 10 additions & 0 deletions tests/functional/lang/eval-okay-derivationOf-single-context.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
let
drv = derivation {
name = "single-test";
builder = "/bin/false";
system = "x86_64-linux";
};
# Explicitly test with a single context item
singleContext = drv.outPath;
in
builtins.derivationOf singleContext == drv.drvPath
1 change: 1 addition & 0 deletions tests/functional/lang/eval-okay-derivationOf.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
true
8 changes: 8 additions & 0 deletions tests/functional/lang/eval-okay-derivationOf.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
let
pkg = derivation {
name = "test";
builder = "/bin/false";
system = "x86_64-linux";
};
in
builtins.derivationOf pkg == drv.drvPath