aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/flake/flake.cc
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2020-01-29 23:12:58 +0100
committerEelco Dolstra <edolstra@gmail.com>2020-01-29 23:14:27 +0100
commitb9fb3720750a24d8b2fbe6b1491696d6a51dcff3 (patch)
tree27bef94799d20261c9b49e43bbcd1907a107fde9 /src/libexpr/flake/flake.cc
parent88b44b1e94735710853bdabb6904073bc77f2ccb (diff)
Add --update-input flag to update a specific flake input
Typical usage: $ nix flake update ~/Misc/eelco-configurations/hagbard --update-input nixpkgs to update the 'nixpkgs' input of a flake while leaving every other input unchanged. The argument is an input path, so you can do e.g. '--update-input dwarffs/nixpkgs' to update an input of an input. Fixes #2928.
Diffstat (limited to 'src/libexpr/flake/flake.cc')
-rw-r--r--src/libexpr/flake/flake.cc53
1 files changed, 38 insertions, 15 deletions
diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc
index c752eeedc..a8f05efb6 100644
--- a/src/libexpr/flake/flake.cc
+++ b/src/libexpr/flake/flake.cc
@@ -394,7 +394,13 @@ LockedFlake lockFlake(
continue;
}
- auto oldLock = oldLocks.inputs.find(id);
+ /* Do we have an entry in the existing lock file? And
+ we don't have a --update-input flag for this
+ input? */
+ auto oldLock =
+ lockFlags.inputUpdates.count(inputPath)
+ ? oldLocks.inputs.end()
+ : oldLocks.inputs.find(id);
if (oldLock != oldLocks.inputs.end() && oldLock->second.originalRef == input.ref && !hasOverride) {
/* Copy the input from the old lock file if its
@@ -402,22 +408,39 @@ LockedFlake lockFlake(
from a higher level flake. */
newLocks.inputs.insert_or_assign(id, oldLock->second);
- /* However there may be new overrides on the
- inputs of this flake, so we need to check those
- (without fetching this flake - we need to be
- lazy). */
- FlakeInputs fakeInputs;
+ /* If we have an --update-input flag for an input
+ of this input, then we must fetch the flake to
+ to update it. */
+ auto lb = lockFlags.inputUpdates.lower_bound(inputPath);
- for (auto & i : oldLock->second.inputs) {
- fakeInputs.emplace(i.first, FlakeInput {
- .ref = i.second.originalRef
- });
- }
+ auto hasChildUpdate =
+ lb != lockFlags.inputUpdates.end()
+ && lb->size() > inputPath.size()
+ && std::equal(inputPath.begin(), inputPath.end(), lb->begin());
+
+ if (hasChildUpdate) {
+ auto inputFlake = getFlake(state, oldLock->second.ref, false, flakeCache);
+
+ updateLocks(inputFlake.inputs,
+ (const LockedInputs &) oldLock->second,
+ newLocks.inputs.find(id)->second,
+ inputPath);
- updateLocks(fakeInputs,
- oldLock->second,
- newLocks.inputs.find(id)->second,
- inputPath);
+ } else {
+ /* No need to fetch this flake, we can be
+ lazy. However there may be new overrides on
+ the inputs of this flake, so we need to
+ check those. */
+ FlakeInputs fakeInputs;
+
+ for (auto & i : oldLock->second.inputs)
+ fakeInputs.emplace(i.first, FlakeInput { .ref = i.second.originalRef });
+
+ updateLocks(fakeInputs,
+ oldLock->second,
+ newLocks.inputs.find(id)->second,
+ inputPath);
+ }
} else {
/* We need to update/create a new lock file