1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-24 22:11:15 +02:00

Merge pull request #13170 from MattSturgeon/fix/call-flake/rel-path

Use correct parent `outPath` for relative path inputs
This commit is contained in:
Robert Hensing 2025-05-19 14:13:54 +02:00 committed by GitHub
commit f18af849fe
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 117 additions and 15 deletions

View file

@ -0,0 +1,17 @@
---
synopsis: Non-flake inputs now contain a `sourceInfo` attribute
issues: 13164
prs: 13170
---
Flakes have always a `sourceInfo` attribute which describes the source of the flake.
The `sourceInfo.outPath` is often identical to the flake's `outPath`, however it can differ when the flake is located in a subdirectory of its source.
Non-flake inputs (i.e. inputs with `flake = false`) can also be located at some path _within_ a wider source.
This usually happens when defining a relative path input within the same source as the parent flake, e.g. `inputs.foo.url = ./some-file.nix`.
Such relative inputs will now inherit their parent's `sourceInfo`.
This also means it is now possible to use `?dir=subdir` on non-flake inputs.
This iterates on the work done in 2.26 to improve relative path support ([#10089](https://github.com/NixOS/nix/pull/10089)),
and resolves a regression introduced in 2.28 relating to nested relative path inputs ([#13164](https://github.com/NixOS/nix/issues/13164)).

View file

@ -39,24 +39,16 @@ let
allNodes = mapAttrs (
key: node:
let
hasOverride = overrides ? ${key};
isRelative = node.locked.type or null == "path" && builtins.substring 0 1 node.locked.path != "/";
parentNode = allNodes.${getInputByPath lockFile.root node.parent};
flakeDir =
let
dir = overrides.${key}.dir or node.locked.path or "";
parentDir = parentNode.flakeDir;
in
if node ? parent then parentDir + ("/" + dir) else dir;
sourceInfo =
if overrides ? ${key} then
if hasOverride then
overrides.${key}.sourceInfo
else if node.locked.type == "path" && builtins.substring 0 1 node.locked.path != "/" then
else if isRelative then
parentNode.sourceInfo
// {
outPath = parentNode.sourceInfo.outPath + ("/" + flakeDir);
}
else
# FIXME: remove obsolete node.info.
# Note: lock file entries are always final.
@ -64,7 +56,11 @@ let
subdir = overrides.${key}.dir or node.locked.dir or "";
outPath = sourceInfo + ((if subdir == "" then "" else "/") + subdir);
outPath =
if !hasOverride && isRelative then
parentNode.outPath + (if node.locked.path == "" then "" else "/" + node.locked.path)
else
sourceInfo.outPath + (if subdir == "" then "" else "/" + subdir);
flake = import (outPath + "/flake.nix");
@ -99,9 +95,9 @@ let
assert builtins.isFunction flake.outputs;
result
else
sourceInfo;
sourceInfo // { inherit sourceInfo outPath; };
inherit flakeDir sourceInfo;
inherit outPath sourceInfo;
}
) lockFile.nodes;

View file

@ -37,11 +37,20 @@ cat > "$flake3Dir/flake.nix" <<EOF
url = "$nonFlakeDir/README.md";
flake = false;
};
nonFlakeFile3 = {
url = "$nonFlakeDir?dir=README.md";
flake = false;
};
relativeNonFlakeFile = {
url = ./config.nix;
flake = false;
};
};
description = "Fnord";
outputs = inputs: rec {
inherit inputs;
packages.$system.xyzzy = inputs.flake2.packages.$system.bar;
packages.$system.sth = inputs.flake1.packages.$system.foo;
packages.$system.fnord =
@ -88,6 +97,43 @@ mv "$flake2Dir.tmp" "$flake2Dir"
mv "$nonFlakeDir.tmp" "$nonFlakeDir"
nix build -o "$TEST_ROOT/result" flake3#xyzzy flake3#fnord
# Check non-flake inputs have a sourceInfo and an outPath
#
# This may look redundant, but the other checks below happen in a command
# substitution subshell, so failures there will not exit this shell
nix eval --raw flake3#inputs.nonFlake.outPath
nix eval --raw flake3#inputs.nonFlake.sourceInfo.outPath
nix eval --raw flake3#inputs.nonFlakeFile.outPath
nix eval --raw flake3#inputs.nonFlakeFile.sourceInfo.outPath
nix eval --raw flake3#inputs.nonFlakeFile2.outPath
nix eval --raw flake3#inputs.nonFlakeFile2.sourceInfo.outPath
nix eval --raw flake3#inputs.nonFlakeFile3.outPath
nix eval --raw flake3#inputs.nonFlakeFile3.sourceInfo.outPath
nix eval --raw flake3#inputs.relativeNonFlakeFile.outPath
nix eval --raw flake3#inputs.relativeNonFlakeFile.sourceInfo.outPath
# Check non-flake file inputs have the expected outPaths
[[
$(nix eval --raw flake3#inputs.nonFlake.outPath) \
= $(nix eval --raw flake3#inputs.nonFlake.sourceInfo.outPath)
]]
[[
$(nix eval --raw flake3#inputs.nonFlakeFile.outPath) \
= $(nix eval --raw flake3#inputs.nonFlakeFile.sourceInfo.outPath)
]]
[[
$(nix eval --raw flake3#inputs.nonFlakeFile2.outPath) \
= $(nix eval --raw flake3#inputs.nonFlakeFile2.sourceInfo.outPath)
]]
[[
$(nix eval --raw flake3#inputs.nonFlakeFile3.outPath) \
= $(nix eval --raw flake3#inputs.nonFlakeFile3.sourceInfo.outPath)/README.md
]]
[[
$(nix eval --raw flake3#inputs.relativeNonFlakeFile.outPath) \
= $(nix eval --raw flake3#inputs.relativeNonFlakeFile.sourceInfo.outPath)/config.nix
]]
# Make branch "removeXyzzy" where flake3 doesn't have xyzzy anymore
git -C "$flake3Dir" checkout -b removeXyzzy
rm "$flake3Dir/flake.nix"

View file

@ -131,3 +131,46 @@ EOF
# would fail:
nix eval .#ok
)
# https://github.com/NixOS/nix/issues/13164
mkdir -p "$TEST_ROOT/issue-13164/nested-flake1/nested-flake2"
(
cd "$TEST_ROOT/issue-13164"
git init
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
cat >flake.nix <<EOF
{
inputs.nestedFlake1.url = "path:./nested-flake1";
outputs = { self, nestedFlake1 }: {
inherit nestedFlake1;
};
}
EOF
cat >nested-flake1/flake.nix <<EOF
{
inputs.nestedFlake2.url = "path:./nested-flake2";
outputs = { self, nestedFlake2 }: {
name = "nestedFlake1";
inherit nestedFlake2;
};
}
EOF
cat >nested-flake1/nested-flake2/flake.nix <<EOF
{
outputs = { self }: {
name = "nestedFlake2";
};
}
EOF
git add .
git commit -m "Initial commit"
# I don't understand why two calls are necessary to reproduce the issue.
nix eval --json .#nestedFlake1.nestedFlake2 --no-eval-cache
nix eval --json .#nestedFlake1.nestedFlake2 --no-eval-cache
)