Last active
July 26, 2024 11:12
-
-
Save Noah765/f03c3cb23ccdf70757ad2164a3a1b8e5 to your computer and use it in GitHub Desktop.
Debugging
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| prefix ? [], | |
| specialArgs ? {}, | |
| modules ? [], | |
| osModules ? [], | |
| hmModules ? [], | |
| }: | |
| with specialArgs.inputs.nixpkgs.lib; let | |
| inherit (specialArgs.inputs) nixpkgs home-manager; | |
| inherit (nixpkgs) lib; | |
| modifiedLib = import ./modified-lib.nix lib; | |
| inherit (specialArgs) useHm; | |
| inherit mkOption types; | |
| osBaseModules = import "${nixpkgs}/nixos/modules/module-list.nix"; | |
| osExtraModules = let e = builtins.getEnv "NIXOS_EXTRA_MODULE_PATH"; in optional (e != "") (import e); | |
| allOsModules = osBaseModules ++ osExtraModules ++ osModules; | |
| osSpecialArgs = | |
| { | |
| modulesPath = "${nixpkgs}/nixos/modules"; | |
| baseModules = osBaseModules; | |
| extraModules = osExtraModules; | |
| modules = osModules; | |
| } | |
| // specialArgs; | |
| evalOsModules = options: | |
| evalModules { | |
| class = "nixos"; | |
| specialArgs = osSpecialArgs; | |
| modules = | |
| allOsModules | |
| ++ [ | |
| ( | |
| let | |
| osOptions = | |
| (evalModules { | |
| specialArgs = osSpecialArgs; | |
| modules = allOsModules; | |
| }) | |
| .options; | |
| hmUsername = options.hmUsername.value; | |
| # TODO Optional hm | |
| hmOptions = | |
| removeAttrs | |
| (evalModules { | |
| specialArgs.lib = import "${home-manager}/modules/lib/stdlib-extended.nix" lib; | |
| modules = | |
| osOptions.home-manager.users.type.getSubModules | |
| ++ [ | |
| { | |
| _module.args.name = hmUsername; | |
| home.stateVersion = options.os.value.home-manager.users.${hmUsername}.home.stateVersion; | |
| } | |
| ]; | |
| }) | |
| .options ["_module" "nixpkgs"]; | |
| filtered = | |
| osOptions | |
| // { | |
| nixpkgs = removeAttrs osOptions.nixpkgs ["pkgs"]; | |
| home-manager = osOptions.home-manager // {users.${hmUsername} = hmOptions;}; | |
| }; | |
| # Relying only on option.isDefined instead of also relying on the description doesn't work, because evaluating some defaults in the wrong circumstances will throw, e.g. networking.fqdn | |
| filterOptions = options: | |
| filterAttrsRecursive | |
| (_: x: !isOption x || ((!hasPrefix "Alias of" x.description or "" || x.isDefined) && !x.readOnly or false)) | |
| (removeAttrs options ["_module"]); | |
| mapOptions = options: config: | |
| mapAttrsRecursiveCond (x: !isOption x) (path: option: let | |
| currentConfig = getAttrFromPath path config; | |
| in | |
| if option.type.name == "submodule" | |
| then mapOptions (filterOptions (option.type.getSubOptions [])) currentConfig | |
| else if option.type.name == "attrsOf" && option.type.nestedTypes.elemType.name == "submodule" | |
| then mapAttrs (name: mapOptions (filterOptions (evalModules {modules = option.type.getSubModules ++ [{_module.args.name = name;}];}).options)) currentConfig | |
| else currentConfig) | |
| options; | |
| in | |
| mapOptions (filterOptions filtered) options.os.value | |
| ) | |
| ]; | |
| }; | |
| evaluatedModules = modifiedLib.evalModules { | |
| inherit prefix specialArgs; | |
| class = "combinedManager"; | |
| modules = | |
| [ | |
| ( | |
| { | |
| options, | |
| config, | |
| ... | |
| }: { | |
| options = { | |
| inputs = mkOption { | |
| type = with types; attrsOf raw; | |
| default = {}; | |
| description = "Inputs"; | |
| }; | |
| hmUsername = mkOption { | |
| type = types.str; | |
| description = "Username used for Home Manager."; | |
| }; | |
| osImports = mkOption { | |
| type = with types; listOf raw; | |
| default = []; | |
| description = "NixOS modules."; | |
| }; | |
| hmImports = mkOption { | |
| type = with types; listOf raw; | |
| default = []; | |
| description = "Home Manager modules."; | |
| }; | |
| os = mkOption { | |
| # TODO Change type to deferredModule? | |
| type = types.submoduleWith { | |
| class = "nixos"; | |
| specialArgs = osSpecialArgs; | |
| modules = allOsModules; | |
| }; | |
| default = {}; | |
| visible = "shallow"; | |
| description = "NixOS configuration."; | |
| }; | |
| hm = mkOption { | |
| type = types.deferredModule; | |
| default = {}; | |
| description = "Home Manager configuration."; | |
| }; | |
| }; | |
| config = { | |
| _module.args = { | |
| pkgs = | |
| (evalModules { | |
| modules = [ | |
| "${nixpkgs}/nixos/modules/misc/nixpkgs.nix" | |
| {nixpkgs = builtins.removeAttrs config.os.nixpkgs ["pkgs" "flake"];} | |
| ]; | |
| }) | |
| ._module | |
| .args | |
| .pkgs; | |
| osOptions = let | |
| enhanceOption = _: option: | |
| # TODO Support listOf, functionTo, and standalone submodules | |
| if | |
| (option.type.name == "attrsOf" || option.type.name == "lazyAttrsOf") | |
| && option.type.nestedTypes.elemType.name == "submodule" | |
| then | |
| option | |
| // { | |
| __functor = self: name: | |
| mapAttrsRecursiveCond (x: !isOption x) enhanceOption | |
| (evalModules {modules = [{_module.args.name = name;}] ++ self.type.getSubModules;}).options; | |
| } | |
| else option; | |
| in | |
| mapAttrsRecursiveCond (x: !isOption x) enhanceOption (evalOsModules options).options; | |
| osConfig = config.os; | |
| }; | |
| os = { | |
| system.nixos.versionSuffix = ".${lib.substring 0 8 (nixpkgs.lastModifiedDate or nixpkgs.lastModified)}.${nixpkgs.shortRev or "dirty"}"; | |
| system.nixos.revision = lib.mkIf (nixpkgs ? rev) nixpkgs.rev; | |
| }; | |
| }; | |
| } | |
| ) | |
| "${nixpkgs}/nixos/modules/misc/assertions.nix" | |
| (mkAliasOptionModule ["osModules"] ["osImports"]) | |
| ] | |
| ++ optionals useHm [ | |
| ( | |
| { | |
| osOptions, | |
| config, | |
| osConfig, | |
| ... | |
| }: { | |
| config = { | |
| _module.args = { | |
| hmOptions = osOptions.home-manager.users config.hmUsername; | |
| hmConfig = osConfig.home-manager.users.${config.hmUsername}; | |
| }; | |
| os.home-manager = { | |
| useGlobalPkgs = true; | |
| useUserPackages = true; | |
| extraSpecialArgs = specialArgs; | |
| sharedModules = hmModules; | |
| users.${config.hmUsername} = config.hm; | |
| }; | |
| }; | |
| } | |
| ) | |
| (mkAliasOptionModule ["hmModules"] ["hmImports"]) | |
| ] | |
| ++ modules; | |
| }; | |
| in { | |
| combinedManager = evaluatedModules; | |
| nixos = evalOsModules evaluatedModules.options; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| useHomeManager ? true, | |
| globalSpecialArgs ? {}, | |
| globalModules ? [], | |
| globalOsModules ? [], | |
| globalHmModules ? [], | |
| configurations, | |
| outputs ? (_: {}), | |
| ... | |
| }: rawInputs: | |
| with rawInputs.nixpkgs.lib; let | |
| inherit (rawInputs.nixpkgs) lib; | |
| modifiedLib = import ./modified-lib.nix lib; | |
| evalModules = import ./eval-modules.nix; | |
| evalModule = configs: config: let | |
| inputs = rawInputs // config.inputOverrides or (_: {}) rawInputs; | |
| modules = globalModules ++ config.modules or []; | |
| configModules = modifiedLib.collectModules null "" modules { | |
| inherit lib inputs; | |
| options = null; | |
| config = null; | |
| }; | |
| findImports = name: alias: x: | |
| if x ? ${name} || x ? ${alias} | |
| then x.${name} or [] ++ x.${alias} or [] | |
| else if x ? content | |
| then findImports name alias x.content | |
| else if x ? contents | |
| then lib.foldl (imports: x: imports ++ findImports name alias x) [] x.contents | |
| else []; | |
| configOsModules = lib.foldl (defs: module: defs ++ findImports "osImports" "osModules" module.config) [] configModules; | |
| configHmModules = lib.foldl (defs: module: defs ++ findImports "hmImports" "hmModules" module.config) [] configModules; | |
| useHm = config.useHomeManager or useHomeManager; | |
| result = evalModules { | |
| prefix = config.prefix or []; | |
| specialArgs = | |
| { | |
| inherit inputs useHm configs; | |
| combinedManager = import ../.; | |
| combinedManagerPath = ../.; | |
| } | |
| // globalSpecialArgs | |
| // config.specialArgs or {}; | |
| inherit modules; | |
| osModules = globalOsModules ++ config.osModules or [] ++ configOsModules++ optional useHm inputs.home-manager.nixosModules.default; | |
| hmModules = globalHmModules ++ config.hmModules or [] ++ configHmModules; | |
| }; | |
| showWarnings = module: | |
| foldl ( | |
| module: warning: builtins.trace "warning: ${warning}" module | |
| ) | |
| module | |
| module.config.warnings; | |
| showErrors = module: let | |
| failedAssertions = lists.map (x: x.message) (filter (x: !x.assertion) module.config.assertions); | |
| in | |
| if failedAssertions == [] | |
| then module | |
| else | |
| throw '' | |
| Failed assertions: | |
| ${concatStringsSep "\n" (map (x: "- ${x}") failedAssertions)}''; | |
| in { | |
| combinedManager = showErrors (showWarnings result.combinedManager); | |
| inherit (result) nixos; # TODO Errors and warnings? | |
| }; | |
| explicitOutputs = outputs rawInputs; | |
| combinedManagerConfigurations = let configs = mapAttrs (_: config: (evalModule configs config).combinedManager) configurations; in configs; | |
| nixosConfigurations = let | |
| withExtraAttrs = config: | |
| config | |
| // { | |
| extraArgs = {}; | |
| inherit (config._module.args) pkgs; | |
| inherit lib; | |
| extendModules = args: withExtraAttrs (config.extendModules args); | |
| }; | |
| configs = mapAttrs (_: config: withExtraAttrs (evalModule configs config).nixos) configurations; | |
| in | |
| configs; | |
| in | |
| explicitOutputs | |
| // { | |
| inherit combinedManagerConfigurations; | |
| nixosConfigurations = nixosConfigurations // explicitOutputs.nixosConfigurations or {}; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment