Skip to content

Commit 44b831c

Browse files
Merge master into staging-next
2 parents ac86a85 + cd519af commit 44b831c

File tree

80 files changed

+1436
-802
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+1436
-802
lines changed

lib/modules.nix

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -751,17 +751,47 @@ let
751751
t' = opt.options.type;
752752
mergedType = t.typeMerge t'.functor;
753753
typesMergeable = mergedType != null;
754-
typeSet = if (bothHave "type") && typesMergeable
755-
then { type = mergedType; }
756-
else {};
754+
755+
# TODO: Remove this when all downstream reliances of internals: 'functor.wrapped' are sufficiently migrated.
756+
# A function that adds the deprecated wrapped message to a type.
757+
addDeprecatedWrapped = t:
758+
t // {
759+
functor = t.functor // {
760+
wrapped = t.functor.wrappedDeprecationMessage {
761+
inherit loc;
762+
};
763+
};
764+
};
765+
766+
typeSet =
767+
if opt.options ? type then
768+
if res ? type then
769+
if typesMergeable then
770+
{
771+
type =
772+
if mergedType ? functor.wrappedDeprecationMessage then
773+
addDeprecatedWrapped mergedType
774+
else
775+
mergedType;
776+
}
777+
else
778+
# Keep in sync with the same error below!
779+
throw "The option `${showOption loc}' in `${opt._file}' is already declared in ${showFiles res.declarations}."
780+
else if opt.options.type ? functor.wrappedDeprecationMessage then
781+
{ type = addDeprecatedWrapped opt.options.type; }
782+
else
783+
{}
784+
else
785+
{};
786+
757787
bothHave = k: opt.options ? ${k} && res ? ${k};
758788
in
759789
if bothHave "default" ||
760790
bothHave "example" ||
761791
bothHave "description" ||
762-
bothHave "apply" ||
763-
(bothHave "type" && (! typesMergeable))
792+
bothHave "apply"
764793
then
794+
# Keep in sync with the same error above!
765795
throw "The option `${showOption loc}' in `${opt._file}' is already declared in ${showFiles res.declarations}."
766796
else
767797
let

lib/tests/modules.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,14 @@ checkConfigOutput '^true$' config.conditionalWorks ./declare-attrsOf.nix ./attrs
386386
checkConfigOutput '^false$' config.conditionalWorks ./declare-lazyAttrsOf.nix ./attrsOf-conditional-check.nix
387387
checkConfigOutput '^"empty"$' config.value.foo ./declare-lazyAttrsOf.nix ./attrsOf-conditional-check.nix
388388

389+
# Check attrsWith type merging
390+
checkConfigError 'The option `mergedLazyNonLazy'\'' in `.*'\'' is already declared in `.*'\''\.' options.mergedLazyNonLazy ./lazy-attrsWith.nix
391+
checkConfigOutput '^11$' config.lazyResult ./lazy-attrsWith.nix
392+
checkConfigError 'infinite recursion encountered' config.nonLazyResult ./lazy-attrsWith.nix
393+
394+
# Test the attrsOf functor.wrapped warning
395+
# shellcheck disable=2016
396+
NIX_ABORT_ON_WARN=1 checkConfigError 'The deprecated `type.functor.wrapped` attribute of the option `mergedLazyLazy` is accessed, use `nestedTypes.elemType` instead.' options.mergedLazyLazy.type.functor.wrapped ./lazy-attrsWith.nix
389397

390398
# Even with multiple assignments, a type error should be thrown if any of them aren't valid
391399
checkConfigError 'A definition for option .* is not of type .*' \
@@ -575,6 +583,7 @@ checkConfigOutput '^38|27$' options.submoduleLine38.declarationPositions.1.line
575583
# nested options work
576584
checkConfigOutput '^34$' options.nested.nestedLine34.declarationPositions.0.line ./declaration-positions.nix
577585

