-
Notifications
You must be signed in to change notification settings - Fork 73
Expand file tree
/
Copy pathtransposition.nix
More file actions
132 lines (118 loc) · 4.48 KB
/
Copy pathtransposition.nix
File metadata and controls
132 lines (118 loc) · 4.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
{ config, lib, flake-parts-lib, ... }:
let
inherit (lib)
filterAttrs
mapAttrs
mkOption
types
;
inherit (lib.strings)
escapeNixIdentifier
;
transpositionModule = {
options = {
adHoc = mkOption {
type = types.bool;
default = false;
description = ''
Whether to provide a stub option declaration for {option}`perSystem.<name>`.
The stub option declaration does not support merging and lacks
documentation, so you are recommended to declare the {option}`perSystem.<name>`
option yourself and avoid {option}`adHoc`.
'';
};
};
};
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}
'';
in
{
options = {
transposition = lib.mkOption {
description = ''
A helper that defines transposed attributes in the flake outputs.
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};
```
Transposition is the operation that swaps the indices of a data structure.
Here it refers specifically to the transposition between
```plain
perSystem: .''${system}.''${attribute}
outputs: .''${attribute}.''${system}
```
It also defines the reverse operation in [{option}`perInput`](#opt-perInput).
'';
type =
types.lazyAttrsOf
(types.submoduleWith { modules = [ transpositionModule ]; });
};
};
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}).
''))
config.allSystems
)
config.transposition;
perInput =
system: flake:
mapAttrs
(attrName: attrConfig:
flake.${attrName}.${system} or (
throw (perInputAttributeError { inherit system flake attrName attrConfig; })
)
)
config.transposition;
perSystem = {
options =
mapAttrs
(k: v: lib.mkOption { })
(filterAttrs
(k: v: v.adHoc)
config.transposition
);
};
};
}