From 4b0d1225f5e93e794800306d0785473e20129534 Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Tue, 13 May 2025 18:27:14 -0400 Subject: [PATCH] lib/asserts: Factor out NixOS's toplevel assertion / warning logic. --- lib/asserts.nix | 68 +++++++++++++++++++ nixos/modules/system/activation/top-level.nix | 9 +-- 2 files changed, 69 insertions(+), 8 deletions(-) diff --git a/lib/asserts.nix b/lib/asserts.nix index b22252a7654b..41908d00a812 100644 --- a/lib/asserts.nix +++ b/lib/asserts.nix @@ -1,5 +1,16 @@ { 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; + } diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix index 75738bc0f5db..56e97d3fdea9 100644 --- a/nixos/modules/system/activation/top-level.nix +++ b/nixos/modules/system/activation/top-level.nix @@ -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 =