586+
578587
cat <<EOF
579588
====== module tests ======
580589
$pass Pass
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Check that AttrsWith { lazy = true; } is lazy
2+
{ lib, ... }:
3+
let
4+
inherit (lib) types mkOption;
5+
6+
lazyAttrsOf = mkOption {
7+
# Same as lazyAttrsOf
8+
type = types.attrsWith {
9+
lazy = true;
10+
elemType = types.int;
11+
};
12+
};
13+
14+
attrsOf = mkOption {
15+
# Same as lazyAttrsOf
16+
type = types.attrsWith {
17+
elemType = types.int;
18+
};
19+
};
20+
in
21+
{
22+
imports = [
23+
# Module A
24+
(
25+
{ ... }:
26+
{
27+
options.mergedLazyLazy = lazyAttrsOf;
28+
options.mergedLazyNonLazy = lazyAttrsOf;
29+
options.mergedNonLazyNonLazy = attrsOf;
30+
}
31+
)
32+
# Module B
33+
(
34+
{ ... }:
35+
{
36+
options.mergedLazyLazy = lazyAttrsOf;
37+
options.mergedLazyNonLazy = attrsOf;
38+
options.mergedNonLazyNonLazy = attrsOf;
39+
}
40+
)
41+
# Result
42+
(
43+
{ config, ... }:
44+
{
45+
# Can only evaluate if lazy
46+
config.mergedLazyLazy.bar = config.mergedLazyLazy.baz + 1;
47+
config.mergedLazyLazy.baz = 10;
48+
options.lazyResult = mkOption { default = config.mergedLazyLazy.bar; };
49+
50+
# Can not only evaluate if not lazy
51+
config.mergedNonLazyNonLazy.bar = config.mergedNonLazyNonLazy.baz + 1;
52+
config.mergedNonLazyNonLazy.baz = 10;
53+
options.nonLazyResult = mkOption { default = config.mergedNonLazyNonLazy.bar; };
54+
}
55+
)
56+
];
57+
}

lib/types.nix

