aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/flake/flake.cc
diff options
context:
space:
mode:
authorMaximilian Bosch <maximilian@mbosch.me>2024-05-04 08:52:29 +0000
committerGerrit Code Review <gerrit@lix>2024-05-04 08:52:29 +0000
commit799d0132f0797f59cda8c66cde968aba8c3486c3 (patch)
tree804ea4829bb1798a644e3199d27a65dea6b80769 /src/libexpr/flake/flake.cc
parent79d0ae667066b758fd4202cd18294a0f40ddc8f0 (diff)
parent0e38720502c10ddba4afb8c49532b69be83e23a7 (diff)
Merge "Revert "Revert "Merge pull request #6621 from Kha/nested-follows""" into main
Diffstat (limited to 'src/libexpr/flake/flake.cc')
-rw-r--r--src/libexpr/flake/flake.cc47
1 files changed, 34 insertions, 13 deletions
diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc
index 4cc2ab43b..e13d1cb93 100644
--- a/src/libexpr/flake/flake.cc
+++ b/src/libexpr/flake/flake.cc
@@ -91,11 +91,11 @@ static void expectType(EvalState & state, ValueType type,
static std::map<FlakeId, FlakeInput> parseFlakeInputs(
EvalState & state, Value * value, const PosIdx pos,
- const std::optional<Path> & baseDir, InputPath lockRootPath);
+ const std::optional<Path> & baseDir, InputPath lockRootPath, unsigned depth);
static FlakeInput parseFlakeInput(EvalState & state,
const std::string & inputName, Value * value, const PosIdx pos,
- const std::optional<Path> & baseDir, InputPath lockRootPath)
+ const std::optional<Path> & baseDir, InputPath lockRootPath, unsigned depth)
{
expectType(state, nAttrs, *value, pos);
@@ -119,7 +119,7 @@ static FlakeInput parseFlakeInput(EvalState & state,
expectType(state, nBool, *attr.value, attr.pos);
input.isFlake = attr.value->boolean;
} else if (attr.name == sInputs) {
- input.overrides = parseFlakeInputs(state, attr.value, attr.pos, baseDir, lockRootPath);
+ input.overrides = parseFlakeInputs(state, attr.value, attr.pos, baseDir, lockRootPath, depth + 1);
} else if (attr.name == sFollows) {
expectType(state, nString, *attr.value, attr.pos);
auto follows(parseInputPath(attr.value->string.s));
@@ -168,7 +168,11 @@ static FlakeInput parseFlakeInput(EvalState & state,
input.ref = parseFlakeRef(*url, baseDir, true, input.isFlake);
}
- if (!input.follows && !input.ref)
+ if (!input.follows && !input.ref && depth == 0)
+ // in `input.nixops.inputs.nixpkgs.url = ...`, we assume `nixops` is from
+ // the flake registry absent `ref`/`follows`, but we should not assume so
+ // about `nixpkgs` (where `depth == 1`) as the `nixops` flake should
+ // determine its default source
input.ref = FlakeRef::fromAttrs({{"type", "indirect"}, {"id", inputName}});
return input;
@@ -176,7 +180,7 @@ static FlakeInput parseFlakeInput(EvalState & state,
static std::map<FlakeId, FlakeInput> parseFlakeInputs(
EvalState & state, Value * value, const PosIdx pos,
- const std::optional<Path> & baseDir, InputPath lockRootPath)
+ const std::optional<Path> & baseDir, InputPath lockRootPath, unsigned depth)
{
std::map<FlakeId, FlakeInput> inputs;
@@ -189,7 +193,8 @@ static std::map<FlakeId, FlakeInput> parseFlakeInputs(
inputAttr.value,
inputAttr.pos,
baseDir,
- lockRootPath));
+ lockRootPath,
+ depth));
}
return inputs;
@@ -239,7 +244,7 @@ static Flake getFlake(
auto sInputs = state.symbols.create("inputs");
if (auto inputs = vInfo.attrs->get(sInputs))
- flake.inputs = parseFlakeInputs(state, inputs->value, inputs->pos, flakeDir, lockRootPath);
+ flake.inputs = parseFlakeInputs(state, inputs->value, inputs->pos, flakeDir, lockRootPath, 0);
auto sOutputs = state.symbols.create("outputs");
@@ -322,6 +327,19 @@ Flake getFlake(EvalState & state, const FlakeRef & originalRef, bool allowLookup
return getFlake(state, originalRef, allowLookup, flakeCache);
}
+/* Recursively merge `overrides` into `overrideMap` */
+static void updateOverrides(std::map<InputPath, FlakeInput> & overrideMap, const FlakeInputs & overrides,
+ const InputPath & inputPathPrefix)
+{
+ for (auto & [id, input] : overrides) {
+ auto inputPath(inputPathPrefix);
+ inputPath.push_back(id);
+ // Do not override existing assignment from outer flake
+ overrideMap.insert({inputPath, input});
+ updateOverrides(overrideMap, input.overrides, inputPath);
+ }
+}
+
/* Compute an in-memory lock file for the specified top-level flake,
and optionally write it to file, if the flake is writable. */
LockedFlake lockFlake(
@@ -394,12 +412,9 @@ LockedFlake lockFlake(
/* Get the overrides (i.e. attributes of the form
'inputs.nixops.inputs.nixpkgs.url = ...'). */
for (auto & [id, input] : flakeInputs) {
- for (auto & [idOverride, inputOverride] : input.overrides) {
- auto inputPath(inputPathPrefix);
- inputPath.push_back(id);
- inputPath.push_back(idOverride);
- overrides.insert_or_assign(inputPath, inputOverride);
- }
+ auto inputPath(inputPathPrefix);
+ inputPath.push_back(id);
+ updateOverrides(overrides, input.overrides, inputPath);
}
/* Check whether this input has overrides for a
@@ -434,6 +449,12 @@ LockedFlake lockFlake(
// Respect the “flakeness” of the input even if we
// override it
i->second.isFlake = input2.isFlake;
+ if (!i->second.ref)
+ i->second.ref = input2.ref;
+ if (!i->second.follows)
+ i->second.follows = input2.follows;
+ // Note that `input.overrides` is not used in the following,
+ // so no need to merge it here (already done by `updateOverrides`)
}
auto & input = hasOverride ? i->second : input2;