How it works
The index
flake.nix declares five inputs: nixpkgs, flake-utils, systems,
flake-parts and flake-compat. Every other flake is an entry in
index.json, keyed by attribute name:
"disko": {"locked": {"lastModified": 1781152676, "narHash": "sha256-RxWs…", "owner": "nix-community", "repo": "disko", "rev": "ff8702b4…", "type": "github"}}
locked is the attribute set a flake.lock entry carries for that flake:
enough for builtins.fetchTree to fetch it in pure evaluation mode.
An entry may also carry "lock": true, meaning a lock file for the flake's
inputs is stored under locks/, named after the revision. See
Lock files.
Evaluation
omniflake.flakes.<name> is produced by lib/load.nix,
which follows the same steps as Nix's
call-flake.nix:
builtins.fetchTreeon the entry'slockedattributes.- Read the flake's lock file: the stored one if
"lock": true, otherwise theflake.lockin the fetched tree, otherwise an empty lock. - For each node in that lock,
fetchTreeon itslockedattributes,importitsflake.nix, and calloutputswith the inputs the lock names. Relativepath:inputs resolve against the parent node's tree. - Return the root node's outputs together with the source metadata
(
outPath,rev,narHash,lastModified,sourceInfo,inputs), the same shape Nix gives a flake.
Every node is pinned by revision and NAR hash, so pure evaluation permits the fetches.
Nothing is fetched until an attribute of the result is forced. Reading
index.json costs an evaluation of a 3 MB JSON file and no network access.
Fetches nothing:
$ nix eval github:fzakaria/omniflake#lib.count
Fetches nh and nothing else:
$ nix eval github:fzakaria/omniflake#flakes.nh.packages.x86_64-linux.default.name
Lock files
Each flake is evaluated from its own lock file, so its inputs are the revisions its author locked.
When a flake ships no flake.lock, or one that does not match its
flake.nix, the lock Nix computes for it is stored in locks/<rev>.json
and the index entry is marked "lock": true. The stored lock is the output
of nix flake metadata --json for that flake: Nix keeps the entries of the
committed lock that still match flake.nix and resolves the rest. See
Building the index.
Overrides
lib/load.nix takes an overrides attribute set. While walking a flake's
lock, any input whose name is in overrides receives the override instead
of the node the lock points to, at every depth. omniflake.flakes.<name>
passes omniflake's five inputs as overrides; omniflake.pinned.<name>
passes none; omniflake.unified.<name> passes an entry for every name in
the index, each one loaded under that same policy, so substitution
continues inside what it substituted. See Unification.