From cc2394d9fac9995ca0ee48c35c718a0b995c3d24 Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Sun, 7 Jun 2026 08:10:02 -0400 Subject: [PATCH 01/14] pkgs.formats.ini: share ignoredArgs between ini generators --- pkgs/pkgs-lib/formats.nix | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/pkgs/pkgs-lib/formats.nix b/pkgs/pkgs-lib/formats.nix index 2f3e5ad9d191..3d0f800873d2 100644 --- a/pkgs/pkgs-lib/formats.nix +++ b/pkgs/pkgs-lib/formats.nix @@ -256,6 +256,11 @@ optionalAttrs allowAliases aliases mapAttrs (key: val: if isList val then listToValue val else val) else id; + + ignoredArgs = [ + "listToValue" + "atomsCoercedToLists" + ]; in { ini = @@ -287,12 +292,7 @@ optionalAttrs allowAliases aliases name: value: pipe value [ (mapAttrs (_: maybeToList listToValue)) - (toINI ( - removeAttrs args [ - "listToValue" - "atomsCoercedToLists" - ] - )) + (toINI (removeAttrs args ignoredArgs)) (pkgs.writeText name) ]; }; @@ -341,15 +341,10 @@ optionalAttrs allowAliases aliases ... }: pkgs.writeText name ( - toINIWithGlobalSection - (removeAttrs args [ - "listToValue" - "atomsCoercedToLists" - ]) - { - globalSection = maybeToList listToValue globalSection; - sections = mapAttrs (_: maybeToList listToValue) sections; - } + toINIWithGlobalSection (removeAttrs args ignoredArgs) { + globalSection = maybeToList listToValue globalSection; + sections = mapAttrs (_: maybeToList listToValue) sections; + } ); }; From 3198ae073a62c8e7565e62d0117a8926e88fc9ef Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Sun, 7 Jun 2026 08:11:43 -0400 Subject: [PATCH 02/14] pkgs.formats.ini: rename list coercion helper It coerces lists, it doesn't turn other attributes into lists. --- pkgs/pkgs-lib/formats.nix | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/pkgs-lib/formats.nix b/pkgs/pkgs-lib/formats.nix index 3d0f800873d2..72586dca934d 100644 --- a/pkgs/pkgs-lib/formats.nix +++ b/pkgs/pkgs-lib/formats.nix @@ -250,7 +250,7 @@ optionalAttrs allowAliases aliases description = "section of an INI file (attrs of " + atom.description + ")"; }; - maybeToList = + maybeCoerceList = listToValue: if listToValue != null then mapAttrs (key: val: if isList val then listToValue val else val) @@ -291,7 +291,7 @@ optionalAttrs allowAliases aliases generate = name: value: pipe value [ - (mapAttrs (_: maybeToList listToValue)) + (mapAttrs (_: maybeCoerceList listToValue)) (toINI (removeAttrs args ignoredArgs)) (pkgs.writeText name) ]; @@ -342,8 +342,8 @@ optionalAttrs allowAliases aliases }: pkgs.writeText name ( toINIWithGlobalSection (removeAttrs args ignoredArgs) { - globalSection = maybeToList listToValue globalSection; - sections = mapAttrs (_: maybeToList listToValue) sections; + globalSection = maybeCoerceList listToValue globalSection; + sections = mapAttrs (_: maybeCoerceList listToValue) sections; } ); }; From 8217bcabaf9cb25361e1168a2c24089989ae98ac Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Sun, 7 Jun 2026 08:17:54 -0400 Subject: [PATCH 03/14] pkgs.formats.ini: add helper to coerce all lists more lazily Before, we would run a mapAttrs on every attribute, checking listToValue on each of them. But listToValue is known ahead of time. Instead, we can only run that map if listToValue isn't null in the first place. --- pkgs/pkgs-lib/formats.nix | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pkgs/pkgs-lib/formats.nix b/pkgs/pkgs-lib/formats.nix index 72586dca934d..5ed60f3bd05c 100644 --- a/pkgs/pkgs-lib/formats.nix +++ b/pkgs/pkgs-lib/formats.nix @@ -256,6 +256,12 @@ optionalAttrs allowAliases aliases mapAttrs (key: val: if isList val then listToValue val else val) else id; + maybeCoerceAllLists = + listToValue: + if listToValue != null then + mapAttrs (_: mapAttrs (key: val: if isList val then listToValue val else val)) + else + id; ignoredArgs = [ "listToValue" @@ -291,7 +297,7 @@ optionalAttrs allowAliases aliases generate = name: value: pipe value [ - (mapAttrs (_: maybeCoerceList listToValue)) + (maybeCoerceAllLists listToValue) (toINI (removeAttrs args ignoredArgs)) (pkgs.writeText name) ]; @@ -343,7 +349,7 @@ optionalAttrs allowAliases aliases pkgs.writeText name ( toINIWithGlobalSection (removeAttrs args ignoredArgs) { globalSection = maybeCoerceList listToValue globalSection; - sections = mapAttrs (_: maybeCoerceList listToValue) sections; + sections = maybeCoerceAllLists listToValue sections; } ); }; From 4cf86ef3bf86ba54cae99bb37cb944f967926fe0 Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Sun, 7 Jun 2026 08:20:26 -0400 Subject: [PATCH 04/14] pkgs.formats.gitIni: remove unused variable --- pkgs/pkgs-lib/formats.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/pkgs-lib/formats.nix b/pkgs/pkgs-lib/formats.nix index 5ed60f3bd05c..5d9876e67ee6 100644 --- a/pkgs/pkgs-lib/formats.nix +++ b/pkgs/pkgs-lib/formats.nix @@ -358,7 +358,7 @@ optionalAttrs allowAliases aliases { listsAsDuplicateKeys ? false, ... - }@args: + }: let atom = iniAtom { inherit listsAsDuplicateKeys; From e7ba7a958b7dabd3b157ae6ec69656e949329d9c Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Sun, 7 Jun 2026 08:27:37 -0400 Subject: [PATCH 05/14] pkgs.formats.toml: remove unused callPackage arg --- pkgs/pkgs-lib/formats.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/pkgs-lib/formats.nix b/pkgs/pkgs-lib/formats.nix index 5d9876e67ee6..1f63c44232f0 100644 --- a/pkgs/pkgs-lib/formats.nix +++ b/pkgs/pkgs-lib/formats.nix @@ -469,7 +469,7 @@ optionalAttrs allowAliases aliases generate = name: value: pkgs.callPackage ( - { runCommand, remarshal }: + { runCommand }: runCommand name { nativeBuildInputs = [ json2x ]; From bffa9f19fbb5f04b807049b266e66ed28a716bcc Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Sun, 7 Jun 2026 08:28:26 -0400 Subject: [PATCH 06/14] pkgs.formats.cdn: remove no-op merge The json format only contains `type` and `generate` attributes, so merging replaces both of them. --- pkgs/pkgs-lib/formats.nix | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkgs/pkgs-lib/formats.nix b/pkgs/pkgs-lib/formats.nix index 1f63c44232f0..3576a00e9943 100644 --- a/pkgs/pkgs-lib/formats.nix +++ b/pkgs/pkgs-lib/formats.nix @@ -495,8 +495,7 @@ optionalAttrs allowAliases aliases */ cdn = { }: - json { } - // { + { type = serializableValueWith { typeName = "CDN"; }; generate = From 02c3f8ed7b878d4cdce9a90e8e4fb4acd3543613 Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Sun, 7 Jun 2026 08:31:28 -0400 Subject: [PATCH 07/14] pkgs.formats.keyValue: do more logic before generation Allows more caching if the same generator is called multiple times. --- pkgs/pkgs-lib/formats.nix | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkgs/pkgs-lib/formats.nix b/pkgs/pkgs-lib/formats.nix index 3576a00e9943..e81cec4212b0 100644 --- a/pkgs/pkgs-lib/formats.nix +++ b/pkgs/pkgs-lib/formats.nix @@ -449,15 +449,15 @@ optionalAttrs allowAliases aliases attrsOf atom; generate = - name: value: let - transformedValue = + transformValue = if listToValue != null then - mapAttrs (key: val: if isList val then listToValue val else val) value + mapAttrs (key: val: if isList val then listToValue val else val) else - value; + id; + finalArgs = removeAttrs args [ "listToValue" ]; in - pkgs.writeText name (toKeyValue (removeAttrs args [ "listToValue" ]) transformedValue); + name: value: pkgs.writeText name (toKeyValue finalArgs (transformValue value)); }; From a13dd134c113e2c15a7864bc5dac260dc2c27c7a Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Sun, 7 Jun 2026 08:32:50 -0400 Subject: [PATCH 08/14] pkgs.formats.elixirConf: hoist let variables above args --- pkgs/pkgs-lib/formats.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/pkgs-lib/formats.nix b/pkgs/pkgs-lib/formats.nix index e81cec4212b0..999efaac12da 100644 --- a/pkgs/pkgs-lib/formats.nix +++ b/pkgs/pkgs-lib/formats.nix @@ -551,9 +551,6 @@ optionalAttrs allowAliases aliases [Tuple]: */ elixirConf = - { - elixir ? pkgs.elixir, - }: let toElixir = value: @@ -634,6 +631,9 @@ optionalAttrs allowAliases aliases ${concatStringsSep "\n" rootConfigs} ''; in + { + elixir ? pkgs.elixir, + }: { type = let From 5e0e1a165aa5a27b3246f53aa03b1941a0d8d882 Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Sun, 7 Jun 2026 08:33:48 -0400 Subject: [PATCH 09/14] pkgs.formats.elixirConf: host variables to outside function --- pkgs/pkgs-lib/formats.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkgs/pkgs-lib/formats.nix b/pkgs/pkgs-lib/formats.nix index 999efaac12da..d419f8ffe3d8 100644 --- a/pkgs/pkgs-lib/formats.nix +++ b/pkgs/pkgs-lib/formats.nix @@ -617,12 +617,14 @@ optionalAttrs allowAliases aliases tuple = values: "{${listContent values}}"; toConf = - values: let keyConfig = rootKey: key: value: "config ${rootKey}, ${key}, ${toElixir value}"; keyConfigs = rootKey: values: mapAttrsToList (keyConfig rootKey) values; + in + values: + let rootConfigs = flatten (mapAttrsToList keyConfigs values); in '' From 01d76243e0c0a5f86576766476cde3ca87d68c3a Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Sun, 7 Jun 2026 08:35:52 -0400 Subject: [PATCH 10/14] pkgs.formats.nixConf: host let variables outside of function scope --- pkgs/pkgs-lib/formats.nix | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkgs/pkgs-lib/formats.nix b/pkgs/pkgs-lib/formats.nix index d419f8ffe3d8..06d235fa1884 100644 --- a/pkgs/pkgs-lib/formats.nix +++ b/pkgs/pkgs-lib/formats.nix @@ -841,9 +841,7 @@ optionalAttrs allowAliases aliases in attrsOf atomType; generate = - name: value: let - # note that list type has been omitted here as the separator varies, see `nix.settings.*` mkValueString = v: @@ -871,8 +869,8 @@ optionalAttrs allowAliases aliases mkKeyValuePairs = attrs: concatStringsSep "\n" (mapAttrsToList mkKeyValue attrs); isExtra = key: hasPrefix "extra-" key; - in + name: value: pkgs.writeTextFile { inherit name; # workaround for https://github.com/NixOS/nix/issues/9487 From 6bd71d7e085ec519009adc1110082210061a5fa3 Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Sun, 7 Jun 2026 08:36:28 -0400 Subject: [PATCH 11/14] pkgs.formats.hcl1: host let variables to outside function scope --- pkgs/pkgs-lib/formats.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/pkgs-lib/formats.nix b/pkgs/pkgs-lib/formats.nix index 06d235fa1884..a7f92f51dab4 100644 --- a/pkgs/pkgs-lib/formats.nix +++ b/pkgs/pkgs-lib/formats.nix @@ -1063,7 +1063,6 @@ optionalAttrs allowAliases aliases }; hcl1 = - args: let # Helper function to recursively transform values for HCL1 canonicalization # Rule: If an attribute value is an attribute set, wrap it in a list @@ -1079,6 +1078,7 @@ optionalAttrs allowAliases aliases value; jsonFormat = json { }; in + args: jsonFormat // { generate = name: value: jsonFormat.generate name (mapAttrs (_: transform) value); From d6c42b772581c087c7ff02b15ac55d4c9e0e81eb Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Sun, 7 Jun 2026 08:39:06 -0400 Subject: [PATCH 12/14] pkgs.formats: use lib functions from global scope --- pkgs/pkgs-lib/formats.nix | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pkgs/pkgs-lib/formats.nix b/pkgs/pkgs-lib/formats.nix index a7f92f51dab4..7639c62ea43e 100644 --- a/pkgs/pkgs-lib/formats.nix +++ b/pkgs/pkgs-lib/formats.nix @@ -37,6 +37,7 @@ let toKeyValue toLua mkLuaInline + toPlist ; inherit (lib.types) @@ -397,7 +398,7 @@ optionalAttrs allowAliases aliases // { generate = name: value: - lib.warn + warn "Direct use of `pkgs.formats.systemd` has been deprecated, please use `pkgs.formats.systemd { }` instead." rawFormat.generate name @@ -812,7 +813,7 @@ optionalAttrs allowAliases aliases '' ) { }; # Alias for mkLuaInline - lib.mkRaw = lib.mkLuaInline; + lib.mkRaw = mkLuaInline; }; nixConf = @@ -883,7 +884,7 @@ optionalAttrs allowAliases aliases ${mkKeyValuePairs (filterAttrs (key: _: isExtra key) value)} ${extraOptions} ''; - checkPhase = lib.optionalString checkConfig ( + checkPhase = optionalString checkConfig ( if pkgs.stdenv.hostPlatform != pkgs.stdenv.buildPlatform then '' echo "Ignoring validation for cross-compilation" @@ -1059,7 +1060,7 @@ optionalAttrs allowAliases aliases in valueType; - generate = name: value: pkgs.writeText name (lib.generators.toPlist { inherit escape; } value); + generate = name: value: pkgs.writeText name (toPlist { inherit escape; } value); }; hcl1 = From f214820f08e0771b518cbac000189cf6218f653d Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Sun, 7 Jun 2026 08:40:53 -0400 Subject: [PATCH 13/14] pkgs.formats.nixConf: use package from lib.types explicitly This was actually being set to the package attribute for the function, which is definitely not what we want. --- pkgs/pkgs-lib/formats.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/pkgs-lib/formats.nix b/pkgs/pkgs-lib/formats.nix index 7639c62ea43e..272099653b3c 100644 --- a/pkgs/pkgs-lib/formats.nix +++ b/pkgs/pkgs-lib/formats.nix @@ -837,7 +837,7 @@ optionalAttrs allowAliases aliases float str path - package + types.package ]); in attrsOf atomType; From 623c813d5f875aea13c92652674988ad92e023ad Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Sun, 7 Jun 2026 08:42:28 -0400 Subject: [PATCH 14/14] pkgs.formats: move toJSON to global scope --- pkgs/pkgs-lib/formats.nix | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/pkgs/pkgs-lib/formats.nix b/pkgs/pkgs-lib/formats.nix index 272099653b3c..5f6ed4f0e74b 100644 --- a/pkgs/pkgs-lib/formats.nix +++ b/pkgs/pkgs-lib/formats.nix @@ -23,6 +23,7 @@ let pipe singleton strings + toJSON toPretty types versionAtLeast @@ -143,7 +144,7 @@ optionalAttrs allowAliases aliases runCommand name { nativeBuildInputs = [ jq ]; - value = builtins.toJSON value; + value = toJSON value; preferLocalBuild = true; __structuredAttrs = true; } @@ -168,7 +169,7 @@ optionalAttrs allowAliases aliases runCommand name { nativeBuildInputs = [ remarshal_0_17 ]; - value = builtins.toJSON value; + value = toJSON value; preferLocalBuild = true; __structuredAttrs = true; } @@ -193,7 +194,7 @@ optionalAttrs allowAliases aliases runCommand name { nativeBuildInputs = [ remarshal ]; - value = builtins.toJSON value; + value = toJSON value; preferLocalBuild = true; __structuredAttrs = true; } @@ -506,7 +507,7 @@ optionalAttrs allowAliases aliases runCommand name { nativeBuildInputs = [ json2cdn ]; - value = builtins.toJSON value; + value = toJSON value; preferLocalBuild = true; __structuredAttrs = true; } @@ -939,8 +940,8 @@ optionalAttrs allowAliases aliases python3 black ]; - imports = builtins.toJSON (value._imports or [ ]); - value = builtins.toJSON (removeAttrs value [ "_imports" ]); + imports = toJSON (value._imports or [ ]); + value = toJSON (removeAttrs value [ "_imports" ]); pythonGen = pkgs.writeText "pythonGen" '' import json import os @@ -1012,7 +1013,7 @@ optionalAttrs allowAliases aliases python3Packages.xmltodict libxml2Python ]; - value = builtins.toJSON value; + value = toJSON value; pythonGen = pkgs.writeText "pythonGen" '' import json import os