Loading lib/asserts.nix +68 −0 Original line number Diff line number Diff line { lib }: let inherit (lib.strings) concatStringsSep ; inherit (lib.lists) filter ; inherit (lib.trivial) showWarnings ; in rec { /** Loading Loading @@ -131,4 +142,61 @@ rec { "each element in ${name} must be one of ${lib.generators.toPretty { } xs}, but is: ${ lib.generators.toPretty { } vals }"; /** Wrap a value with logic that throws an error when assertions fail and emits any warnings. # Inputs `assertions` : A list of assertions. If any of their `assertion` attrs is `false`, their `message` attrs will be emitted in a `throw`. `warnings` : A list of strings to emit as warnings. This function does no filtering on this list. `val` : A value to return, wrapped in `warn`, if a `throw` is not necessary. # Type ``` checkAssertWarn :: [ { assertion :: Bool; message :: String } ] -> [ String ] -> Any -> Any ``` # Examples :::{.example} ## `lib.asserts.checkAssertWarn` usage example ```nix checkAssertWarn [ { assertion = false; message = "Will fail"; } ] [ ] null stderr> error: stderr> Failed assertions: stderr> - Will fail checkAssertWarn [ { assertion = true; message = "Will not fail"; } ] [ "Will warn" ] null stderr> evaluation warning: Will warn null ``` ::: */ checkAssertWarn = assertions: warnings: val: let failedAssertions = map (x: x.message) (filter (x: !x.assertion) assertions); in if failedAssertions != [ ] then throw "\nFailed assertions:\n${concatStringsSep "\n" (map (x: "- ${x}") failedAssertions)}" else showWarnings warnings val; } nixos/modules/image/repart.nix +77 −55 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ { config, options, pkgs, lib, utils, Loading Loading @@ -258,50 +259,29 @@ in ''; }; assertions = lib.mkOption { type = options.assertions.type; default = [ ]; internal = true; visible = false; description = '' Assertions only evaluated by the repart image, not by the system toplevel. ''; }; config = { assertions = lib.mapAttrsToList ( fileName: partitionConfig: let inherit (partitionConfig) repartConfig; labelLength = builtins.stringLength repartConfig.Label; in { assertion = repartConfig ? Label -> GPTMaxLabelLength >= labelLength; message = '' The partition label '${repartConfig.Label}' defined for '${fileName}' is ${toString labelLength} characters long, but the maximum label length supported by UEFI is ${toString GPTMaxLabelLength}. warnings = lib.mkOption { type = options.warnings.type; default = [ ]; internal = true; visible = false; description = '' Warnings only evaluated by the repart image, not by the system toplevel. ''; } ) cfg.partitions; warnings = lib.filter (v: v != null) ( lib.mapAttrsToList ( fileName: partitionConfig: let inherit (partitionConfig) repartConfig; suggestedMaxLabelLength = GPTMaxLabelLength - 2; labelLength = builtins.stringLength repartConfig.Label; in if (repartConfig ? Label && labelLength >= suggestedMaxLabelLength) then '' The partition label '${repartConfig.Label}' defined for '${fileName}' is ${toString labelLength} characters long. The suggested maximum label length is ${toString suggestedMaxLabelLength}. }; If you use sytemd-sysupdate style A/B updates, this might not leave enough space to increment the version number included in the label in a future release. For example, if your label is ${toString GPTMaxLabelLength} characters long (the maximum enforced by UEFI) and you're at version 9, you cannot increment this to 10. '' else null ) cfg.partitions ); }; config = { image.baseName = let version = config.image.repart.version; Loading Loading @@ -352,6 +332,47 @@ in }; finalPartitions = lib.mapAttrs addClosure cfg.partitions; assertions = lib.mapAttrsToList ( fileName: partitionConfig: let inherit (partitionConfig) repartConfig; labelLength = builtins.stringLength repartConfig.Label; in { assertion = repartConfig ? Label -> GPTMaxLabelLength >= labelLength; message = '' The partition label '${repartConfig.Label}' defined for '${fileName}' is ${toString labelLength} characters long, but the maximum label length supported by UEFI is ${toString GPTMaxLabelLength}. ''; } ) cfg.partitions; warnings = lib.filter (v: v != null) ( lib.mapAttrsToList ( fileName: partitionConfig: let inherit (partitionConfig) repartConfig; suggestedMaxLabelLength = GPTMaxLabelLength - 2; labelLength = builtins.stringLength repartConfig.Label; in if (repartConfig ? Label && labelLength >= suggestedMaxLabelLength) then '' The partition label '${repartConfig.Label}' defined for '${fileName}' is ${toString labelLength} characters long. The suggested maximum label length is ${toString suggestedMaxLabelLength}. If you use sytemd-sysupdate style A/B updates, this might not leave enough space to increment the version number included in the label in a future release. For example, if your label is ${toString GPTMaxLabelLength} characters long (the maximum enforced by UEFI) and you're at version 9, you cannot increment this to 10. '' else null ) cfg.partitions ); }; system.build.image = Loading @@ -367,8 +388,7 @@ in ); mkfsEnv = mkfsOptionsToEnv cfg.mkfsOptions; in pkgs.callPackage ./repart-image.nix { val = pkgs.callPackage ./repart-image.nix { systemd = cfg.package; imageFileBasename = config.image.baseName; inherit (cfg) Loading @@ -382,6 +402,8 @@ in ; inherit fileSystems definitionsDirectory mkfsEnv; }; in lib.asserts.checkAssertWarn cfg.assertions cfg.warnings val; }; meta.maintainers = with lib.maintainers; [ Loading nixos/modules/system/activation/top-level.nix +1 −8 Original line number Diff line number Diff line Loading @@ -77,14 +77,7 @@ let ); # Handle assertions and warnings failedAssertions = map (x: x.message) (filter (x: !x.assertion) config.assertions); baseSystemAssertWarn = if failedAssertions != [ ] then throw "\nFailed assertions:\n${concatStringsSep "\n" (map (x: "- ${x}") failedAssertions)}" else showWarnings config.warnings baseSystem; baseSystemAssertWarn = lib.asserts.checkAssertWarn config.assertions config.warnings baseSystem; # Replace runtime dependencies system = Loading Loading
lib/asserts.nix +68 −0 Original line number Diff line number Diff line { lib }: let inherit (lib.strings) concatStringsSep ; inherit (lib.lists) filter ; inherit (lib.trivial) showWarnings ; in rec { /** Loading Loading @@ -131,4 +142,61 @@ rec { "each element in ${name} must be one of ${lib.generators.toPretty { } xs}, but is: ${ lib.generators.toPretty { } vals }"; /** Wrap a value with logic that throws an error when assertions fail and emits any warnings. # Inputs `assertions` : A list of assertions. If any of their `assertion` attrs is `false`, their `message` attrs will be emitted in a `throw`. `warnings` : A list of strings to emit as warnings. This function does no filtering on this list. `val` : A value to return, wrapped in `warn`, if a `throw` is not necessary. # Type ``` checkAssertWarn :: [ { assertion :: Bool; message :: String } ] -> [ String ] -> Any -> Any ``` # Examples :::{.example} ## `lib.asserts.checkAssertWarn` usage example ```nix checkAssertWarn [ { assertion = false; message = "Will fail"; } ] [ ] null stderr> error: stderr> Failed assertions: stderr> - Will fail checkAssertWarn [ { assertion = true; message = "Will not fail"; } ] [ "Will warn" ] null stderr> evaluation warning: Will warn null ``` ::: */ checkAssertWarn = assertions: warnings: val: let failedAssertions = map (x: x.message) (filter (x: !x.assertion) assertions); in if failedAssertions != [ ] then throw "\nFailed assertions:\n${concatStringsSep "\n" (map (x: "- ${x}") failedAssertions)}" else showWarnings warnings val; }
nixos/modules/image/repart.nix +77 −55 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ { config, options, pkgs, lib, utils, Loading Loading @@ -258,50 +259,29 @@ in ''; }; assertions = lib.mkOption { type = options.assertions.type; default = [ ]; internal = true; visible = false; description = '' Assertions only evaluated by the repart image, not by the system toplevel. ''; }; config = { assertions = lib.mapAttrsToList ( fileName: partitionConfig: let inherit (partitionConfig) repartConfig; labelLength = builtins.stringLength repartConfig.Label; in { assertion = repartConfig ? Label -> GPTMaxLabelLength >= labelLength; message = '' The partition label '${repartConfig.Label}' defined for '${fileName}' is ${toString labelLength} characters long, but the maximum label length supported by UEFI is ${toString GPTMaxLabelLength}. warnings = lib.mkOption { type = options.warnings.type; default = [ ]; internal = true; visible = false; description = '' Warnings only evaluated by the repart image, not by the system toplevel. ''; } ) cfg.partitions; warnings = lib.filter (v: v != null) ( lib.mapAttrsToList ( fileName: partitionConfig: let inherit (partitionConfig) repartConfig; suggestedMaxLabelLength = GPTMaxLabelLength - 2; labelLength = builtins.stringLength repartConfig.Label; in if (repartConfig ? Label && labelLength >= suggestedMaxLabelLength) then '' The partition label '${repartConfig.Label}' defined for '${fileName}' is ${toString labelLength} characters long. The suggested maximum label length is ${toString suggestedMaxLabelLength}. }; If you use sytemd-sysupdate style A/B updates, this might not leave enough space to increment the version number included in the label in a future release. For example, if your label is ${toString GPTMaxLabelLength} characters long (the maximum enforced by UEFI) and you're at version 9, you cannot increment this to 10. '' else null ) cfg.partitions ); }; config = { image.baseName = let version = config.image.repart.version; Loading Loading @@ -352,6 +332,47 @@ in }; finalPartitions = lib.mapAttrs addClosure cfg.partitions; assertions = lib.mapAttrsToList ( fileName: partitionConfig: let inherit (partitionConfig) repartConfig; labelLength = builtins.stringLength repartConfig.Label; in { assertion = repartConfig ? Label -> GPTMaxLabelLength >= labelLength; message = '' The partition label '${repartConfig.Label}' defined for '${fileName}' is ${toString labelLength} characters long, but the maximum label length supported by UEFI is ${toString GPTMaxLabelLength}. ''; } ) cfg.partitions; warnings = lib.filter (v: v != null) ( lib.mapAttrsToList ( fileName: partitionConfig: let inherit (partitionConfig) repartConfig; suggestedMaxLabelLength = GPTMaxLabelLength - 2; labelLength = builtins.stringLength repartConfig.Label; in if (repartConfig ? Label && labelLength >= suggestedMaxLabelLength) then '' The partition label '${repartConfig.Label}' defined for '${fileName}' is ${toString labelLength} characters long. The suggested maximum label length is ${toString suggestedMaxLabelLength}. If you use sytemd-sysupdate style A/B updates, this might not leave enough space to increment the version number included in the label in a future release. For example, if your label is ${toString GPTMaxLabelLength} characters long (the maximum enforced by UEFI) and you're at version 9, you cannot increment this to 10. '' else null ) cfg.partitions ); }; system.build.image = Loading @@ -367,8 +388,7 @@ in ); mkfsEnv = mkfsOptionsToEnv cfg.mkfsOptions; in pkgs.callPackage ./repart-image.nix { val = pkgs.callPackage ./repart-image.nix { systemd = cfg.package; imageFileBasename = config.image.baseName; inherit (cfg) Loading @@ -382,6 +402,8 @@ in ; inherit fileSystems definitionsDirectory mkfsEnv; }; in lib.asserts.checkAssertWarn cfg.assertions cfg.warnings val; }; meta.maintainers = with lib.maintainers; [ Loading
nixos/modules/system/activation/top-level.nix +1 −8 Original line number Diff line number Diff line Loading @@ -77,14 +77,7 @@ let ); # Handle assertions and warnings failedAssertions = map (x: x.message) (filter (x: !x.assertion) config.assertions); baseSystemAssertWarn = if failedAssertions != [ ] then throw "\nFailed assertions:\n${concatStringsSep "\n" (map (x: "- ${x}") failedAssertions)}" else showWarnings config.warnings baseSystem; baseSystemAssertWarn = lib.asserts.checkAssertWarn config.assertions config.warnings baseSystem; # Replace runtime dependencies system = Loading