diff --git a/lib/modules.nix b/lib/modules.nix index 21ffbb9591c5..1adee44f7a33 100644 --- a/lib/modules.nix +++ b/lib/modules.nix @@ -1598,6 +1598,28 @@ let inherit priority content; }; + /** + Applies a function to the value inside a definition, + preserving all surrounding properties (`mkForce`, `mkOrder`, `mkIf`, etc.). + */ + mapDefinitionValue = + f: def: + if def ? _type then + if def._type == "merge" then + def // { contents = map (mapDefinitionValue f) def.contents; } + else if def._type == "if" then + def // { content = mapDefinitionValue f def.content; } + else if def._type == "override" then + def // { content = mapDefinitionValue f def.content; } + else if def._type == "order" then + def // { content = mapDefinitionValue f def.content; } + else if def._type == "definition" then + def // { value = mapDefinitionValue f def.value; } + else + f def + else + f def; + mkBefore = mkOrder 500; defaultOrderPriority = 1000; mkAfter = mkOrder 1500; @@ -2302,6 +2324,7 @@ private importApply importJSON importTOML + mapDefinitionValue mergeDefinitions mergeAttrDefinitionsWithPrio mergeOptionDecls # should be private? diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix index e2872dcafce9..021a7eca25b8 100644 --- a/lib/tests/misc.nix +++ b/lib/tests/misc.nix @@ -5114,4 +5114,96 @@ runTests { ); expected = false; }; + + # mapDefinitionValue + + testMapDefinitionValuePlain = { + expr = lib.modules.mapDefinitionValue (x: x + 1) 5; + expected = 6; + }; + + testMapDefinitionValueMkForce = { + expr = lib.modules.mapDefinitionValue (x: x + 1) (lib.mkForce 5); + expected = lib.mkForce 6; + }; + + testMapDefinitionValueMkDefault = { + expr = lib.modules.mapDefinitionValue (x: x + 1) (lib.mkDefault 5); + expected = lib.mkDefault 6; + }; + + testMapDefinitionValueMkOrder = { + expr = lib.modules.mapDefinitionValue (x: x + 1) (lib.mkOrder 500 5); + expected = lib.mkOrder 500 6; + }; + + testMapDefinitionValueMkOverrideNested = { + expr = lib.modules.mapDefinitionValue (x: x + 1) (lib.mkForce (lib.mkOrder 500 5)); + expected = lib.mkForce (lib.mkOrder 500 6); + }; + + testMapDefinitionValueMkIf = { + expr = lib.modules.mapDefinitionValue (x: x + 1) (lib.mkIf true 5); + expected = lib.mkIf true 6; + }; + + testMapDefinitionValueMkMerge = { + expr = lib.modules.mapDefinitionValue (x: x + 1) ( + lib.mkMerge [ + 5 + 10 + ] + ); + expected = lib.mkMerge [ + 6 + 11 + ]; + }; + + testMapDefinitionValueMkDefinition = { + expr = lib.modules.mapDefinitionValue (x: x + 1) ( + lib.mkDefinition { + file = "test"; + value = 5; + } + ); + expected = lib.mkDefinition { + file = "test"; + value = 6; + }; + }; + + testMapDefinitionValueDeep = { + expr = lib.modules.mapDefinitionValue (x: x + 1) (lib.mkIf true (lib.mkForce (lib.mkOrder 500 5))); + expected = lib.mkIf true (lib.mkForce (lib.mkOrder 500 6)); + }; + + testMapDefinitionValueAllNested = { + expr = lib.modules.mapDefinitionValue (x: x + 1) ( + lib.mkMerge [ + (lib.mkIf true ( + lib.mkForce ( + lib.mkOrder 500 ( + lib.mkDefinition { + file = "test"; + value = lib.mkBefore 5; + } + ) + ) + )) + ] + ); + expected = lib.mkMerge [ + (lib.mkIf true ( + lib.mkForce ( + lib.mkOrder 500 ( + lib.mkDefinition { + file = "test"; + value = lib.mkBefore 6; + } + ) + ) + )) + ]; + }; }