mirror of
https://github.com/NixOS/nix
synced 2025-06-29 23:13:14 +02:00
This requires that we refer to the `sourceInfo` instead of the
`result`. However, `sourceInfo` does not create a chain of basedir
resolution, so we add that back with `flakeDir`.
(cherry picked from commit 2109a5a206
)
109 lines
3.2 KiB
Nix
109 lines
3.2 KiB
Nix
# This is a helper to callFlake() to lazily fetch flake inputs.
|
|
|
|
# The contents of the lock file, in JSON format.
|
|
lockFileStr:
|
|
|
|
# A mapping of lock file node IDs to { sourceInfo, subdir } attrsets,
|
|
# with sourceInfo.outPath providing an SourceAccessor to a previously
|
|
# fetched tree. This is necessary for possibly unlocked inputs, in
|
|
# particular the root input, but also --override-inputs pointing to
|
|
# unlocked trees.
|
|
overrides:
|
|
|
|
# This is `prim_fetchFinalTree`.
|
|
fetchTreeFinal:
|
|
|
|
let
|
|
inherit (builtins) mapAttrs;
|
|
|
|
lockFile = builtins.fromJSON lockFileStr;
|
|
|
|
# Resolve a input spec into a node name. An input spec is
|
|
# either a node name, or a 'follows' path from the root
|
|
# node.
|
|
resolveInput =
|
|
inputSpec: if builtins.isList inputSpec then getInputByPath lockFile.root inputSpec else inputSpec;
|
|
|
|
# Follow an input attrpath (e.g. ["dwarffs" "nixpkgs"]) from the
|
|
# root node, returning the final node.
|
|
getInputByPath =
|
|
nodeName: path:
|
|
if path == [ ] then
|
|
nodeName
|
|
else
|
|
getInputByPath
|
|
# Since this could be a 'follows' input, call resolveInput.
|
|
(resolveInput lockFile.nodes.${nodeName}.inputs.${builtins.head path})
|
|
(builtins.tail path);
|
|
|
|
allNodes = mapAttrs (
|
|
key: node:
|
|
let
|
|
|
|
parentNode = allNodes.${getInputByPath lockFile.root node.parent};
|
|
|
|
flakeDir =
|
|
let
|
|
dir = overrides.${key}.dir or node.locked.path or "";
|
|
parentDir = parentNode.flakeDir;
|
|
in
|
|
if node ? parent then parentDir + ("/" + dir) else dir;
|
|
|
|
sourceInfo =
|
|
if overrides ? ${key} then
|
|
overrides.${key}.sourceInfo
|
|
else if node.locked.type == "path" && builtins.substring 0 1 node.locked.path != "/" then
|
|
parentNode.sourceInfo
|
|
// {
|
|
outPath = parentNode.sourceInfo.outPath + ("/" + flakeDir);
|
|
}
|
|
else
|
|
# FIXME: remove obsolete node.info.
|
|
# Note: lock file entries are always final.
|
|
fetchTreeFinal (node.info or { } // removeAttrs node.locked [ "dir" ]);
|
|
|
|
subdir = overrides.${key}.dir or node.locked.dir or "";
|
|
|
|
outPath = sourceInfo + ((if subdir == "" then "" else "/") + subdir);
|
|
|
|
flake = import (outPath + "/flake.nix");
|
|
|
|
inputs = mapAttrs (inputName: inputSpec: allNodes.${resolveInput inputSpec}.result) (
|
|
node.inputs or { }
|
|
);
|
|
|
|
outputs = flake.outputs (inputs // { self = result; });
|
|
|
|
result =
|
|
outputs
|
|
# We add the sourceInfo attribute for its metadata, as they are
|
|
# relevant metadata for the flake. However, the outPath of the
|
|
# sourceInfo does not necessarily match the outPath of the flake,
|
|
# as the flake may be in a subdirectory of a source.
|
|
# This is shadowed in the next //
|
|
// sourceInfo
|
|
// {
|
|
# This shadows the sourceInfo.outPath
|
|
inherit outPath;
|
|
|
|
inherit inputs;
|
|
inherit outputs;
|
|
inherit sourceInfo;
|
|
_type = "flake";
|
|
};
|
|
|
|
in
|
|
{
|
|
result =
|
|
if node.flake or true then
|
|
assert builtins.isFunction flake.outputs;
|
|
result
|
|
else
|
|
sourceInfo;
|
|
|
|
inherit flakeDir sourceInfo;
|
|
}
|
|
) lockFile.nodes;
|
|
|
|
in
|
|
allNodes.${lockFile.root}.result
|