aboutsummaryrefslogtreecommitdiff
path: root/src/nix/flake.cc
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2020-06-11 14:40:21 +0200
committerEelco Dolstra <edolstra@gmail.com>2020-06-11 14:40:21 +0200
commit0c62b4ad0f80d2801a7e7caabf20cc8e50182540 (patch)
tree583ef5ad90342e0d789d21ec748d650c91367992 /src/nix/flake.cc
parent195ed43b60cc2a2a18adc24e272a3d90466c9bc7 (diff)
Represent 'follows' inputs explicitly in the lock file
This fixes an issue where lockfile generation was not idempotent: after updating a lockfile, a "follows" node would end up pointing to a new copy of the node, rather than to the original node.
Diffstat (limited to 'src/nix/flake.cc')
-rw-r--r--src/nix/flake.cc42
1 files changed, 24 insertions, 18 deletions
diff --git a/src/nix/flake.cc b/src/nix/flake.cc
index 865ac8cb8..57c5478c3 100644
--- a/src/nix/flake.cc
+++ b/src/nix/flake.cc
@@ -169,15 +169,21 @@ struct CmdFlakeListInputs : FlakeCommand, MixJSON
recurse = [&](const Node & node, const std::string & prefix)
{
for (const auto & [i, input] : enumerate(node.inputs)) {
- bool firstVisit = visited.insert(input.second).second;
bool last = i + 1 == node.inputs.size();
- auto lockedNode = std::dynamic_pointer_cast<const LockedNode>(input.second);
- logger->stdout("%s" ANSI_BOLD "%s" ANSI_NORMAL ": %s",
- prefix + (last ? treeLast : treeConn), input.first,
- lockedNode ? lockedNode->lockedRef : flake.flake.lockedRef);
+ if (auto lockedNode = std::get_if<0>(&input.second)) {
+ logger->stdout("%s" ANSI_BOLD "%s" ANSI_NORMAL ": %s",
+ prefix + (last ? treeLast : treeConn), input.first,
+ *lockedNode ? (*lockedNode)->lockedRef : flake.flake.lockedRef);
- if (firstVisit) recurse(*input.second, prefix + (last ? treeNull : treeLine));
+ bool firstVisit = visited.insert(*lockedNode).second;
+
+ if (firstVisit) recurse(**lockedNode, prefix + (last ? treeNull : treeLine));
+ } else if (auto follows = std::get_if<1>(&input.second)) {
+ logger->stdout("%s" ANSI_BOLD "%s" ANSI_NORMAL " follows input '%s'",
+ prefix + (last ? treeLast : treeConn), input.first,
+ printInputPath(*follows));
+ }
}
};
@@ -723,18 +729,18 @@ struct CmdFlakeArchive : FlakeCommand, MixJSON, MixDryRun
traverse = [&](const Node & node, std::optional<JSONObject> & jsonObj)
{
auto jsonObj2 = jsonObj ? jsonObj->object("inputs") : std::optional<JSONObject>();
- for (auto & input : node.inputs) {
- auto lockedInput = std::dynamic_pointer_cast<const LockedNode>(input.second);
- assert(lockedInput);
- auto jsonObj3 = jsonObj2 ? jsonObj2->object(input.first) : std::optional<JSONObject>();
- auto storePath =
- dryRun
- ? lockedInput->lockedRef.input.computeStorePath(*store)
- : lockedInput->lockedRef.input.fetch(store).first.storePath;
- if (jsonObj3)
- jsonObj3->attr("path", store->printStorePath(storePath));
- sources.insert(std::move(storePath));
- traverse(*lockedInput, jsonObj3);
+ for (auto & [inputName, input] : node.inputs) {
+ if (auto inputNode = std::get_if<0>(&input)) {
+ auto jsonObj3 = jsonObj2 ? jsonObj2->object(inputName) : std::optional<JSONObject>();
+ auto storePath =
+ dryRun
+ ? (*inputNode)->lockedRef.input.computeStorePath(*store)
+ : (*inputNode)->lockedRef.input.fetch(store).first.storePath;
+ if (jsonObj3)
+ jsonObj3->attr("path", store->printStorePath(storePath));
+ sources.insert(std::move(storePath));
+ traverse(**inputNode, jsonObj3);
+ }
}
};