1
1
forked from extern/flakelight

Allow bundlers to be functions that take pkgs

In addition to a regular bundler of the form `x: x`, this allows setting
bundler options to a function of the form `pkgs: x: x` which is passed
the package set for the system (for example: `{ hello, ... }: x: hello`
to always return hello). This allows, in particular, an autoloaded
bundler in its own file to access the package set.

This is non-trivial as we must tell `x: x` and `pkgs: x: x` apart.

Fortunately, given some derivation `drv`, `pkgs // drv` is a valid
derivation and a set with attr names matching pkgs. When applying this
to the function, if it returns a derivation, it was of the `x: x` form,
and if it returns a function, it was of the `pkgs: x: x` form.

In order to prevent IFD when evaluating the flake if the bundler is of
form `x: x` and uses IFD, we determine the form and apply pkgs when
applying the bundler instead of during flake evaluation. This is done by
wrapping the bundler.

Of note, we cannot rely on `builtins.functionArgs`, since
`pkgs: { hello, ... }: (x: hello) pkgs` is the same as the inner
function but with args hidden.
This commit is contained in:
Archit Gupta 2023-11-06 23:13:47 -08:00
parent d7c7f4634a
commit ff24d5d433
2 changed files with 16 additions and 7 deletions

View File

@ -4,21 +4,22 @@
{ config, lib, flakelight, ... }:
let
inherit (lib) mkMerge mkOption mkIf;
inherit (lib.types) functionTo lazyAttrsOf nullOr package uniq;
inherit (flakelight.types) optFunctionTo;
inherit (lib) isFunction mapAttrs mkMerge mkOption mkIf;
inherit (lib.types) lazyAttrsOf nullOr;
inherit (flakelight.types) function optFunctionTo;
bundler = uniq (functionTo package);
wrapBundler = pkgs: bundler: drv:
if isFunction (bundler (pkgs // drv)) then bundler pkgs drv else bundler drv;
in
{
options = {
bundler = mkOption {
type = nullOr bundler;
type = nullOr function;
default = null;
};
bundlers = mkOption {
type = nullOr (optFunctionTo (lazyAttrsOf bundler));
type = nullOr (optFunctionTo (lazyAttrsOf function));
default = { };
};
};
@ -30,7 +31,7 @@ in
(mkIf (config.bundlers != null) {
perSystem = pkgs: {
bundlers = config.bundlers pkgs;
bundlers = mapAttrs (_: wrapBundler pkgs) (config.bundlers pkgs);
};
})
];

View File

@ -61,6 +61,14 @@ let
merge = mergeEqualOption;
};
function = mkOptionType {
name = "function";
description = "function";
descriptionClass = "noun";
check = isFunction;
merge = mergeOneOption;
};
module = mkOptionType {
name = "module";
description = "module";