From cecfafe9a4d51050e6ebb2071a2a56093f8979e2 Mon Sep 17 00:00:00 2001 From: Archit Gupta Date: Sun, 10 Mar 2024 18:22:08 -0700 Subject: [PATCH] Set defaults for inputs from flake.lock If the `src` passed to flakelight contains a flake.lock, it will now be read and used to set defaults for `inputs`. Explicitly passed inputs will override this. --- API_GUIDE.md | 27 ++++++++++++++++++-- README.md | 3 +-- builtinModules/autoInputs.nix | 13 ++++++++++ misc/lock2inputs.nix | 46 +++++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 4 deletions(-) create mode 100644 builtinModules/autoInputs.nix create mode 100644 misc/lock2inputs.nix diff --git a/API_GUIDE.md b/API_GUIDE.md index ecb9a3b..6252cd3 100644 --- a/API_GUIDE.md +++ b/API_GUIDE.md @@ -87,8 +87,31 @@ This section covers the options available to modules. Type: AttrsOf FlakeInput ``` -The `inputs` option allows setting the flake inputs used by modules. To set the -nixpkgs used for building outputs, you can pass your flake inputs in as follows: +The `inputs` option is an attrset of the flake inputs used by flakelight +modules. These inputs get passed as the `inputs` module argument, and are used +for `inputs` and `inputs'` in the package set. + +Default values are automatically initialized from your flake inputs by reading +your `flake.lock`. Note that this does not include the `self` argument, which +must be passed explicitly if you want to use it. + +Flakelight will add a recent `nixpkgs` input if your flake does not have one. +Other flakelight modules may provide default inputs for their dependencies. + +To use a different nixpkgs from the built-in default: + +```nix +{ + inputs = { + flakelight.url = "github:nix-community/flakelight"; + nixpkgs.url = "nixpkgs/nixpkgs-unstable"; + }; + outputs = { flakelight, ... }: + flakelight ./. { }; +} +``` + +You can also explicitly pass in inputs, overriding defaults, as follows: ```nix { diff --git a/README.md b/README.md index 0a2a235..e2c059e 100644 --- a/README.md +++ b/README.md @@ -73,9 +73,8 @@ To use a different nixpkgs, you can instead use: nixpkgs.url = "nixpkgs/nixpkgs-unstable"; flakelight.url = "github:nix-community/flakelight"; }; - outputs = { flakelight, ... }@inputs: + outputs = { flakelight, ... }: flakelight ./. { - inherit inputs; devShell.packages = pkgs: [ pkgs.hello pkgs.coreutils ]; }; } diff --git a/builtinModules/autoInputs.nix b/builtinModules/autoInputs.nix new file mode 100644 index 0000000..1c86bb2 --- /dev/null +++ b/builtinModules/autoInputs.nix @@ -0,0 +1,13 @@ +# flakelight -- Framework for simplifying flake setup +# Copyright (C) 2023 Archit Gupta +# SPDX-License-Identifier: MIT + +{ lib, src, ... }: +let + inherit (builtins) mapAttrs pathExists; + inherit (lib) mkOverride; + lock2inputs = import ../misc/lock2inputs.nix { inherit lib; }; + lockFound = pathExists (src + "/flake.lock"); + autoInputs = if lockFound then lock2inputs src else { }; +in +{ config.inputs = mapAttrs (_: mkOverride 950) autoInputs; } diff --git a/misc/lock2inputs.nix b/misc/lock2inputs.nix new file mode 100644 index 0000000..8092aea --- /dev/null +++ b/misc/lock2inputs.nix @@ -0,0 +1,46 @@ +# flakelight -- Framework for simplifying flake setup +# Copyright (C) 2023 Archit Gupta +# SPDX-License-Identifier: MIT + +# Get a flakes inputs +{ lib, ... }: +src: +let + inherit (builtins) fromJSON head isString mapAttrs readFile tail; + inherit (lib) fix; + + json = fromJSON (readFile (src + "/flake.lock")); + inherit (json) nodes; + rootNode = nodes.${json.root}; + + getInputName = base: ref: + let next = getInputName json.root nodes.${base}.inputs.${head ref}; in + if isString ref then ref + else if ref == [ ] then base + else getInputName next (tail ref); + + getInput = ref: resolved.${getInputName json.root ref}; + + fetchNode = node: fetchTree (node.info or { } // + removeAttrs node.locked [ "dir" ]); + + resolveFlakeNode = node: fix (self: + let + sourceInfo = fetchNode node; + outPath = sourceInfo + + (if node.locked ? dir then "/${node.locked.dir}" else ""); + inputs = (mapAttrs (_: getInput) (node.inputs or { })) // + { inherit self; }; + outputs = (import (outPath + "/flake.nix")).outputs inputs; + in + outputs // sourceInfo // { + _type = "flake"; + inherit outPath inputs outputs sourceInfo; + }); + + resolveNode = node: + if node.flake or true then resolveFlakeNode node else fetchNode node; + + resolved = mapAttrs (_: resolveNode) nodes; +in +mapAttrs (_: v: resolved.${v}) rootNode.inputs