From b3b623db8de2957db35e8b07e39dca7100359ebf Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 27 Mar 2026 12:28:51 +0100 Subject: [PATCH] builtins.getFlake: Handle path:

where p has a discarded string context For instance, github:Mic92/sops-nix/8b89f44c2cc4581e402111d928869fe7ba9f7033 does this: loadPrivateFlake = path: let flakeHash = builtins.readFile "${toString path}.narHash"; flakePath = "path:${toString path}?narHash=${flakeHash}"; in builtins.getFlake (builtins.unsafeDiscardStringContext flakePath); This previously resulted in error: path '/nix/store/2c8r30kz9zg8kz11ngp64ah5ya0hc011-source/dev/private/flake.nix' does not exist Fixes https://github.com/DeterminateSystems/nix-src/issues/345. --- src/libflake/flake-primops.cc | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/libflake/flake-primops.cc b/src/libflake/flake-primops.cc index 4d27c6848272..33c7b7d8789a 100644 --- a/src/libflake/flake-primops.cc +++ b/src/libflake/flake-primops.cc @@ -9,6 +9,7 @@ #include #include "nix/flake/flake-primops.hh" +#include "nix/store/store-api.hh" #include "nix/expr/eval.hh" #include "nix/flake/flake.hh" #include "nix/flake/flakeref.hh" @@ -66,6 +67,25 @@ PrimOp getFlake(const Settings & settings) flakeRefS, state.positions[pos]); + /* Backward compatibility hack: If this is a `path` flake and it's a virtual path that had + * `unsafeDiscardStringContext` applied to it, then treat it like the `nPath` case, i.e. call lockFlake() on + * the virtual path directly. This is necessary because the `path` fetcher doesn't see virtual paths. */ + if (flakeRef.input.getType() == "path") { + if (auto sourcePath = flakeRef.input.getSourcePath(); + sourcePath && state.store->isInStore(sourcePath->string())) { + auto [storePath, subPath] = state.store->toStorePath(sourcePath->string()); + for (auto & c : context) { + if (auto p = std::get_if(&c.raw); p && p->storePath == storePath) { + auto path = state.storePath(storePath) / CanonPath(subPath); + if (!flakeRef.subdir.empty()) + path = path / flakeRef.subdir; + callFlake(state, lockFlake(settings, state, path, lockFlags), v); + return; + } + } + } + } + callFlake(state, lockFlake(settings, state, flakeRef, lockFlags), v); } };