Lines changed: 76 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -83,35 +83,39 @@ rec {
8383
# Default type merging function
8484
# takes two type functors and return the merged type
8585
defaultTypeMerge = f: f':
86-
let mergedWrapped = f.wrapped.typeMerge f'.wrapped.functor;
87-
mergedPayload = f.binOp f.payload f'.payload;
86+
let
87+
mergedWrapped = f.wrapped.typeMerge f'.wrapped.functor;
88+
mergedPayload = f.binOp f.payload f'.payload;
8889

89-
hasPayload = assert (f'.payload != null) == (f.payload != null); f.payload != null;
90-
hasWrapped = assert (f'.wrapped != null) == (f.wrapped != null); f.wrapped != null;
90+
hasPayload = assert (f'.payload != null) == (f.payload != null); f.payload != null;
91+
hasWrapped = assert (f'.wrapped != null) == (f.wrapped != null); f.wrapped != null;
92+
93+
typeFromPayload = if mergedPayload == null then null else f.type mergedPayload;
94+
typeFromWrapped = if mergedWrapped == null then null else f.type mergedWrapped;
9195
in
9296
# Abort early: cannot merge different types
9397
if f.name != f'.name
9498
then null
9599
else
96100

97101
if hasPayload then
98-
if hasWrapped then
102+
# Just return the payload if returning wrapped is deprecated
103+
if f ? wrappedDeprecationMessage then
104+
typeFromPayload
105+
else if hasWrapped then
99106
# Has both wrapped and payload
100107
throw ''
101108
Type ${f.name} defines both `functor.payload` and `functor.wrapped` at the same time, which is not supported.
102109
103110
Use either `functor.payload` or `functor.wrapped` but not both.
104111
105-
If your code worked before remove `functor.payload` from the type definition.
112+
If your code worked before remove either `functor.wrapped` or `functor.payload` from the type definition.
106113
''
107114
else
108-
# Has payload
109-
if mergedPayload == null then null else f.type mergedPayload
115+
typeFromPayload
110116
else
111117
if hasWrapped then
112-
# Has wrapped
113-
# TODO(@hsjobeki): This could also be a warning and removed in the future
114-
if mergedWrapped == null then null else f.type mergedWrapped
118+
typeFromWrapped
115119
else
116120
f.type;
117121

@@ -582,48 +586,78 @@ rec {
582586
substSubModules = m: nonEmptyListOf (elemType.substSubModules m);
583587
};
584588

585-
attrsOf = elemType: mkOptionType rec {
586-
name = "attrsOf";
587-
description = "attribute set of ${optionDescriptionPhrase (class: class == "noun" || class == "composite") elemType}";
588-
descriptionClass = "composite";
589-
check = isAttrs;
590-
merge = loc: defs:
591-
mapAttrs (n: v: v.value) (filterAttrs (n: v: v ? value) (zipAttrsWith (name: defs:
592-
(mergeDefinitions (loc ++ [name]) elemType defs).optionalValue
593-
)
594-
# Push down position info.
595-
(map (def: mapAttrs (n: v: { inherit (def) file; value = v; }) def.value) defs)));
596-
emptyValue = { value = {}; };
597-
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name>"]);
598-
getSubModules = elemType.getSubModules;
599-
substSubModules = m: attrsOf (elemType.substSubModules m);
600-
functor = (defaultFunctor name) // { wrapped = elemType; };
601-
nestedTypes.elemType = elemType;
602-
};
589+
attrsOf = elemType: attrsWith { inherit elemType; };
603590

604591
# A version of attrsOf that's lazy in its values at the expense of
605592
# conditional definitions not working properly. E.g. defining a value with
606593
# `foo.attr = mkIf false 10`, then `foo ? attr == true`, whereas with
607594
# attrsOf it would correctly be `false`. Accessing `foo.attr` would throw an
608595
# error that it's not defined. Use only if conditional definitions don't make sense.
609-
lazyAttrsOf = elemType: mkOptionType rec {
610-
name = "lazyAttrsOf";
611-
description = "lazy attribute set of ${optionDescriptionPhrase (class: class == "noun" || class == "composite") elemType}";
596+
lazyAttrsOf = elemType: attrsWith { inherit elemType; lazy = true; };
597+
598+
# base type for lazyAttrsOf and attrsOf
599+
attrsWith =
600+
let
601+
# Push down position info.
602+
pushPositions = map (def: mapAttrs (n: v: { inherit (def) file; value = v; }) def.value);
603+
binOp = lhs: rhs:
604+
let
605+
elemType = lhs.elemType.typeMerge rhs.elemType.functor;
606+
lazy =
607+
if lhs.lazy == rhs.lazy then
608+
lhs.lazy
609+
else
610+
null;
611+
in
612+
if elemType == null || lazy == null then
613+
null
614+
else
615+
{
616+
inherit elemType lazy;
617+
};
618+
in
619+
{
620+
elemType,
621+
lazy ? false,
622+
}:
623+
mkOptionType {
624+
name = if lazy then "lazyAttrsOf" else "attrsOf";
625+
description = (if lazy then "lazy attribute set" else "attribute set") + " of ${optionDescriptionPhrase (class: class == "noun" || class == "composite") elemType}";
612626
descriptionClass = "composite";
613627
check = isAttrs;
614-
merge = loc: defs:
615-
zipAttrsWith (name: defs:
616-
let merged = mergeDefinitions (loc ++ [name]) elemType defs;
617-
# mergedValue will trigger an appropriate error when accessed
618-
in merged.optionalValue.value or elemType.emptyValue.value or merged.mergedValue
619-
)
620-
# Push down position info.
621-
(map (def: mapAttrs (n: v: { inherit (def) file; value = v; }) def.value) defs);
628+
merge = if lazy then (
629+
# Lazy merge Function
630+
loc: defs:
631+
zipAttrsWith (name: defs:
632+
let merged = mergeDefinitions (loc ++ [name]) elemType defs;
633+
# mergedValue will trigger an appropriate error when accessed
634+
in merged.optionalValue.value or elemType.emptyValue.value or merged.mergedValue
635+
)
636+
# Push down position info.
637+
(pushPositions defs)
638+
) else (
639+
# Non-lazy merge Function
640+
loc: defs:
641+
mapAttrs (n: v: v.value) (filterAttrs (n: v: v ? value) (zipAttrsWith (name: defs:
642+
(mergeDefinitions (loc ++ [name]) elemType (defs)).optionalValue
643+
)
644+
# Push down position info.
645+
(pushPositions defs)))
646+
);
622647
emptyValue = { value = {}; };
623648
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name>"]);
624649
getSubModules = elemType.getSubModules;
625-
substSubModules = m: lazyAttrsOf (elemType.substSubModules m);
626-
functor = (defaultFunctor name) // { wrapped = elemType; };
650+
substSubModules = m: attrsWith { elemType = elemType.substSubModules m; inherit lazy; };
651+
functor = defaultFunctor "attrsWith" // {
652+
wrappedDeprecationMessage = { loc }: lib.warn ''
653+
The deprecated `type.functor.wrapped` attribute of the option `${showOption loc}` is accessed, use `type.nestedTypes.elemType` instead.
654+
'' elemType;
655+
payload = {
656+
# Important!: Add new function attributes here in case of future changes
657+
inherit elemType lazy;
658+
};
659+
inherit binOp;
660+
};
627661
nestedTypes.elemType = elemType;
628662
};
629663

nixos/doc/manual/release-notes/rl-2505.section.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@
5555

5656
- `gkraken` software and `hardware.gkraken.enable` option have been removed, use `coolercontrol` via `programs.coolercontrol.enable` option instead.
5757

58+
- `containerd` has been updated to v2, which contains breaking changes. See the [containerd
59+
2.0](https://github.com/containerd/containerd/blob/main/docs/containerd-2.0.md) documentation for more
60+
details.
61+
5862
- the notmuch vim plugin now lives in a separate output of the `notmuch`
5963
package. Installing `notmuch` will not bring the notmuch vim package anymore,
6064
add `vimPlugins.notmuch-vim` to your (Neo)vim configuration if you want the

nixos/modules/services/misc/signald.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ in
4949
User = cfg.user;
5050
Group = cfg.group;
5151
ExecStart = "${pkgs.signald}/bin/signald -d ${dataDir} -s ${cfg.socketPath}";
52+
ExecStartPre = "${pkgs.signald}/bin/signald -d ${dataDir} -s ${cfg.socketPath} --migrate-data";
5253
Restart = "on-failure";
5354
StateDirectory = "signald";
5455
RuntimeDirectory = "signald";

nixos/modules/services/networking/kea.nix

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ in
115115
name = "/var/lib/kea/dhcp4.leases";
116116
};
117117
subnet4 = [ {
118+
id = 1;
118119
subnet = "192.0.2.0/24";
119120
pools = [ {
120121
pool = "192.0.2.100 - 192.0.2.240";
@@ -176,6 +177,7 @@ in
176177
name = "/var/lib/kea/dhcp6.leases";
177178
};
178179
subnet6 = [ {
180+
id = 1;
179181
subnet = "2001:db8:1::/64";
180182
pools = [ {
181183
pool = "2001:db8:1::1-2001:db8:1::ffff";

nixos/modules/services/networking/networkd-dispatcher.nix

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,15 @@ in {
6262
});
6363
};
6464

65+
extraArgs = mkOption {
66+
type = types.listOf types.str;
67+
default = [ ];
68+
description = ''
69+
Extra arguments to pass to the networkd-dispatcher command.
70+
'';
71+
apply = escapeShellArgs;
72+
};
73+
6574
};
6675
};
6776

@@ -71,28 +80,29 @@ in {
7180
packages = [ pkgs.networkd-dispatcher ];
7281
services.networkd-dispatcher = {
7382
wantedBy = [ "multi-user.target" ];
74-
# Override existing ExecStart definition
75-
serviceConfig.ExecStart = let
76-
scriptDir = pkgs.symlinkJoin {
77-
name = "networkd-dispatcher-script-dir";
78-
paths = lib.mapAttrsToList (name: cfg:
79-
(map(state:
80-
pkgs.writeTextFile {
81-
inherit name;
82-
text = cfg.script;
83-
destination = "/${state}.d/${name}";
84-
executable = true;
85-
}
86-
) cfg.onState)
87-
) cfg.rules;
88-
};
89-
in [
90-
""
91-
"${pkgs.networkd-dispatcher}/bin/networkd-dispatcher -v --script-dir ${scriptDir} $networkd_dispatcher_args"
92-
];
83+
environment.networkd_dispatcher_args = cfg.extraArgs;
9384
};
9485
};
9586

87+
services.networkd-dispatcher.extraArgs = let
88+
scriptDir = pkgs.symlinkJoin {
89+
name = "networkd-dispatcher-script-dir";
90+
paths = lib.mapAttrsToList (name: cfg:
91+
(map(state:
92+
pkgs.writeTextFile {
93+
inherit name;
94+
text = cfg.script;
95+
destination = "/${state}.d/${name}";
96+
executable = true;
97+
}
98+
) cfg.onState)
99+
) cfg.rules;
100+
};
101+
in [
102+
"--verbose"
103+
"--script-dir" "${scriptDir}"
104+
];
105+
96106
};
97107
}
98108

0 commit comments

Comments
 (0)