nixos/image/repart: Use own assertions / warnings. (#406940)

Changed files
+146 -63
lib
nixos
modules
image
system
activation
+68
lib/asserts.nix
···
{ lib }:
+
let
+
inherit (lib.strings)
+
concatStringsSep
+
;
+
inherit (lib.lists)
+
filter
+
;
+
inherit (lib.trivial)
+
showWarnings
+
;
+
in
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;
+
}
+77 -55
nixos/modules/image/repart.nix
···
{
config,
+
options,
pkgs,
lib,
utils,
···
'';
};
+
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.
+
'';
+
};
+
+
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.
+
'';
+
};
+
};
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}.
-
'';
-
}
-
) 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
-
);
-
image.baseName =
let
version = config.image.repart.version;
···
};
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 =
···
);
mkfsEnv = mkfsOptionsToEnv cfg.mkfsOptions;
+
val = pkgs.callPackage ./repart-image.nix {
+
systemd = cfg.package;
+
imageFileBasename = config.image.baseName;
+
inherit (cfg)
+
name
+
version
+
compression
+
split
+
seed
+
sectorSize
+
finalPartitions
+
;
+
inherit fileSystems definitionsDirectory mkfsEnv;
+
};
in
-
pkgs.callPackage ./repart-image.nix {
-
systemd = cfg.package;
-
imageFileBasename = config.image.baseName;
-
inherit (cfg)
-
name
-
version
-
compression
-
split
-
seed
-
sectorSize
-
finalPartitions
-
;
-
inherit fileSystems definitionsDirectory mkfsEnv;
-
};
+
lib.asserts.checkAssertWarn cfg.assertions cfg.warnings val;
};
meta.maintainers = with lib.maintainers; [
+1 -8
nixos/modules/system/activation/top-level.nix
···
);
# 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 =