From a572c9433330ea307a3b5c83db2357d6ca55f8e0 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 12 Jun 2025 20:19:19 +0200 Subject: [PATCH] Fix deep overrides An override like inputs.foo.inputs.bar.inputs.nixpkgs.follows = "nixpkgs"; implicitly set `inputs.foo.inputs.bar` to `flake:bar`, which led to an unexpected error like error: cannot find flake 'flake:bar' in the flake registries We now no longer create a parent override (like for `foo.bar` in the example above) if it doesn't set an explicit ref or follows attribute. We only recursively apply its child overrides. Fixes https://github.com/NixOS/nix/issues/8325, https://github.com/DeterminateSystems/nix-src/issues/95, https://github.com/NixOS/nix/issues/12083, https://github.com/NixOS/nix/issues/5790. --- src/libflake/flake.cc | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/src/libflake/flake.cc b/src/libflake/flake.cc index 31328abde..5570422a3 100644 --- a/src/libflake/flake.cc +++ b/src/libflake/flake.cc @@ -85,7 +85,6 @@ static void parseFlakeInputAttr( static FlakeInput parseFlakeInput( EvalState & state, - std::string_view inputName, Value * value, const PosIdx pos, const InputAttrPath & lockRootAttrPath, @@ -155,9 +154,6 @@ static FlakeInput parseFlakeInput( input.ref = parseFlakeRef(state.fetchSettings, *url, {}, true, input.isFlake, true); } - if (!input.follows && !input.ref) - input.ref = FlakeRef::fromAttrs(state.fetchSettings, {{"type", "indirect"}, {"id", std::string(inputName)}}); - return input; } @@ -185,7 +181,6 @@ static std::pair, fetchers::Attrs> parseFlakeInput } else { inputs.emplace(inputName, parseFlakeInput(state, - inputName, inputAttr.value, inputAttr.pos, lockRootAttrPath, @@ -467,18 +462,27 @@ LockedFlake lockFlake( /* Get the overrides (i.e. attributes of the form 'inputs.nixops.inputs.nixpkgs.url = ...'). */ - for (auto & [id, input] : flakeInputs) { + std::function addOverrides; + addOverrides = [&](const FlakeInput & input, const InputAttrPath & prefix) + { for (auto & [idOverride, inputOverride] : input.overrides) { - auto inputAttrPath(inputAttrPathPrefix); - inputAttrPath.push_back(id); + auto inputAttrPath(prefix); inputAttrPath.push_back(idOverride); - overrides.emplace(inputAttrPath, - OverrideTarget { - .input = inputOverride, - .sourcePath = sourcePath, - .parentInputAttrPath = inputAttrPathPrefix - }); + if (inputOverride.ref || inputOverride.follows) + overrides.emplace(inputAttrPath, + OverrideTarget { + .input = inputOverride, + .sourcePath = sourcePath, + .parentInputAttrPath = inputAttrPathPrefix + }); + addOverrides(inputOverride, inputAttrPath); } + }; + + for (auto & [id, input] : flakeInputs) { + auto inputAttrPath(inputAttrPathPrefix); + inputAttrPath.push_back(id); + addOverrides(input, inputAttrPath); } /* Check whether this input has overrides for a @@ -534,7 +538,8 @@ LockedFlake lockFlake( continue; } - assert(input.ref); + if (!input.ref) + input.ref = FlakeRef::fromAttrs(state.fetchSettings, {{"type", "indirect"}, {"id", std::string(id)}}); auto overridenParentPath = input.ref->input.isRelative()