aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Bantyev <balsoft@balsoft.ru>2021-12-28 15:30:06 +0300
committerAlexander Bantyev <balsoft@balsoft.ru>2021-12-28 15:30:06 +0300
commit2664a216e57169ec57d7f51be1b8383c1be83fd5 (patch)
tree0e5d590a4b5f0004456c8e8aefea7e7382daeac4
parent0e90b13ab1df925e549b5d55853b65911b4b40d3 (diff)
flake.cc: computeLocks: Only verify overrides when they could change
When we check for disappeared overrides, we can get "false positives" for follows and overrides which are defined in the dependencies of the flake we are locking, since they are not parsed by parseFlakeInputs. However, at that point we already know that the overrides couldn't have possible been changed if the input itself hasn't changed (since we check that oldLock->originalRef == *input.ref for the input's parent). So, to prevent this, only perform this check when it was possible that the flake changed (e.g. the flake we're locking, or a new input, or the input has changed and mustRefetch == true).
-rw-r--r--src/libexpr/flake/flake.cc36
-rw-r--r--tests/flakes.sh10
2 files changed, 25 insertions, 21 deletions
diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc
index b15878d5c..c549c5971 100644
--- a/src/libexpr/flake/flake.cc
+++ b/src/libexpr/flake/flake.cc
@@ -344,7 +344,8 @@ LockedFlake lockFlake(
const InputPath & inputPathPrefix,
std::shared_ptr<const Node> oldNode,
const LockParent & parent,
- const Path & parentPath)>
+ const Path & parentPath,
+ bool trustLock)>
computeLocks;
computeLocks = [&](
@@ -353,7 +354,8 @@ LockedFlake lockFlake(
const InputPath & inputPathPrefix,
std::shared_ptr<const Node> oldNode,
const LockParent & parent,
- const Path & parentPath)
+ const Path & parentPath,
+ bool trustLock)
{
debug("computing lock file node '%s'", printInputPath(inputPathPrefix));
@@ -464,14 +466,20 @@ LockedFlake lockFlake(
.isFlake = (*lockedNode)->isFlake,
});
} else if (auto follows = std::get_if<1>(&i.second)) {
- auto o = input.overrides.find(i.first);
- // If the override disappeared, we have to refetch the flake,
- // since some of the inputs may not be present in the lockfile.
- if (o == input.overrides.end()) {
- mustRefetch = true;
- // There's no point populating the rest of the fake inputs,
- // since we'll refetch the flake anyways.
- break;
+ if (! trustLock) {
+ // It is possible that the flake has changed,
+ // so we must confirm all the follows that are in the lockfile are also in the flake.
+ auto overridePath(inputPath);
+ overridePath.push_back(i.first);
+ auto o = overrides.find(overridePath);
+ // If the override disappeared, we have to refetch the flake,
+ // since some of the inputs may not be present in the lockfile.
+ if (o == overrides.end()) {
+ mustRefetch = true;
+ // There's no point populating the rest of the fake inputs,
+ // since we'll refetch the flake anyways.
+ break;
+ }
}
fakeInputs.emplace(i.first, FlakeInput {
.follows = *follows,
@@ -482,14 +490,14 @@ LockedFlake lockFlake(
LockParent newParent {
.path = inputPath,
- .absolute = false
+ .absolute = true
};
computeLocks(
mustRefetch
? getFlake(state, oldLock->lockedRef, false, flakeCache).inputs
: fakeInputs,
- childNode, inputPath, oldLock, newParent, parentPath);
+ childNode, inputPath, oldLock, newParent, parentPath, !mustRefetch);
} else {
/* We need to create a new lock file entry. So fetch
@@ -546,7 +554,7 @@ LockedFlake lockFlake(
? std::dynamic_pointer_cast<const Node>(oldLock)
: LockFile::read(
inputFlake.sourceInfo->actualPath + "/" + inputFlake.lockedRef.subdir + "/flake.lock").root,
- newParent, localPath);
+ newParent, localPath, false);
}
else {
@@ -574,7 +582,7 @@ LockedFlake lockFlake(
computeLocks(
flake.inputs, newLockFile.root, {},
- lockFlags.recreateLockFile ? nullptr : oldLockFile.root, parent, parentPath);
+ lockFlags.recreateLockFile ? nullptr : oldLockFile.root, parent, parentPath, false);
for (auto & i : lockFlags.inputOverrides)
if (!overridesUsed.count(i.first))
diff --git a/tests/flakes.sh b/tests/flakes.sh
index 942d07010..20e6d09c1 100644
--- a/tests/flakes.sh
+++ b/tests/flakes.sh
@@ -716,11 +716,10 @@ cat > $flakeFollowsA/flake.nix <<EOF
inputs = {
B = {
url = "path:./flakeB";
- inputs.foobar.follows = "D";
- inputs.nonFlake.follows = "D";
+ inputs.foobar.follows = "foobar";
};
- D.url = "path:./flakeD";
+ foobar.url = "path:$flakeFollowsA/flakeE";
};
outputs = { ... }: {};
}
@@ -731,8 +730,6 @@ cat > $flakeFollowsB/flake.nix <<EOF
description = "Flake B";
inputs = {
foobar.url = "path:$flakeFollowsA/flakeE";
- nonFlake.url = "path:$nonFlakeDir";
- goodoo.follows = "C/goodoo";
C = {
url = "path:./flakeC";
inputs.foobar.follows = "foobar";
@@ -747,7 +744,6 @@ cat > $flakeFollowsC/flake.nix <<EOF
description = "Flake C";
inputs = {
foobar.url = "path:$flakeFollowsA/flakeE";
- goodoo.follows = "foobar";
};
outputs = { ... }: {};
}
@@ -785,7 +781,7 @@ newLock="$(cat "$flakeFollowsA/flake.lock")"
diff <(echo "$newLock") <(echo "$oldLock")
[[ $(jq -c .nodes.B.inputs.C $flakeFollowsA/flake.lock) = '"C"' ]]
-[[ $(jq -c .nodes.B.inputs.foobar $flakeFollowsA/flake.lock) = '["D"]' ]]
+[[ $(jq -c .nodes.B.inputs.foobar $flakeFollowsA/flake.lock) = '["foobar"]' ]]
[[ $(jq -c .nodes.C.inputs.foobar $flakeFollowsA/flake.lock) = '["B","foobar"]' ]]
# Ensure removing follows from flake.nix removes them from the lockfile