From 7a8024c39f4089320ae45a7f257f0ddb60954938 Mon Sep 17 00:00:00 2001 From: zimbatm Date: Tue, 24 Dec 2024 15:23:08 +0100 Subject: [PATCH] builtins.getFlake: also support path argument This is a papercut that has been bugging me for a while. `:lf .` is fine but doesn't show you what variables it adds to the context. And `builtins.getFlake (toString ./.)` works but gets tedious after a while. When inspecting a flake in the repl, the natural thing to do is to call: x = builtins.getFlake ./. Before this change, Nix would fail with: error: expected a string but found a path: /path/to/flake After this change, Nix automatically coerces the path to a string. --- src/libflake/flake/flake.cc | 12 +++++++++++- tests/functional/flakes/shebang.sh | 2 +- tests/functional/suggestions.sh | 4 ++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/libflake/flake/flake.cc b/src/libflake/flake/flake.cc index 19b622a34af..140ac5052f3 100644 --- a/src/libflake/flake/flake.cc +++ b/src/libflake/flake/flake.cc @@ -823,7 +823,11 @@ void initLib(const Settings & settings) { auto prim_getFlake = [&settings](EvalState & state, const PosIdx pos, Value * * args, Value & v) { - std::string flakeRefS(state.forceStringNoCtx(*args[0], pos, "while evaluating the argument passed to builtins.getFlake")); + NixStringContext context; // no context + auto flakeRefS = state.coerceToString(pos, *args[0], context, + "while evaluating the argument passed to builtins.getFlake", + false, false, true).toOwned(); + auto flakeRef = parseFlakeRef(state.fetchSettings, flakeRefS, {}, true); if (state.settings.pureEval && !flakeRef.input.isLocked()) throw Error("cannot call 'getFlake' on unlocked flake reference '%s', at %s (use --impure to override)", flakeRefS, state.positions[pos]); @@ -849,6 +853,12 @@ void initLib(const Settings & settings) (builtins.getFlake "nix/55bc52401966fbffa525c574c14f67b00bc4fb3a").packages.x86_64-linux.nix ``` + The function can also be used to load flakes from the file system. For example: + + ```nix + (builtins.getFlake ./.).packages.x86_64-linux.nix + ``` + Unless impure evaluation is allowed (`--impure`), the flake reference must be "locked", e.g. contain a Git revision or content hash. An example of an unlocked usage is: diff --git a/tests/functional/flakes/shebang.sh b/tests/functional/flakes/shebang.sh index 576a62e2cb4..d9ba7997029 100644 --- a/tests/functional/flakes/shebang.sh +++ b/tests/functional/flakes/shebang.sh @@ -69,7 +69,7 @@ EOF cat >> "$scriptDir/shebang-inline-expr.sh" <<"EOF" #! nix --offline shell #! nix --impure --expr `` -#! nix let flake = (builtins.getFlake (toString ../flake1)).packages; +#! nix let flake = (builtins.getFlake ../flake1).packages; #! nix fooScript = flake.${builtins.currentSystem}.fooScript; #! nix /* just a comment !@#$%^&*()__+ # */ #! nix in fooScript diff --git a/tests/functional/suggestions.sh b/tests/functional/suggestions.sh index fbca93da859..bcfaa00fc53 100755 --- a/tests/functional/suggestions.sh +++ b/tests/functional/suggestions.sh @@ -37,8 +37,8 @@ NIX_BUILD_STDERR_WITH_NO_CLOSE_SUGGESTION=$(! nix build .\#bar 2>&1 1>/dev/null) [[ ! "$NIX_BUILD_STDERR_WITH_NO_CLOSE_SUGGESTION" =~ "Did you mean" ]] || \ fail "The nix build stderr shouldn’t suggest anything if there’s nothing relevant to suggest" -NIX_EVAL_STDERR_WITH_SUGGESTIONS=$(! nix build --impure --expr '(builtins.getFlake (builtins.toPath ./.)).packages.'"$system"'.fob' 2>&1 1>/dev/null) -[[ "$NIX_EVAL_STDERR_WITH_SUGGESTIONS" =~ "Did you mean one of fo1, fo2, foo or fooo?" ]] || \ +NIX_EVAL_STDERR_WITH_SUGGESTIONS=$(! nix build --impure --expr '(builtins.getFlake ./.).packages.'"$system"'.fob' 2>&1 1>/dev/null) +[[ "$NIX_EVAL_STDERR_WITH_SUGGESTIONS" =~ "Did you mean one of fo1, fo2, foo or fooo?" ]] || fail "The evaluator should suggest the three closest possiblities" NIX_EVAL_STDERR_WITH_SUGGESTIONS=$(! nix build --impure --expr '({ foo }: foo) { foo = 1; fob = 2; }' 2>&1 1>/dev/null)