diff --git a/nixos/modules/config/nix.nix b/nixos/modules/config/nix.nix index 48ac45323750..9dfc4a1e664e 100644 --- a/nixos/modules/config/nix.nix +++ b/nixos/modules/config/nix.nix @@ -16,40 +16,21 @@ let inherit (lib) - concatStringsSep - boolToString - escape - filterAttrs - floatToString - getVersion - hasPrefix - isBool - isDerivation - isFloat - isInt - isList - isString literalExpression mapAttrsToList mkAfter mkIf mkOption mkRenamedOptionModuleWith - optionalString optionals - strings systems - toPretty types - versionAtLeast ; cfg = config.nix; nixPackage = cfg.package.out; - isNixAtLeast = versionAtLeast (getVersion nixPackage); - defaultSystemFeatures = [ "nixos-test" "benchmark" @@ -98,74 +79,17 @@ let attrsOf (either confAtom (listOf confAtom)); nixConf = - assert isNixAtLeast "2.2"; - let - - mkValueString = - v: - if v == null then - "" - else if isInt v then - toString v - else if isBool v then - boolToString v - else if isFloat v then - floatToString v - else if isList v then - toString v - else if isDerivation v then - toString v - else if builtins.isPath v then - toString v - else if isString v then - v - else if strings.isConvertibleWithToString v then - toString v - else - abort "The nix conf value: ${toPretty { } v} can not be encoded"; - - mkKeyValue = k: v: "${escape [ "=" ] k} = ${mkValueString v}"; - - mkKeyValuePairs = attrs: concatStringsSep "\n" (mapAttrsToList mkKeyValue attrs); - - isExtra = key: hasPrefix "extra-" key; - - in - pkgs.writeTextFile { - name = "nix.conf"; - # workaround for https://github.com/NixOS/nix/issues/9487 - # extra-* settings must come after their non-extra counterpart - text = '' - # WARNING: this file is generated from the nix.* options in - # your NixOS configuration, typically - # /etc/nixos/configuration.nix. Do not edit it! - ${mkKeyValuePairs (filterAttrs (key: value: !(isExtra key)) cfg.settings)} - ${mkKeyValuePairs (filterAttrs (key: value: isExtra key) cfg.settings)} - ${cfg.extraOptions} - ''; - checkPhase = lib.optionalString cfg.checkConfig ( - if pkgs.stdenv.hostPlatform != pkgs.stdenv.buildPlatform then - '' - echo "Ignoring validation for cross-compilation" - '' - else - let - showCommand = if isNixAtLeast "2.20pre" then "config show" else "show-config"; - in - '' - echo "Validating generated nix.conf" - ln -s $out ./nix.conf - set -e - set +o pipefail - NIX_CONF_DIR=$PWD \ - ${cfg.package}/bin/nix ${showCommand} ${optionalString (isNixAtLeast "2.3pre") "--no-net"} \ - ${optionalString (isNixAtLeast "2.4pre") "--option experimental-features nix-command"} \ - |& sed -e 's/^warning:/error:/' \ - | (! grep '${if cfg.checkAllErrors then "^error:" else "^error: unknown setting"}') - set -o pipefail - '' - ); - }; + (pkgs.formats.nixConf { + inherit (cfg) + package + checkAllErrors + checkConfig + extraOptions + ; + inherit (nixPackage) version; + }).generate + "nix.conf" + cfg.settings; in { diff --git a/pkgs/pkgs-lib/formats.nix b/pkgs/pkgs-lib/formats.nix index 25bdbdc8a08f..acbc088e28e1 100644 --- a/pkgs/pkgs-lib/formats.nix +++ b/pkgs/pkgs-lib/formats.nix @@ -1,11 +1,16 @@ { lib, pkgs }: let inherit (lib) + boolToString concatStringsSep escape + filterAttrs flatten + hasPrefix id isAttrs + isBool + isDerivation isFloat isInt isList @@ -16,8 +21,11 @@ let optionalAttrs optionalString pipe - types singleton + strings + toPretty + types + versionAtLeast warn ; @@ -863,6 +871,101 @@ optionalAttrs allowAliases aliases lib.mkRaw = lib.mkLuaInline; }; + nixConf = + { + package, + version, + extraOptions ? "", + checkAllErrors ? true, + checkConfig ? true, + }: + let + isNixAtLeast = versionAtLeast version; + in + assert isNixAtLeast "2.2"; + { + type = + let + atomType = nullOr (oneOf [ + bool + int + float + str + path + package + ]); + in + attrsOf atomType; + generate = + name: value: + let + + # note that list type has been omitted here as the separator varies, see `nix.settings.*` + mkValueString = + v: + if v == null then + "" + else if isInt v then + toString v + else if isBool v then + boolToString v + else if isFloat v then + strings.floatToString v + else if isDerivation v then + toString v + else if builtins.isPath v then + toString v + else if isString v then + v + else if strings.isConvertibleWithToString v then + toString v + else + abort "The nix conf value: ${toPretty { } v} can not be encoded"; + + mkKeyValue = k: v: "${escape [ "=" ] k} = ${mkValueString v}"; + + mkKeyValuePairs = attrs: concatStringsSep "\n" (mapAttrsToList mkKeyValue attrs); + + isExtra = key: hasPrefix "extra-" key; + + in + pkgs.writeTextFile { + inherit name; + # workaround for https://github.com/NixOS/nix/issues/9487 + # extra-* settings must come after their non-extra counterpart + text = '' + # WARNING: this file is generated from the nix.* options in + # your NixOS configuration, typically + # /etc/nixos/configuration.nix. Do not edit it! + ${mkKeyValuePairs (filterAttrs (key: _: !(isExtra key)) value)} + ${mkKeyValuePairs (filterAttrs (key: _: isExtra key) value)} + ${extraOptions} + ''; + checkPhase = lib.optionalString checkConfig ( + if pkgs.stdenv.hostPlatform != pkgs.stdenv.buildPlatform then + '' + echo "Ignoring validation for cross-compilation" + '' + else + let + showCommand = if isNixAtLeast "2.20pre" then "config show" else "show-config"; + in + '' + echo "Validating generated nix.conf" + ln -s $out ./nix.conf + set -e + set +o pipefail + NIX_CONF_DIR=$PWD \ + ${package}/bin/nix ${showCommand} ${optionalString (isNixAtLeast "2.3pre") "--no-net"} \ + ${optionalString (isNixAtLeast "2.4pre") "--option experimental-features nix-command"} \ + |& sed -e 's/^warning:/error:/' \ + | (! grep '${if checkAllErrors then "^error:" else "^error: unknown setting"}') + set -o pipefail + '' + ); + }; + }; + # Outputs a succession of Python variable assignments # Useful for many Django-based services pythonVars = diff --git a/pkgs/pkgs-lib/tests/formats.nix b/pkgs/pkgs-lib/tests/formats.nix index badde2d7b025..9b1ab396a3fe 100644 --- a/pkgs/pkgs-lib/tests/formats.nix +++ b/pkgs/pkgs-lib/tests/formats.nix @@ -850,6 +850,31 @@ runBuildTests { ''; }; + nixConfAtoms = shouldPass { + format = formats.nixConf { + package = pkgs.nix; + version = pkgs.nix.version; + extraOptions = ''ignore-try = false''; + }; + input = { + auto-optimise-store = true; + cores = 0; + store = "auto"; + }; + # note that null type is hard to test here, + # as it involves a trailing space our formatter will remove here + expected = '' + # WARNING: this file is generated from the nix.* options in + # your NixOS configuration, typically + # /etc/nixos/configuration.nix. Do not edit it! + auto-optimise-store = true + cores = 0 + store = auto + + ignore-try = false + ''; + }; + phpAtoms = shouldPass rec { format = formats.php { finalVariable = "config"; }; input = {