Unverified Commit 871526be authored by Arian van Putten's avatar Arian van Putten Committed by GitHub
Browse files

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

parents 710f3f8b 26ccfb7a
Loading
Loading
Loading
Loading
+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 {

  /**
@@ -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;

}
+77 −55
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@

{
  config,
  options,
  pkgs,
  lib,
  utils,
@@ -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;
@@ -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 =
@@ -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)
@@ -382,6 +402,8 @@ in
            ;
          inherit fileSystems definitionsDirectory mkfsEnv;
        };
      in
      lib.asserts.checkAssertWarn cfg.assertions cfg.warnings val;
  };

  meta.maintainers = with lib.maintainers; [
+1 −8
Original line number Diff line number Diff line
@@ -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 =