mirror of
https://github.com/nix-community/flakelight.git
synced 2024-11-21 23:13:09 +01:00
ff24d5d433
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.
118 lines
3.5 KiB
Nix
118 lines
3.5 KiB
Nix
# flakelight -- Framework for simplifying flake setup
|
|
# Copyright (C) 2023 Archit Gupta <archit@accelbread.com>
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
nixpkgs:
|
|
let
|
|
inherit (builtins) isAttrs isPath readDir;
|
|
inherit (nixpkgs.lib) attrNames composeManyExtensions
|
|
filter findFirst fix genAttrs getValues hasSuffix isFunction isList
|
|
mapAttrsToList pathExists pipe removePrefix removeSuffix evalModules
|
|
mkDefault mkOptionType singleton;
|
|
inherit (nixpkgs.lib.types) coercedTo functionTo listOf;
|
|
inherit (nixpkgs.lib.options) mergeEqualOption mergeOneOption;
|
|
|
|
builtinModules = mapAttrsToList (k: _: ./builtinModules + ("/" + k))
|
|
(readDir ./builtinModules);
|
|
|
|
mkFlake = {
|
|
__functor = self: src: root: (evalModules {
|
|
specialArgs.modulesPath = ./builtinModules;
|
|
modules = builtinModules ++ self.extraModules ++ [
|
|
{ inputs.nixpkgs = mkDefault nixpkgs; }
|
|
{ _module.args = { inherit src flakelight; }; }
|
|
root
|
|
];
|
|
}).config.outputs;
|
|
|
|
# Attributes to allow module flakes to extend mkFlake
|
|
extraModules = [ ];
|
|
extend = (fix (extend': mkFlake': modules: fix (self: mkFlake' // {
|
|
extraModules = mkFlake'.extraModules ++ modules;
|
|
extend = extend' self;
|
|
}))) mkFlake;
|
|
};
|
|
|
|
flakelight = {
|
|
inherit mkFlake supportedSystem autoImport autoImportArgs;
|
|
|
|
types = {
|
|
overlay = mkOptionType {
|
|
name = "overlay";
|
|
description = "nixpkgs overlay";
|
|
descriptionClass = "noun";
|
|
check = isFunction;
|
|
merge = _: defs: composeManyExtensions (getValues defs);
|
|
};
|
|
|
|
packageDef = mkOptionType {
|
|
name = "packageDef";
|
|
description = "package definition";
|
|
descriptionClass = "noun";
|
|
check = isFunction;
|
|
merge = mergeOneOption;
|
|
};
|
|
|
|
path = mkOptionType {
|
|
name = "path";
|
|
description = "path";
|
|
descriptionClass = "noun";
|
|
check = isPath;
|
|
merge = mergeEqualOption;
|
|
};
|
|
|
|
function = mkOptionType {
|
|
name = "function";
|
|
description = "function";
|
|
descriptionClass = "noun";
|
|
check = isFunction;
|
|
merge = mergeOneOption;
|
|
};
|
|
|
|
module = mkOptionType {
|
|
name = "module";
|
|
description = "module";
|
|
descriptionClass = "noun";
|
|
check = x: isPath x || isFunction x || isAttrs x;
|
|
merge = _: defs: { imports = getValues defs; };
|
|
};
|
|
|
|
optListOf = elemType: coercedTo elemType singleton (listOf elemType);
|
|
|
|
optFunctionTo = elemType: coercedTo elemType (x: _: x)
|
|
(functionTo elemType);
|
|
};
|
|
};
|
|
|
|
supportedSystem = { lib, stdenv, ... }:
|
|
lib.meta.availableOn stdenv.hostPlatform;
|
|
|
|
importDir = path: genAttrs
|
|
(pipe (readDir path) [
|
|
attrNames
|
|
(filter (s: s != "default.nix"))
|
|
(filter (hasSuffix ".nix"))
|
|
(map (removeSuffix ".nix"))
|
|
(map (removePrefix "_"))
|
|
])
|
|
(p: import (path + (if pathExists
|
|
(path + "/_${p}.nix") then "/_${p}.nix" else "/${p}.nix")));
|
|
|
|
autoImport = dir: name:
|
|
if isList name
|
|
then findFirst (x: x != null) null (map (autoImport dir) name)
|
|
else
|
|
if pathExists (dir + "/${name}.nix")
|
|
then import (dir + "/${name}.nix")
|
|
else if pathExists (dir + "/${name}/default.nix")
|
|
then import (dir + "/${name}")
|
|
else if pathExists (dir + "/${name}")
|
|
then importDir (dir + "/${name}")
|
|
else null;
|
|
|
|
autoImportArgs = dir: args: name:
|
|
let v = autoImport dir name; in
|
|
if isFunction v then v args else v;
|
|
in
|
|
flakelight
|