mirror of
https://github.com/NixOS/nix
synced 2025-07-07 22:33:57 +02:00
Merge pull request #13400 from NixOS/fix-deep-overrides
Fix deep flake input overrides
This commit is contained in:
commit
5879ab1577
2 changed files with 93 additions and 14 deletions
|
@ -101,7 +101,6 @@ static void parseFlakeInputAttr(
|
||||||
|
|
||||||
static FlakeInput parseFlakeInput(
|
static FlakeInput parseFlakeInput(
|
||||||
EvalState & state,
|
EvalState & state,
|
||||||
std::string_view inputName,
|
|
||||||
Value * value,
|
Value * value,
|
||||||
const PosIdx pos,
|
const PosIdx pos,
|
||||||
const InputAttrPath & lockRootAttrPath,
|
const InputAttrPath & lockRootAttrPath,
|
||||||
|
@ -171,8 +170,8 @@ static FlakeInput parseFlakeInput(
|
||||||
input.ref = parseFlakeRef(state.fetchSettings, *url, {}, true, input.isFlake, true);
|
input.ref = parseFlakeRef(state.fetchSettings, *url, {}, true, input.isFlake, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!input.follows && !input.ref)
|
if (input.ref && input.follows)
|
||||||
input.ref = FlakeRef::fromAttrs(state.fetchSettings, {{"type", "indirect"}, {"id", std::string(inputName)}});
|
throw Error("flake input has both a flake reference and a follows attribute, at %s", state.positions[pos]);
|
||||||
|
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
@ -201,7 +200,6 @@ static std::pair<std::map<FlakeId, FlakeInput>, fetchers::Attrs> parseFlakeInput
|
||||||
} else {
|
} else {
|
||||||
inputs.emplace(inputName,
|
inputs.emplace(inputName,
|
||||||
parseFlakeInput(state,
|
parseFlakeInput(state,
|
||||||
inputName,
|
|
||||||
inputAttr.value,
|
inputAttr.value,
|
||||||
inputAttr.pos,
|
inputAttr.pos,
|
||||||
lockRootAttrPath,
|
lockRootAttrPath,
|
||||||
|
@ -483,18 +481,27 @@ LockedFlake lockFlake(
|
||||||
|
|
||||||
/* Get the overrides (i.e. attributes of the form
|
/* Get the overrides (i.e. attributes of the form
|
||||||
'inputs.nixops.inputs.nixpkgs.url = ...'). */
|
'inputs.nixops.inputs.nixpkgs.url = ...'). */
|
||||||
for (auto & [id, input] : flakeInputs) {
|
std::function<void(const FlakeInput & input, const InputAttrPath & prefix)> addOverrides;
|
||||||
|
addOverrides = [&](const FlakeInput & input, const InputAttrPath & prefix)
|
||||||
|
{
|
||||||
for (auto & [idOverride, inputOverride] : input.overrides) {
|
for (auto & [idOverride, inputOverride] : input.overrides) {
|
||||||
auto inputAttrPath(inputAttrPathPrefix);
|
auto inputAttrPath(prefix);
|
||||||
inputAttrPath.push_back(id);
|
|
||||||
inputAttrPath.push_back(idOverride);
|
inputAttrPath.push_back(idOverride);
|
||||||
|
if (inputOverride.ref || inputOverride.follows)
|
||||||
overrides.emplace(inputAttrPath,
|
overrides.emplace(inputAttrPath,
|
||||||
OverrideTarget {
|
OverrideTarget {
|
||||||
.input = inputOverride,
|
.input = inputOverride,
|
||||||
.sourcePath = sourcePath,
|
.sourcePath = sourcePath,
|
||||||
.parentInputAttrPath = inputAttrPathPrefix
|
.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
|
/* Check whether this input has overrides for a
|
||||||
|
@ -550,7 +557,8 @@ LockedFlake lockFlake(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(input.ref);
|
if (!input.ref)
|
||||||
|
input.ref = FlakeRef::fromAttrs(state.fetchSettings, {{"type", "indirect"}, {"id", std::string(id)}});
|
||||||
|
|
||||||
auto overriddenParentPath =
|
auto overriddenParentPath =
|
||||||
input.ref->input.isRelative()
|
input.ref->input.isRelative()
|
||||||
|
|
|
@ -359,3 +359,74 @@ rm "$flakeFollowsCustomUrlA"/flake.lock
|
||||||
json=$(nix flake metadata "$flakeFollowsCustomUrlA" --override-input B/C "$flakeFollowsCustomUrlD" --json)
|
json=$(nix flake metadata "$flakeFollowsCustomUrlA" --override-input B/C "$flakeFollowsCustomUrlD" --json)
|
||||||
echo "$json" | jq .locks.nodes.C.original
|
echo "$json" | jq .locks.nodes.C.original
|
||||||
[[ $(echo "$json" | jq -r .locks.nodes.C.original.path) = './flakeC' ]]
|
[[ $(echo "$json" | jq -r .locks.nodes.C.original.path) = './flakeC' ]]
|
||||||
|
|
||||||
|
# Test deep overrides, e.g. `inputs.B.inputs.C.inputs.D.follows = ...`.
|
||||||
|
|
||||||
|
cat <<EOF > $flakeFollowsD/flake.nix
|
||||||
|
{ outputs = _: {}; }
|
||||||
|
EOF
|
||||||
|
cat <<EOF > $flakeFollowsC/flake.nix
|
||||||
|
{
|
||||||
|
inputs.D.url = "path:nosuchflake";
|
||||||
|
outputs = _: {};
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
cat <<EOF > $flakeFollowsB/flake.nix
|
||||||
|
{
|
||||||
|
inputs.C.url = "path:$flakeFollowsC";
|
||||||
|
outputs = _: {};
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
cat <<EOF > $flakeFollowsA/flake.nix
|
||||||
|
{
|
||||||
|
inputs.B.url = "path:$flakeFollowsB";
|
||||||
|
inputs.D.url = "path:$flakeFollowsD";
|
||||||
|
inputs.B.inputs.C.inputs.D.follows = "D";
|
||||||
|
outputs = _: {};
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
nix flake lock $flakeFollowsA
|
||||||
|
|
||||||
|
[[ $(jq -c .nodes.C.inputs.D $flakeFollowsA/flake.lock) = '["D"]' ]]
|
||||||
|
|
||||||
|
# Test overlapping flake follows: B has D follow C/D, while A has B/C follow C
|
||||||
|
|
||||||
|
cat <<EOF > $flakeFollowsC/flake.nix
|
||||||
|
{
|
||||||
|
inputs.D.url = "path:$flakeFollowsD";
|
||||||
|
outputs = _: {};
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
cat <<EOF > $flakeFollowsB/flake.nix
|
||||||
|
{
|
||||||
|
inputs.C.url = "path:nosuchflake";
|
||||||
|
inputs.D.follows = "C/D";
|
||||||
|
outputs = _: {};
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
cat <<EOF > $flakeFollowsA/flake.nix
|
||||||
|
{
|
||||||
|
inputs.B.url = "path:$flakeFollowsB";
|
||||||
|
inputs.C.url = "path:$flakeFollowsC";
|
||||||
|
inputs.B.inputs.C.follows = "C";
|
||||||
|
outputs = _: {};
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# bug was not triggered without recreating the lockfile
|
||||||
|
nix flake lock $flakeFollowsA --recreate-lock-file
|
||||||
|
|
||||||
|
[[ $(jq -c .nodes.B.inputs.D $flakeFollowsA/flake.lock) = '["B","C","D"]' ]]
|
||||||
|
|
||||||
|
# Check that you can't have both a flakeref and a follows attribute on an input.
|
||||||
|
cat <<EOF > $flakeFollowsB/flake.nix
|
||||||
|
{
|
||||||
|
inputs.C.url = "path:nosuchflake";
|
||||||
|
inputs.D.url = "path:nosuchflake";
|
||||||
|
inputs.D.follows = "C/D";
|
||||||
|
outputs = _: {};
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
expectStderr 1 nix flake lock $flakeFollowsA --recreate-lock-file | grepQuiet "flake input has both a flake reference and a follows attribute"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue