1
0
Fork 0
mirror of https://github.com/hercules-ci/flake-parts.git synced 2024-12-15 17:50:53 +00:00
flake-parts/modules/transposition.nix

133 lines
4.5 KiB
Nix
Raw Normal View History

2022-10-26 11:16:04 +00:00
{ config, lib, flake-parts-lib, ... }:
let
inherit (lib)
filterAttrs
mapAttrs
mkOption
types
;
inherit (lib.strings)
escapeNixIdentifier
;
2022-10-26 12:07:24 +00:00
transpositionModule = {
options = {
adHoc = mkOption {
type = types.bool;
default = false;
2022-11-11 06:39:25 +00:00
description = ''
2022-11-11 05:40:37 +00:00
Whether to provide a stub option declaration for {option}`perSystem.<name>`.
2022-10-26 12:07:24 +00:00
The stub option declaration does not support merging and lacks
2022-11-11 05:40:37 +00:00
documentation, so you are recommended to declare the {option}`perSystem.<name>`
option yourself and avoid {option}`adHoc`.
2022-10-26 12:07:24 +00:00
'';
};
};
};
perInputAttributeError = { flake, attrName, system, attrConfig }:
# This uses flake.outPath for lack of a better identifier.
# Consider adding a perInput variation that has a normally-redundant argument for the input name.
# Tested manually with
# perSystem = { inputs', ... }: {
# packages.extra = inputs'.nixpkgs.extra;
# packages.default = inputs'.nixpkgs.packages.default;
# packages.veryWrong = (top.config.perInput "x86_64-linux" inputs'.nixpkgs.legacyPackages.hello).packages.default;
# };
# transposition.extra = {};
let
attrPath = "${escapeNixIdentifier attrName}.${escapeNixIdentifier system}";
flakeIdentifier =
if flake._type or null != "flake"
then
throw "An attempt was made to access attribute ${attrPath} on a value that's supposed to be a flake, but may not be a proper flake."
else
builtins.addErrorContext "while trying to find out how to describe what is supposedly a flake, whose attribute ${attrPath} was accessed but does not exist" (
toString flake.outPath
);
# This ought to be generalized by extending attrConfig, but this is the only known and common mistake for now.
alternateAttrNameHint =
if attrName == "packages" && flake?legacyPackages
then # Unfortunately we can't just switch them out, because that will put packages *sets* where single packages are expected in user code, resulting in potentially much worse and more confusing errors down the line.
"\nIt does define legacyPackages; try that instead?"
else "";
in
if flake?${attrName}
then
throw ''
Attempt to access ${attrPath} of flake ${flakeIdentifier}, but it does not have it.
It does have attribute ${escapeNixIdentifier attrName}, so it appears that it does not support system type ${escapeNixIdentifier system}.
''
else
throw ''
Attempt to access ${attrPath} of flake ${flakeIdentifier}, but it does not have attribute ${escapeNixIdentifier attrName}.${alternateAttrNameHint}
'';
2022-10-26 11:16:04 +00:00
in
{
options = {
transposition = lib.mkOption {
2022-11-11 06:39:25 +00:00
description = ''
2022-10-26 11:16:04 +00:00
A helper that defines transposed attributes in the flake outputs.
2023-10-01 12:34:27 +00:00
When you define `transposition.foo = { };`, definitions are added to the effect of (pseudo-code):
```nix
flake.foo.''${system} = (perSystem system).foo;
perInput = system: inputFlake: inputFlake.foo.''${system};
```
2022-10-26 11:16:04 +00:00
Transposition is the operation that swaps the indices of a data structure.
Here it refers specifically to the transposition between
2022-11-11 05:40:37 +00:00
```plain
perSystem: .''${system}.''${attribute}
outputs: .''${attribute}.''${system}
```
2022-10-26 11:16:04 +00:00
2022-11-11 05:40:37 +00:00
It also defines the reverse operation in [{option}`perInput`](#opt-perInput).
2022-10-26 11:16:04 +00:00
'';
type =
types.lazyAttrsOf
2022-10-26 12:07:24 +00:00
(types.submoduleWith { modules = [ transpositionModule ]; });
2022-10-26 11:16:04 +00:00
};
};
config = {
flake =
lib.mapAttrs
(attrName: attrConfig:
mapAttrs
(system: v: v.${attrName} or (
abort ''
Could not find option ${attrName} in the perSystem module. It is required to declare such an option whenever transposition.<name> is defined (and in this instance <name> is ${attrName}).
''))
2022-10-26 11:16:04 +00:00
config.allSystems
)
config.transposition;
perInput =
system: flake:
mapAttrs
(attrName: attrConfig:
flake.${attrName}.${system} or (
throw (perInputAttributeError { inherit system flake attrName attrConfig; })
)
)
2023-05-29 17:39:48 +00:00
config.transposition;
2022-10-26 12:07:24 +00:00
2023-05-29 17:52:03 +00:00
perSystem = {
2022-10-26 12:07:24 +00:00
options =
mapAttrs
(k: v: lib.mkOption { })
(filterAttrs
(k: v: v.adHoc)
config.transposition
);
};
2022-10-26 11:16:04 +00:00
};
}