diff --git a/home-manager/default.nix b/home-manager/default.nix index 144fd7f..90f1e64 100644 --- a/home-manager/default.nix +++ b/home-manager/default.nix @@ -2,7 +2,7 @@ let inherit (builtins) head tail mapAttrs attrValues; inherit (lib) flatten optional mkOption mkDefault mkOptionType; - inherit (lib.my) homeStateVersion mkOpt' commonOpts inlineModule'; + inherit (lib.my) homeStateVersion mkOpt' commonOpts inlineModule' applyAssertions; cfg = config.home-manager; @@ -40,7 +40,11 @@ let ] ++ (tail defs); }; - homeOpts = with lib.types; { config, ... }: { + homeOpts = with lib.types; { ... }@args: + let + config' = args.config; + in + { options = { inherit (commonOpts) system nixpkgs home-manager; # TODO: docCustom for home-manager? @@ -53,16 +57,16 @@ let description = "home-manager configuration module."; type = mkOptionType { name = "home-manager configuration"; - merge = _: defs: mkHome { - config' = config; + merge = _: defs: applyAssertions config (mkHome { + inherit config'; defs = map (d: inlineModule' d.file d.value) defs; - }; + }); }; }; }; config = { - nixpkgs = mkDefault config.home-manager; + nixpkgs = mkDefault config'.home-manager; }; }; in diff --git a/lib.nix b/lib.nix index ce6f1a7..c4cdb4d 100644 --- a/lib.nix +++ b/lib.nix @@ -1,9 +1,10 @@ { lib }: let - inherit (builtins) length match replaceStrings elemAt mapAttrs head split; + inherit (builtins) length match replaceStrings elemAt mapAttrs head split filter; inherit (lib) genAttrs mapAttrs' mapAttrsToList filterAttrsRecursive nameValuePair types - mkOption mkOverride mkForce mkIf mergeEqualOption optional hasPrefix; + mkOption mkOverride mkForce mkIf mergeEqualOption optional hasPrefix + showWarnings concatStringsSep flatten unique; inherit (lib.flake) defaultSystems; in rec { @@ -69,6 +70,24 @@ rec { mkDefault' = mkOverride 900; mkVMOverride' = mkOverride 9; + # This is shocking... + duplicates = l: + flatten + (map + (e: + optional + ((length (filter (e2: e2 == e) l)) > 1) + e) + (unique l)); + + applyAssertions = config: res: + let + failedAssertions = map (x: x.message) (filter (x: !x.assertion) config.assertions); + in + if failedAssertions != [] + then throw "\nFailed assertions:\n${concatStringsSep "\n" (map (x: "- ${x}") failedAssertions)}" + else showWarnings config.warnings res; + homeStateVersion = hmBranch: { # The flake passes a default setting, but we don't care about that # Currently don't need any logic here, but we might need to use a newer version later diff --git a/nixos/default.nix b/nixos/default.nix index 62ee89d..88b9d9c 100644 --- a/nixos/default.nix +++ b/nixos/default.nix @@ -1,8 +1,10 @@ { lib, pkgsFlakes, hmFlakes, inputs, pkgs', config, ... }: let inherit (builtins) attrValues mapAttrs; - inherit (lib) substring flatten optional optionals mkIf mkDefault mkForce mkOption mkOptionType; - inherit (lib.my) naiveIPv4Gateway homeStateVersion mkOpt' mkBoolOpt' mkDefault' commonOpts inlineModule'; + inherit (lib) + substring flatten optional optionals mkIf mkDefault mkForce mkOption mkOptionType; + inherit (lib.my) + naiveIPv4Gateway homeStateVersion mkOpt' mkBoolOpt' mkDefault' commonOpts inlineModule' applyAssertions duplicates; cfg = config.nixos; @@ -114,7 +116,11 @@ let }; }; - systemOpts = with lib.types; { name, config, ... }: { + systemOpts = with lib.types; { name, ... }@args: + let + config' = args.config; + in + { options = { inherit (commonOpts) system nixpkgs home-manager; hmNixpkgs = commonOpts.nixpkgs; @@ -131,18 +137,17 @@ let # Based on the definition of containers..config type = mkOptionType { name = "Toplevel NixOS config"; - merge = _: defs: mkSystem { - inherit name; - config' = config; + merge = _: defs: applyAssertions config (mkSystem { + inherit name config'; defs = map (d: inlineModule' d.file d.value) defs; - }; + }); }; }; }; config = { - home-manager = mkDefault config.nixpkgs; - hmNixpkgs = mkDefault config.nixpkgs; + home-manager = mkDefault config'.nixpkgs; + hmNixpkgs = mkDefault config'.nixpkgs; }; }; in @@ -156,4 +161,25 @@ in systems = mkOpt' (attrsOf (submodule systemOpts)) { } "NixOS systems to be exported by nixfiles."; }; }; + + config = { + assertions = + let + assignedIPs = + flatten + (map + (as: + map + (a: [ a.ipv4.address a.ipv6.address ]) + (attrValues as)) + (attrValues allAssignments)); + dupIPs = duplicates assignedIPs; + in + [ + { + assertion = dupIPs == [ ]; + message = "Duplicate assignments: ${toString dupIPs}"; + } + ]; + }; }