From 7d7ff85b418e434b342b8fd5abc7b2b5a74dcf33 Mon Sep 17 00:00:00 2001 From: anntnzrb Date: Thu, 9 Oct 2025 00:06:31 -0500 Subject: [PATCH] style: fmt --- snowfall-lib/attrs/default.nix | 3 +- snowfall-lib/checks/default.nix | 4 +- snowfall-lib/default.nix | 16 +- snowfall-lib/flake/default.nix | 168 +++---- snowfall-lib/fp/default.nix | 102 ++-- snowfall-lib/fs/default.nix | 17 +- snowfall-lib/home/default.nix | 772 +++++++++++++++--------------- snowfall-lib/internal/default.nix | 61 +-- snowfall-lib/overlay/default.nix | 22 +- snowfall-lib/package/default.nix | 144 +++--- snowfall-lib/path/default.nix | 15 +- snowfall-lib/shell/default.nix | 4 +- snowfall-lib/system/default.nix | 664 ++++++++++++------------- snowfall-lib/template/default.nix | 3 +- 14 files changed, 1008 insertions(+), 987 deletions(-) diff --git a/snowfall-lib/attrs/default.nix b/snowfall-lib/attrs/default.nix index 8a70baf..7c191f1 100644 --- a/snowfall-lib/attrs/default.nix +++ b/snowfall-lib/attrs/default.nix @@ -90,7 +90,8 @@ in ## ``` ## Result: Merged items with aliases applied #@ (Attrs -> Attrs -> Attrs) -> [Attrs] -> Attrs -> Attrs - merge-with-aliases = merge-fn: items: alias: + merge-with-aliases = + merge-fn: items: alias: let merged = foldl merge-fn { } items; in diff --git a/snowfall-lib/checks/default.nix b/snowfall-lib/checks/default.nix index 7828f44..d01ef61 100644 --- a/snowfall-lib/checks/default.nix +++ b/snowfall-lib/checks/default.nix @@ -16,7 +16,7 @@ ## { another-check = ...; my-check = ...; default = ...; } ## ``` #@ Attrs -> Attrs - create-checks = args: - snowfall-lib.internal.create-simple-derivations (args // { type = "checks"; }); + create-checks = + args: snowfall-lib.internal.create-simple-derivations (args // { type = "checks"; }); }; } diff --git a/snowfall-lib/default.nix b/snowfall-lib/default.nix index c23c865..cf515f2 100644 --- a/snowfall-lib/default.nix +++ b/snowfall-lib/default.nix @@ -50,15 +50,13 @@ let # result: { x = nixpkgs.lib; } get-libs = attrs: - fold - (name: acc: - let value = attrs.${name}; in - if builtins.isAttrs (value.lib or null) - then acc // { ${name} = value.lib; } - else acc - ) - { } - (builtins.attrNames attrs); + fold ( + name: acc: + let + value = attrs.${name}; + in + if builtins.isAttrs (value.lib or null) then acc // { ${name} = value.lib; } else acc + ) { } (builtins.attrNames attrs); # Remove the `self` attribute from an attribute set. # Type: Attrs -> Attrs diff --git a/snowfall-lib/flake/default.nix b/snowfall-lib/flake/default.nix index 11d1bb9..89c8d4e 100644 --- a/snowfall-lib/flake/default.nix +++ b/snowfall-lib/flake/default.nix @@ -20,91 +20,93 @@ let ; in let - flake = let - ## Remove the `self` attribute from an attribute set. - ## Example Usage: - ## ```nix - ## without-self { self = {}; x = true; } - ## ``` - ## Result: - ## ```nix - ## { x = true; } - ## ``` - #@ Attrs -> Attrs - without-self = flake-inputs: builtins.removeAttrs flake-inputs [ "self" ]; + flake = + let + ## Remove the `self` attribute from an attribute set. + ## Example Usage: + ## ```nix + ## without-self { self = {}; x = true; } + ## ``` + ## Result: + ## ```nix + ## { x = true; } + ## ``` + #@ Attrs -> Attrs + without-self = flake-inputs: builtins.removeAttrs flake-inputs [ "self" ]; - ## Remove the `src` attribute from an attribute set. - ## Example Usage: - ## ```nix - ## without-src { src = ./.; x = true; } - ## ``` - ## Result: - ## ```nix - ## { x = true; } - ## ``` - #@ Attrs -> Attrs - without-src = flake-inputs: builtins.removeAttrs flake-inputs [ "src" ]; - in { - inherit without-self without-src; + ## Remove the `src` attribute from an attribute set. + ## Example Usage: + ## ```nix + ## without-src { src = ./.; x = true; } + ## ``` + ## Result: + ## ```nix + ## { x = true; } + ## ``` + #@ Attrs -> Attrs + without-src = flake-inputs: builtins.removeAttrs flake-inputs [ "src" ]; + in + { + inherit without-self without-src; - ## Remove the `src` and `self` attributes from an attribute set. - ## Example Usage: - ## ```nix - ## without-snowfall-inputs { self = {}; src = ./.; x = true; } - ## ``` - ## Result: - ## ```nix - ## { x = true; } - ## ``` - #@ Attrs -> Attrs - without-snowfall-inputs = snowfall-lib.fp.compose without-self without-src; + ## Remove the `src` and `self` attributes from an attribute set. + ## Example Usage: + ## ```nix + ## without-snowfall-inputs { self = {}; src = ./.; x = true; } + ## ``` + ## Result: + ## ```nix + ## { x = true; } + ## ``` + #@ Attrs -> Attrs + without-snowfall-inputs = snowfall-lib.fp.compose without-self without-src; - ## Remove Snowfall-specific attributes so the rest can be safely passed to flake-utils-plus. - ## Example Usage: - ## ```nix - ## without-snowfall-options { src = ./.; x = true; } - ## ``` - ## Result: - ## ```nix - ## { x = true; } - ## ``` - #@ Attrs -> Attrs - without-snowfall-options = - flake-options: - builtins.removeAttrs flake-options [ - "systems" - "modules" - "overlays" - "packages" - "outputs-builder" - "outputsBuilder" - "packagesPrefix" - "hosts" - "homes" - "channels-config" - "templates" - "checks" - "alias" - "snowfall" - ]; + ## Remove Snowfall-specific attributes so the rest can be safely passed to flake-utils-plus. + ## Example Usage: + ## ```nix + ## without-snowfall-options { src = ./.; x = true; } + ## ``` + ## Result: + ## ```nix + ## { x = true; } + ## ``` + #@ Attrs -> Attrs + without-snowfall-options = + flake-options: + builtins.removeAttrs flake-options [ + "systems" + "modules" + "overlays" + "packages" + "outputs-builder" + "outputsBuilder" + "packagesPrefix" + "hosts" + "homes" + "channels-config" + "templates" + "checks" + "alias" + "snowfall" + ]; - ## Transform an attribute set of inputs into an attribute set where the values are the inputs' `lib` attribute. Entries without a `lib` attribute are removed. - ## Example Usage: - ## ```nix - ## get-lib { x = nixpkgs; y = {}; } - ## ``` - ## Result: - ## ```nix - ## { x = nixpkgs.lib; } - ## ``` - #@ Attrs -> Attrs - get-libs = - attrs: - pipe attrs [ - (filterAttrs (name: value: builtins.isAttrs (value.lib or null))) - (mapAttrs (name: value: value.lib)) - ]; - }; + ## Transform an attribute set of inputs into an attribute set where the values are the inputs' `lib` attribute. Entries without a `lib` attribute are removed. + ## Example Usage: + ## ```nix + ## get-lib { x = nixpkgs; y = {}; } + ## ``` + ## Result: + ## ```nix + ## { x = nixpkgs.lib; } + ## ``` + #@ Attrs -> Attrs + get-libs = + attrs: + pipe attrs [ + (filterAttrs (name: value: builtins.isAttrs (value.lib or null))) + (mapAttrs (name: value: value.lib)) + ]; + }; mkFlake = full-flake-options: @@ -227,9 +229,7 @@ let (mapAttrs (home-name: _: flake-outputs.homeConfigurations.${home-name})) (mapAttrs' ( name: value: - nameValuePair - (if hasSuffix "@${system}" name then removeSuffix "@${system}" name else name) - value + nameValuePair (if hasSuffix "@${system}" name then removeSuffix "@${system}" name else name) value )) ]; }; diff --git a/snowfall-lib/fp/default.nix b/snowfall-lib/fp/default.nix index 74a8f02..d0d18fc 100644 --- a/snowfall-lib/fp/default.nix +++ b/snowfall-lib/fp/default.nix @@ -9,57 +9,59 @@ let inherit (core-inputs.nixpkgs.lib) id foldr flip; in { - fp = let - ## Compose two functions. - ## Example Usage: - ## ```nix - ## compose add-two add-one - ## ``` - ## Result: - ## ```nix - ## (x: add-two (add-one x)) - ## ``` - #@ (b -> c) -> (a -> b) -> a -> c - compose = - f: g: x: - f (g x); + fp = + let + ## Compose two functions. + ## Example Usage: + ## ```nix + ## compose add-two add-one + ## ``` + ## Result: + ## ```nix + ## (x: add-two (add-one x)) + ## ``` + #@ (b -> c) -> (a -> b) -> a -> c + compose = + f: g: x: + f (g x); - ## Call a function with an argument. - ## Example Usage: - ## ```nix - ## call (x: x + 1) 0 - ## ``` - ## Result: - ## ```nix - ## 1 - ## ``` - #@ (a -> b) -> a -> b - call = f: x: f x; - in { - inherit compose call; + ## Call a function with an argument. + ## Example Usage: + ## ```nix + ## call (x: x + 1) 0 + ## ``` + ## Result: + ## ```nix + ## 1 + ## ``` + #@ (a -> b) -> a -> b + call = f: x: f x; + in + { + inherit compose call; - ## Compose many functions. - ## Example Usage: - ## ```nix - ## compose-all [ add-two add-one ] - ## ``` - ## Result: - ## ```nix - ## (x: add-two (add-one x)) - ## ``` - #@ [(x -> y)] -> a -> b - compose-all = foldr compose id; + ## Compose many functions. + ## Example Usage: + ## ```nix + ## compose-all [ add-two add-one ] + ## ``` + ## Result: + ## ```nix + ## (x: add-two (add-one x)) + ## ``` + #@ [(x -> y)] -> a -> b + compose-all = foldr compose id; - ## Apply an argument to a function. - ## Example Usage: - ## ```nix - ## apply 0 (x: x + 1) - ## ``` - ## Result: - ## ```nix - ## 1 - ## ``` - #@ a -> (a -> b) -> b - apply = flip call; - }; + ## Apply an argument to a function. + ## Example Usage: + ## ```nix + ## apply 0 (x: x + 1) + ## ``` + ## Result: + ## ```nix + ## 1 + ## ``` + #@ a -> (a -> b) -> b + apply = flip call; + }; } diff --git a/snowfall-lib/fs/default.nix b/snowfall-lib/fs/default.nix index 1e5028f..994f5a3 100644 --- a/snowfall-lib/fs/default.nix +++ b/snowfall-lib/fs/default.nix @@ -122,8 +122,7 @@ in ## ``` #@ Path -> [Path] get-directories-with-default = - path: - builtins.filter (dir: pathExists "${dir}/default.nix") (get-directories path); + path: builtins.filter (dir: pathExists "${dir}/default.nix") (get-directories path); ## Get files at a given path. ## Example Usage: @@ -234,7 +233,9 @@ in ## [ "./something/some-directory/default.nix" ] ## ``` #@ Path -> [Path] - get-default-nix-files-recursive = filter-files-recursive (f: builtins.baseNameOf f == "default.nix"); + get-default-nix-files-recursive = filter-files-recursive ( + f: builtins.baseNameOf f == "default.nix" + ); ## Get nix files at a given path not named "default.nix". ## Example Usage: @@ -246,8 +247,9 @@ in ## [ "./something/a.nix" ] ## ``` #@ Path -> [Path] - get-non-default-nix-files = filter-files (f: - snowfall-lib.path.has-file-extension "nix" f && builtins.baseNameOf f != "default.nix"); + get-non-default-nix-files = filter-files ( + f: snowfall-lib.path.has-file-extension "nix" f && builtins.baseNameOf f != "default.nix" + ); ## Get nix files at a given path not named "default.nix", traversing any directories within. ## Example Usage: @@ -259,7 +261,8 @@ in ## [ "./something/some-directory/a.nix" ] ## ``` #@ Path -> [Path] - get-non-default-nix-files-recursive = filter-files-recursive (f: - snowfall-lib.path.has-file-extension "nix" f && builtins.baseNameOf f != "default.nix"); + get-non-default-nix-files-recursive = filter-files-recursive ( + f: snowfall-lib.path.has-file-extension "nix" f && builtins.baseNameOf f != "default.nix" + ); }; } diff --git a/snowfall-lib/home/default.nix b/snowfall-lib/home/default.nix index d704b96..fa45e63 100644 --- a/snowfall-lib/home/default.nix +++ b/snowfall-lib/home/default.nix @@ -33,409 +33,411 @@ let user-modules-root = snowfall-lib.fs.get-snowfall-file "modules"; in { - home = let - # Modules in home-manager expect `hm` to be available directly on `lib` itself. - home-lib = - # NOTE: This prevents an error during evaluation if the input does - # not exist. - if user-inputs ? home-manager then - snowfall-lib.internal.system-lib.extend ( - final: prev: - # NOTE: This order is important, this library's extend and other utilities must write - # _over_ the original `system-lib`. - snowfall-lib.internal.system-lib - // prev - // { - hm = snowfall-lib.internal.system-lib.home-manager.hm; - } - ) - else - { }; + home = + let + # Modules in home-manager expect `hm` to be available directly on `lib` itself. + home-lib = + # NOTE: This prevents an error during evaluation if the input does + # not exist. + if user-inputs ? home-manager then + snowfall-lib.internal.system-lib.extend ( + final: prev: + # NOTE: This order is important, this library's extend and other utilities must write + # _over_ the original `system-lib`. + snowfall-lib.internal.system-lib + // prev + // { + hm = snowfall-lib.internal.system-lib.home-manager.hm; + } + ) + else + { }; - ## Get the user and host from a combined string. - ## Example Usage: - ## ```nix - ## split-user-and-host "myuser@myhost" - ## ``` - ## Result: - ## ```nix - ## { user = "myuser"; host = "myhost"; } - ## ``` - #@ String -> Attrs - split-user-and-host = - target: - let - name-parts = pipe target [ - (builtins.split "@") - (builtins.filter builtins.isString) - ]; - user = builtins.elemAt name-parts 0; - host = if builtins.length name-parts > 1 then builtins.elemAt name-parts 1 else ""; - in - { - inherit user host; - }; - - ## Create a home. - ## Example Usage: - ## ```nix - ## create-home { path = ./homes/my-home; } - ## ``` - ## Result: - ## ```nix - ## - ## ``` - #@ Attrs -> Attrs - create-home = - { - path, - name ? builtins.unsafeDiscardStringContext (snowfall-lib.system.get-inferred-system-name path), - modules ? [ ], - specialArgs ? { }, - channelName ? "nixpkgs", - system ? "x86_64-linux", - }: - let - user-metadata = split-user-and-host name; - unique-name = if user-metadata.host == "" then "${user-metadata.user}@${system}" else name; - - # NOTE: home-manager has trouble with `pkgs` recursion if it isn't passed in here. - pkgs = user-inputs.self.pkgs.${system}.${channelName} // { - lib = home-lib; + ## Get the user and host from a combined string. + ## Example Usage: + ## ```nix + ## split-user-and-host "myuser@myhost" + ## ``` + ## Result: + ## ```nix + ## { user = "myuser"; host = "myhost"; } + ## ``` + #@ String -> Attrs + split-user-and-host = + target: + let + name-parts = pipe target [ + (builtins.split "@") + (builtins.filter builtins.isString) + ]; + user = builtins.elemAt name-parts 0; + host = if builtins.length name-parts > 1 then builtins.elemAt name-parts 1 else ""; + in + { + inherit user host; }; - lib = home-lib; - in - assert assertMsg (user-inputs ? home-manager) - "In order to create home-manager configurations, you must include `home-manager` as a flake input."; - assert assertMsg ( - (user-metadata.host != "") || !(hasInfix "@" name) - ) "Snowfall Lib homes must be named with the format: user@system"; - { - inherit channelName system; - output = "homeConfigurations"; - - modules = [ - path - ../../modules/home/user/default.nix - ] - ++ modules; - - specialArgs = { - inherit system; - name = unique-name; - inherit (user-metadata) user host; - - format = "home"; - - inputs = snowfall-lib.flake.without-src user-inputs; - namespace = snowfall-config.namespace; + ## Create a home. + ## Example Usage: + ## ```nix + ## create-home { path = ./homes/my-home; } + ## ``` + ## Result: + ## ```nix + ## + ## ``` + #@ Attrs -> Attrs + create-home = + { + path, + name ? builtins.unsafeDiscardStringContext (snowfall-lib.system.get-inferred-system-name path), + modules ? [ ], + specialArgs ? { }, + channelName ? "nixpkgs", + system ? "x86_64-linux", + }: + let + user-metadata = split-user-and-host name; + unique-name = if user-metadata.host == "" then "${user-metadata.user}@${system}" else name; # NOTE: home-manager has trouble with `pkgs` recursion if it isn't passed in here. - inherit pkgs lib; - }; - - builder = - args: - user-inputs.home-manager.lib.homeManagerConfiguration ( - (builtins.removeAttrs args [ - "system" - "specialArgs" - ]) - // { - inherit pkgs lib; - - modules = args.modules ++ [ - ( - module-args: - import ./nix-registry-module.nix ( - module-args - // { - inherit user-inputs core-inputs; - } - ) - ) - { - snowfallorg.user = { - name = mkDefault user-metadata.user; - enable = mkDefault true; - }; - } - ]; - - extraSpecialArgs = specialArgs // args.specialArgs; - } - ); - }; - - ## Get structured data about all homes for a given target. - ## Example Usage: - ## ```nix - ## get-target-homes-metadata ./homes - ## ``` - ## Result: - ## ```nix - ## [ { system = "x86_64-linux"; name = "my-home"; path = "/homes/x86_64-linux/my-home";} ] - ## ``` - #@ String -> [Attrs] - get-target-homes-metadata = - target: - let - existing-homes = snowfall-lib.fs.get-directories-with-default target; - create-home-metadata = - path: - let - # We are building flake outputs based on file contents. Nix doesn't like this - # so we have to explicitly discard the string's path context to allow us to - # use the name as a variable. - basename = builtins.unsafeDiscardStringContext (builtins.baseNameOf path); - # We are building flake outputs based on file contents. Nix doesn't like this - # so we have to explicitly discard the string's path context to allow us to - # use the name as a variable. - system = builtins.unsafeDiscardStringContext (builtins.baseNameOf target); - name = if !(hasInfix "@" basename) then "${basename}@${system}" else basename; - in - { - path = "${path}/default.nix"; - inherit name system; + pkgs = user-inputs.self.pkgs.${system}.${channelName} // { + lib = home-lib; }; - home-configurations = builtins.map create-home-metadata existing-homes; - in - home-configurations; + lib = home-lib; + in + assert assertMsg (user-inputs ? home-manager) + "In order to create home-manager configurations, you must include `home-manager` as a flake input."; + assert assertMsg ( + (user-metadata.host != "") || !(hasInfix "@" name) + ) "Snowfall Lib homes must be named with the format: user@system"; + { + inherit channelName system; - ## Create all available homes. - ## Example Usage: - ## ```nix - ## create-homes { users."my-user@my-system".specialArgs.x = true; modules = [ my-shared-module ]; } - ## ``` - ## Result: - ## ```nix - ## { "my-user@my-system" = ; } - ## ``` - #@ Attrs -> Attrs - create-homes = - homes: - let - targets = snowfall-lib.fs.get-directories user-homes-root; - target-homes-metadata = concatMap get-target-homes-metadata targets; + output = "homeConfigurations"; - user-home-modules = snowfall-lib.module.create-modules { - src = "${user-modules-root}/home"; - }; + modules = [ + path + ../../modules/home/user/default.nix + ] + ++ modules; - user-home-modules-list = mapAttrsToList ( - module-path: module: - args@{ pkgs, ... }: - (module args) - // { - _file = "${user-homes-root}/${module-path}/default.nix"; - } - ) user-home-modules; + specialArgs = { + inherit system; + name = unique-name; + inherit (user-metadata) user host; - create-home' = - home-metadata: - let - inherit (home-metadata) name; - overrides = homes.users.${name} or { }; - in - { - "${name}" = create-home ( - overrides - // home-metadata + format = "home"; + + inputs = snowfall-lib.flake.without-src user-inputs; + namespace = snowfall-config.namespace; + + # NOTE: home-manager has trouble with `pkgs` recursion if it isn't passed in here. + inherit pkgs lib; + }; + + builder = + args: + user-inputs.home-manager.lib.homeManagerConfiguration ( + (builtins.removeAttrs args [ + "system" + "specialArgs" + ]) // { - modules = user-home-modules-list ++ (homes.users.${name}.modules or [ ]) ++ (homes.modules or [ ]); - } - ); - }; + inherit pkgs lib; - created-homes = foldl ( - homes: home-metadata: homes // (create-home' home-metadata) - ) { } target-homes-metadata; - in - created-homes; - - ## Create system modules for home-manager integration. - ## Example Usage: - ## ```nix - ## create-home-system-modules { users."my-user@my-system".specialArgs.x = true; modules = [ my-shared-module ]; } - ## ``` - ## Result: - ## ```nix - ## [Module] - ## ``` - #@ Attrs -> [Module] - create-home-system-modules = - users: - let - created-users = create-homes users; - user-home-modules = snowfall-lib.module.create-modules { - src = "${user-modules-root}/home"; - }; - - shared-modules = builtins.map (module: { - config.home-manager.sharedModules = [ module ]; - }) (users.modules or [ ]); - - shared-user-modules = mapAttrsToList (module-path: module: { - _file = "${user-modules-root}/home/${module-path}/default.nix"; - - config = { - home-manager.sharedModules = [ module ]; - }; - }) user-home-modules; - - snowfall-user-home-module = { - _file = "virtual:snowfallorg/modules/home/user/default.nix"; - - config = { - home-manager.sharedModules = [ - ../../modules/home/user/default.nix - ]; - }; - }; - - extra-special-args-module = - args@{ - config, - pkgs, - system ? pkgs.stdenv.hostPlatform.system, - target ? system, - format ? "home", - host ? "", - virtual ? (snowfall-lib.system.is-virtual target), - systems ? { }, - ... - }: - { - _file = "virtual:snowfallorg/home/extra-special-args"; - - config = { - home-manager.extraSpecialArgs = { - inherit - system - target - format - virtual - systems - host - ; - inherit (snowfall-config) namespace; - - lib = home-lib; - - inputs = snowfall-lib.flake.without-src user-inputs; - }; - }; - }; - - system-modules = builtins.map ( - name: - let - created-user = created-users.${name}; - user-module = head created-user.modules; - other-modules = users.users.${name}.modules or [ ]; - user-name = created-user.specialArgs.user; - in - args@{ - config, - options, - pkgs, - host ? "", - system ? pkgs.stdenv.hostPlatform.system, - ... - }: - let - host-matches = (name == "${user-name}@${host}") || (name == "${user-name}@${system}"); - - # NOTE: To conform to the config structure of home-manager, we have to - # remap the options coming from `snowfallorg.user..home.config` since `mkAliasDefinitions` - # does not let us target options within a submodule. - wrap-user-options = - user-option: - if (user-option ? "_type") && user-option._type == "merge" then - user-option - // { - contents = builtins.map ( - merge-entry: merge-entry.${user-name}.home.config or { } - ) user-option.contents; - } - else - (builtins.trace '' - ============= - Snowfall Lib: - Option value for `snowfallorg.users.${user-name}` was not detected to be merged. - - Please report the issue on GitHub with a link to your configuration so we can debug the problem: - https://github.com/snowfallorg/lib/issues/new - ============= - '') - user-option; - - home-config = mkAliasAndWrapDefinitions wrap-user-options options.snowfallorg.users; - in - { - _file = "virtual:snowfallorg/home/user/${name}"; - - config = mkIf host-matches { - # Initialize user information. - snowfallorg.users.${user-name}.home.config = { - snowfallorg.user = { - enable = mkDefault true; - name = mkDefault user-name; - }; - - # NOTE: specialArgs are not propagated by Home-Manager without this. - # However, not all specialArgs values can be set when using `_module.args`. - _module.args = - builtins.removeAttrs - ( - (users.users.${name}.specialArgs or { }) + modules = args.modules ++ [ + ( + module-args: + import ./nix-registry-module.nix ( + module-args // { - namespace = snowfall-config.namespace; + inherit user-inputs core-inputs; } ) - [ - "options" - "config" - "lib" - "pkgs" - "specialArgs" - "host" - ]; - }; - - home-manager = { - users.${user-name} = mkIf config.snowfallorg.users.${user-name}.home.enable ( - { pkgs, ... }: + ) { - imports = (home-config.imports or [ ]) ++ other-modules ++ [ user-module ]; - config = builtins.removeAttrs home-config [ "imports" ]; + snowfallorg.user = { + name = mkDefault user-metadata.user; + enable = mkDefault true; + }; } - ); + ]; - # NOTE: Without this home-manager will instead create its own package set which won't contain the same config and - # user-defined packages/overlays as the flake's nixpkgs channel. - useGlobalPkgs = mkDefault true; + extraSpecialArgs = specialArgs // args.specialArgs; + } + ); + }; + + ## Get structured data about all homes for a given target. + ## Example Usage: + ## ```nix + ## get-target-homes-metadata ./homes + ## ``` + ## Result: + ## ```nix + ## [ { system = "x86_64-linux"; name = "my-home"; path = "/homes/x86_64-linux/my-home";} ] + ## ``` + #@ String -> [Attrs] + get-target-homes-metadata = + target: + let + existing-homes = snowfall-lib.fs.get-directories-with-default target; + create-home-metadata = + path: + let + # We are building flake outputs based on file contents. Nix doesn't like this + # so we have to explicitly discard the string's path context to allow us to + # use the name as a variable. + basename = builtins.unsafeDiscardStringContext (builtins.baseNameOf path); + # We are building flake outputs based on file contents. Nix doesn't like this + # so we have to explicitly discard the string's path context to allow us to + # use the name as a variable. + system = builtins.unsafeDiscardStringContext (builtins.baseNameOf target); + name = if !(hasInfix "@" basename) then "${basename}@${system}" else basename; + in + { + path = "${path}/default.nix"; + inherit name system; + }; + home-configurations = builtins.map create-home-metadata existing-homes; + in + home-configurations; + + ## Create all available homes. + ## Example Usage: + ## ```nix + ## create-homes { users."my-user@my-system".specialArgs.x = true; modules = [ my-shared-module ]; } + ## ``` + ## Result: + ## ```nix + ## { "my-user@my-system" = ; } + ## ``` + #@ Attrs -> Attrs + create-homes = + homes: + let + targets = snowfall-lib.fs.get-directories user-homes-root; + target-homes-metadata = concatMap get-target-homes-metadata targets; + + user-home-modules = snowfall-lib.module.create-modules { + src = "${user-modules-root}/home"; + }; + + user-home-modules-list = mapAttrsToList ( + module-path: module: + args@{ pkgs, ... }: + (module args) + // { + _file = "${user-homes-root}/${module-path}/default.nix"; + } + ) user-home-modules; + + create-home' = + home-metadata: + let + inherit (home-metadata) name; + overrides = homes.users.${name} or { }; + in + { + "${name}" = create-home ( + overrides + // home-metadata + // { + modules = user-home-modules-list ++ (homes.users.${name}.modules or [ ]) ++ (homes.modules or [ ]); + } + ); + }; + + created-homes = foldl ( + homes: home-metadata: homes // (create-home' home-metadata) + ) { } target-homes-metadata; + in + created-homes; + + ## Create system modules for home-manager integration. + ## Example Usage: + ## ```nix + ## create-home-system-modules { users."my-user@my-system".specialArgs.x = true; modules = [ my-shared-module ]; } + ## ``` + ## Result: + ## ```nix + ## [Module] + ## ``` + #@ Attrs -> [Module] + create-home-system-modules = + users: + let + created-users = create-homes users; + user-home-modules = snowfall-lib.module.create-modules { + src = "${user-modules-root}/home"; + }; + + shared-modules = builtins.map (module: { + config.home-manager.sharedModules = [ module ]; + }) (users.modules or [ ]); + + shared-user-modules = mapAttrsToList (module-path: module: { + _file = "${user-modules-root}/home/${module-path}/default.nix"; + + config = { + home-manager.sharedModules = [ module ]; + }; + }) user-home-modules; + + snowfall-user-home-module = { + _file = "virtual:snowfallorg/modules/home/user/default.nix"; + + config = { + home-manager.sharedModules = [ + ../../modules/home/user/default.nix + ]; + }; + }; + + extra-special-args-module = + args@{ + config, + pkgs, + system ? pkgs.stdenv.hostPlatform.system, + target ? system, + format ? "home", + host ? "", + virtual ? (snowfall-lib.system.is-virtual target), + systems ? { }, + ... + }: + { + _file = "virtual:snowfallorg/home/extra-special-args"; + + config = { + home-manager.extraSpecialArgs = { + inherit + system + target + format + virtual + systems + host + ; + inherit (snowfall-config) namespace; + + lib = home-lib; + + inputs = snowfall-lib.flake.without-src user-inputs; + }; }; }; - } - ) (builtins.attrNames created-users); - in - [ - extra-special-args-module - snowfall-user-home-module - ] - ++ shared-modules - ++ shared-user-modules - ++ system-modules; - in { - inherit - home-lib - split-user-and-host - create-home - get-target-homes-metadata - create-homes - create-home-system-modules - ; - }; + + system-modules = builtins.map ( + name: + let + created-user = created-users.${name}; + user-module = head created-user.modules; + other-modules = users.users.${name}.modules or [ ]; + user-name = created-user.specialArgs.user; + in + args@{ + config, + options, + pkgs, + host ? "", + system ? pkgs.stdenv.hostPlatform.system, + ... + }: + let + host-matches = (name == "${user-name}@${host}") || (name == "${user-name}@${system}"); + + # NOTE: To conform to the config structure of home-manager, we have to + # remap the options coming from `snowfallorg.user..home.config` since `mkAliasDefinitions` + # does not let us target options within a submodule. + wrap-user-options = + user-option: + if (user-option ? "_type") && user-option._type == "merge" then + user-option + // { + contents = builtins.map ( + merge-entry: merge-entry.${user-name}.home.config or { } + ) user-option.contents; + } + else + (builtins.trace '' + ============= + Snowfall Lib: + Option value for `snowfallorg.users.${user-name}` was not detected to be merged. + + Please report the issue on GitHub with a link to your configuration so we can debug the problem: + https://github.com/snowfallorg/lib/issues/new + ============= + '') + user-option; + + home-config = mkAliasAndWrapDefinitions wrap-user-options options.snowfallorg.users; + in + { + _file = "virtual:snowfallorg/home/user/${name}"; + + config = mkIf host-matches { + # Initialize user information. + snowfallorg.users.${user-name}.home.config = { + snowfallorg.user = { + enable = mkDefault true; + name = mkDefault user-name; + }; + + # NOTE: specialArgs are not propagated by Home-Manager without this. + # However, not all specialArgs values can be set when using `_module.args`. + _module.args = + builtins.removeAttrs + ( + (users.users.${name}.specialArgs or { }) + // { + namespace = snowfall-config.namespace; + } + ) + [ + "options" + "config" + "lib" + "pkgs" + "specialArgs" + "host" + ]; + }; + + home-manager = { + users.${user-name} = mkIf config.snowfallorg.users.${user-name}.home.enable ( + { pkgs, ... }: + { + imports = (home-config.imports or [ ]) ++ other-modules ++ [ user-module ]; + config = builtins.removeAttrs home-config [ "imports" ]; + } + ); + + # NOTE: Without this home-manager will instead create its own package set which won't contain the same config and + # user-defined packages/overlays as the flake's nixpkgs channel. + useGlobalPkgs = mkDefault true; + }; + }; + } + ) (builtins.attrNames created-users); + in + [ + extra-special-args-module + snowfall-user-home-module + ] + ++ shared-modules + ++ shared-user-modules + ++ system-modules; + in + { + inherit + home-lib + split-user-and-host + create-home + get-target-homes-metadata + create-homes + create-home-system-modules + ; + }; } diff --git a/snowfall-lib/internal/default.nix b/snowfall-lib/internal/default.nix index 16c475c..8efe7aa 100644 --- a/snowfall-lib/internal/default.nix +++ b/snowfall-lib/internal/default.nix @@ -66,36 +66,37 @@ in internal = { inherit system-lib user-lib; - create-simple-derivations = { - type, - channels, - src ? snowfall-lib.fs.get-snowfall-file type, - pkgs ? channels.nixpkgs, - overrides ? {}, - alias ? {}, - }: - let - user-items = snowfall-lib.fs.get-default-nix-files-recursive src; - - create-metadata = item: { - name = snowfall-lib.path.get-output-name item; - drv = callPackageWith ( - pkgs // { - inherit channels; - lib = system-lib; - inputs = snowfall-lib.flake.without-src user-inputs; - namespace = snowfall-config.namespace; - } - ) item {}; - }; - - items-metadata = builtins.map create-metadata user-items; - - merge-items = items: metadata: - items // { ${metadata.name} = metadata.drv; }; - - items = snowfall-lib.attrs.merge-with-aliases merge-items items-metadata alias // overrides; - in + create-simple-derivations = + { + type, + channels, + src ? snowfall-lib.fs.get-snowfall-file type, + pkgs ? channels.nixpkgs, + overrides ? { }, + alias ? { }, + }: + let + user-items = snowfall-lib.fs.get-default-nix-files-recursive src; + + create-metadata = item: { + name = snowfall-lib.path.get-output-name item; + drv = callPackageWith ( + pkgs + // { + inherit channels; + lib = system-lib; + inputs = snowfall-lib.flake.without-src user-inputs; + namespace = snowfall-config.namespace; + } + ) item { }; + }; + + items-metadata = builtins.map create-metadata user-items; + + merge-items = items: metadata: items // { ${metadata.name} = metadata.drv; }; + + items = snowfall-lib.attrs.merge-with-aliases merge-items items-metadata alias // overrides; + in filterPackages pkgs.stdenv.hostPlatform.system items; }; } diff --git a/snowfall-lib/overlay/default.nix b/snowfall-lib/overlay/default.nix index 0b334c9..0978dc0 100644 --- a/snowfall-lib/overlay/default.nix +++ b/snowfall-lib/overlay/default.nix @@ -5,7 +5,13 @@ snowfall-config, }: let - inherit (core-inputs.nixpkgs.lib) assertMsg foldl concatStringsSep pipe flatten; + inherit (core-inputs.nixpkgs.lib) + assertMsg + foldl + concatStringsSep + pipe + flatten + ; user-overlays-root = snowfall-lib.fs.get-snowfall-file "overlays"; user-packages-root = snowfall-lib.fs.get-snowfall-file "packages"; @@ -191,12 +197,14 @@ in default-overlay = final: prev: - pipe [ package-overlays overlays ] [ - (builtins.map builtins.attrValues) - flatten - (builtins.map (overlay: overlay final prev)) - snowfall-lib.attrs.merge-shallow-packages - ]; + pipe + [ package-overlays overlays ] + [ + (builtins.map builtins.attrValues) + flatten + (builtins.map (overlay: overlay final prev)) + snowfall-lib.attrs.merge-shallow-packages + ]; in package-overlays // overlays // { default = default-overlay; } // extra-overlays; }; diff --git a/snowfall-lib/package/default.nix b/snowfall-lib/package/default.nix index 99a4c33..b93e825 100644 --- a/snowfall-lib/package/default.nix +++ b/snowfall-lib/package/default.nix @@ -18,78 +18,80 @@ let user-packages-root = snowfall-lib.fs.get-snowfall-file "packages"; in { - package = let - ## Create flake output packages. - ## Example Usage: - ## ```nix - ## create-packages { inherit channels; src = ./my-packages; overrides = { inherit another-package; }; alias.default = "another-package"; } - ## ``` - ## Result: - ## ```nix - ## { another-package = ...; my-package = ...; default = ...; } - ## ``` - #@ Attrs -> Attrs - create-packages = - { - channels, - src ? user-packages-root, - pkgs ? channels.nixpkgs, - overrides ? { }, - alias ? { }, - namespace ? snowfall-config.namespace, - }: - let - user-packages = snowfall-lib.fs.get-default-nix-files-recursive src; - merge-packages = - packages: metadata: - packages - // { - ${metadata.name} = metadata.drv; - }; - packages-without-aliases = fix ( - packages-without-aliases: - let - create-package-metadata = - package: - let - namespaced-packages = { - ${namespace} = packages-without-aliases; - }; - extra-inputs = - pkgs - // namespaced-packages - // { - inherit channels namespace; - lib = snowfall-lib.internal.system-lib; - pkgs = pkgs // namespaced-packages; - inputs = user-inputs; + package = + let + ## Create flake output packages. + ## Example Usage: + ## ```nix + ## create-packages { inherit channels; src = ./my-packages; overrides = { inherit another-package; }; alias.default = "another-package"; } + ## ``` + ## Result: + ## ```nix + ## { another-package = ...; my-package = ...; default = ...; } + ## ``` + #@ Attrs -> Attrs + create-packages = + { + channels, + src ? user-packages-root, + pkgs ? channels.nixpkgs, + overrides ? { }, + alias ? { }, + namespace ? snowfall-config.namespace, + }: + let + user-packages = snowfall-lib.fs.get-default-nix-files-recursive src; + merge-packages = + packages: metadata: + packages + // { + ${metadata.name} = metadata.drv; + }; + packages-without-aliases = fix ( + packages-without-aliases: + let + create-package-metadata = + package: + let + namespaced-packages = { + ${namespace} = packages-without-aliases; }; - in - { - # We are building flake outputs based on file paths. Nix doesn't allow this - # so we have to explicitly discard the string's path context to use it as an attribute name. - name = builtins.unsafeDiscardStringContext (snowfall-lib.path.get-parent-directory package); - drv = - let - pkg = callPackageWith extra-inputs package { }; - in - pkg - // { - meta = (pkg.meta or { }) // { - snowfall = { - path = package; + extra-inputs = + pkgs + // namespaced-packages + // { + inherit channels namespace; + lib = snowfall-lib.internal.system-lib; + pkgs = pkgs // namespaced-packages; + inputs = user-inputs; + }; + in + { + # We are building flake outputs based on file paths. Nix doesn't allow this + # so we have to explicitly discard the string's path context to use it as an attribute name. + name = builtins.unsafeDiscardStringContext (snowfall-lib.path.get-parent-directory package); + drv = + let + pkg = callPackageWith extra-inputs package { }; + in + pkg + // { + meta = (pkg.meta or { }) // { + snowfall = { + path = package; + }; }; }; - }; - }; - packages-metadata = builtins.map create-package-metadata user-packages; - in - foldl merge-packages { } packages-metadata - ); - packages = snowfall-lib.attrs.apply-aliases-and-overrides packages-without-aliases alias overrides; - in - filterPackages pkgs.stdenv.hostPlatform.system packages; - in { - inherit create-packages; - }; + }; + packages-metadata = builtins.map create-package-metadata user-packages; + in + foldl merge-packages { } packages-metadata + ); + packages = snowfall-lib.attrs.apply-aliases-and-overrides packages-without-aliases alias overrides; + in + filterPackages pkgs.stdenv.hostPlatform.system packages; + in + { + inherit create-packages; + }; } diff --git a/snowfall-lib/path/default.nix b/snowfall-lib/path/default.nix index 1a35325..357d5bd 100644 --- a/snowfall-lib/path/default.nix +++ b/snowfall-lib/path/default.nix @@ -11,7 +11,12 @@ let dirOf concatStringsSep ; - inherit (core-inputs.nixpkgs.lib) assertMsg last init hasPrefix; + inherit (core-inputs.nixpkgs.lib) + assertMsg + last + init + hasPrefix + ; file-name-regex = "(.*)\\.(.*)$"; in @@ -131,9 +136,7 @@ in ## "bar" ## ``` #@ Path -> String - get-output-name = snowfall-lib.fp.compose - builtins.unsafeDiscardStringContext - get-parent-directory; + get-output-name = snowfall-lib.fp.compose builtins.unsafeDiscardStringContext get-parent-directory; ## Get the directory name for flake outputs. ## Example Usage: @@ -145,9 +148,7 @@ in ## "foo" ## ``` #@ Path -> String - get-directory-name = snowfall-lib.fp.compose - builtins.unsafeDiscardStringContext - baseNameOf; + get-directory-name = snowfall-lib.fp.compose builtins.unsafeDiscardStringContext baseNameOf; ## Get relative module path from source directory. ## Example Usage: diff --git a/snowfall-lib/shell/default.nix b/snowfall-lib/shell/default.nix index 5173e37..58123d4 100644 --- a/snowfall-lib/shell/default.nix +++ b/snowfall-lib/shell/default.nix @@ -16,7 +16,7 @@ ## { another-shell = ...; my-shell = ...; default = ...; } ## ``` #@ Attrs -> Attrs - create-shells = args: - snowfall-lib.internal.create-simple-derivations (args // { type = "shells"; }); + create-shells = + args: snowfall-lib.internal.create-simple-derivations (args // { type = "shells"; }); }; } diff --git a/snowfall-lib/system/default.nix b/snowfall-lib/system/default.nix index 919e9a9..7a78d07 100644 --- a/snowfall-lib/system/default.nix +++ b/snowfall-lib/system/default.nix @@ -22,345 +22,347 @@ let user-modules-root = snowfall-lib.fs.get-snowfall-file "modules"; in { - system = let - ## Get the name of a system based on its file path. - ## Example Usage: - ## ```nix - ## get-inferred-system-name "/systems/my-system/default.nix" - ## ``` - ## Result: - ## ```nix - ## "my-system" - ## ``` - #@ Path -> String - get-inferred-system-name = - path: - if snowfall-lib.path.has-file-extension "nix" path then - snowfall-lib.path.get-parent-directory path - else - baseNameOf path; + system = + let + ## Get the name of a system based on its file path. + ## Example Usage: + ## ```nix + ## get-inferred-system-name "/systems/my-system/default.nix" + ## ``` + ## Result: + ## ```nix + ## "my-system" + ## ``` + #@ Path -> String + get-inferred-system-name = + path: + if snowfall-lib.path.has-file-extension "nix" path then + snowfall-lib.path.get-parent-directory path + else + baseNameOf path; - ## Check whether a named system is macOS. - ## Example Usage: - ## ```nix - ## is-darwin "x86_64-linux" - ## ``` - ## Result: - ## ```nix - ## false - ## ``` - #@ String -> Bool - is-darwin = hasInfix "darwin"; + ## Check whether a named system is macOS. + ## Example Usage: + ## ```nix + ## is-darwin "x86_64-linux" + ## ``` + ## Result: + ## ```nix + ## false + ## ``` + #@ String -> Bool + is-darwin = hasInfix "darwin"; - ## Check whether a named system is Linux. - ## Example Usage: - ## ```nix - ## is-linux "x86_64-linux" - ## ``` - ## Result: - ## ```nix - ## false - ## ``` - #@ String -> Bool - is-linux = hasInfix "linux"; + ## Check whether a named system is Linux. + ## Example Usage: + ## ```nix + ## is-linux "x86_64-linux" + ## ``` + ## Result: + ## ```nix + ## false + ## ``` + #@ String -> Bool + is-linux = hasInfix "linux"; - ## Check whether a named system is virtual. - ## Example Usage: - ## ```nix - ## is-virtual "x86_64-iso" - ## ``` - ## Result: - ## ```nix - ## true - ## ``` - #@ String -> Bool - is-virtual = target: (get-virtual-system-type target) != ""; + ## Check whether a named system is virtual. + ## Example Usage: + ## ```nix + ## is-virtual "x86_64-iso" + ## ``` + ## Result: + ## ```nix + ## true + ## ``` + #@ String -> Bool + is-virtual = target: (get-virtual-system-type target) != ""; - ## Get the virtual system type of a system target. - ## Example Usage: - ## ```nix - ## get-virtual-system-type "x86_64-iso" - ## ``` - ## Result: - ## ```nix - ## "iso" - ## ``` - #@ String -> String - get-virtual-system-type = - target: - foldl ( - result: virtual-system: - if result == "" && hasInfix virtual-system target then virtual-system else result - ) "" virtual-systems; + ## Get the virtual system type of a system target. + ## Example Usage: + ## ```nix + ## get-virtual-system-type "x86_64-iso" + ## ``` + ## Result: + ## ```nix + ## "iso" + ## ``` + #@ String -> String + get-virtual-system-type = + target: + foldl ( + result: virtual-system: + if result == "" && hasInfix virtual-system target then virtual-system else result + ) "" virtual-systems; - ## Get structured data about all systems for a given target. - ## Example Usage: - ## ```nix - ## get-target-systems-metadata "x86_64-linux" - ## ``` - ## Result: - ## ```nix - ## [ { target = "x86_64-linux"; name = "my-machine"; path = "/systems/x86_64-linux/my-machine"; } ] - ## ``` - #@ String -> [Attrs] - get-target-systems-metadata = - target: - let - existing-systems = snowfall-lib.fs.get-directories-with-default target; - create-system-metadata = path: { - path = "${path}/default.nix"; - # We are building flake outputs based on file contents. Nix doesn't like this - # so we have to explicitly discard the string's path context to allow us to - # use the name as a variable. - name = builtins.unsafeDiscardStringContext (builtins.baseNameOf path); - # We are building flake outputs based on file contents. Nix doesn't like this - # so we have to explicitly discard the string's path context to allow us to - # use the name as a variable. - target = builtins.unsafeDiscardStringContext (builtins.baseNameOf target); - }; - system-configurations = builtins.map create-system-metadata existing-systems; - in - system-configurations; + ## Get structured data about all systems for a given target. + ## Example Usage: + ## ```nix + ## get-target-systems-metadata "x86_64-linux" + ## ``` + ## Result: + ## ```nix + ## [ { target = "x86_64-linux"; name = "my-machine"; path = "/systems/x86_64-linux/my-machine"; } ] + ## ``` + #@ String -> [Attrs] + get-target-systems-metadata = + target: + let + existing-systems = snowfall-lib.fs.get-directories-with-default target; + create-system-metadata = path: { + path = "${path}/default.nix"; + # We are building flake outputs based on file contents. Nix doesn't like this + # so we have to explicitly discard the string's path context to allow us to + # use the name as a variable. + name = builtins.unsafeDiscardStringContext (builtins.baseNameOf path); + # We are building flake outputs based on file contents. Nix doesn't like this + # so we have to explicitly discard the string's path context to allow us to + # use the name as a variable. + target = builtins.unsafeDiscardStringContext (builtins.baseNameOf target); + }; + system-configurations = builtins.map create-system-metadata existing-systems; + in + system-configurations; - ## Get the system builder for a given target. - ## Example Usage: - ## ```nix - ## get-system-builder "x86_64-iso" - ## ``` - ## Result: - ## ```nix - ## (args: ) - ## ``` - #@ String -> Function - get-system-builder = - target: - let - virtual-system-type = get-virtual-system-type target; - virtual-system-builder = - args: - assert assertMsg ( - user-inputs ? nixos-generators - ) "In order to create virtual systems, you must include `nixos-generators` as a flake input."; - user-inputs.nixos-generators.nixosGenerate ( - args - // { - format = virtual-system-type; - specialArgs = args.specialArgs // { - format = virtual-system-type; - }; - modules = args.modules ++ [ - ../../modules/nixos/user/default.nix - ]; - } - ); - darwin-system-builder = - args: - assert assertMsg ( - user-inputs ? darwin - ) "In order to create virtual systems, you must include `darwin` as a flake input."; - user-inputs.darwin.lib.darwinSystem ( - (builtins.removeAttrs args [ - "system" - "modules" - ]) - // { - specialArgs = args.specialArgs // { - format = "darwin"; - }; - modules = args.modules ++ [ - ../../modules/darwin/user/default.nix - ]; - } - ); - linux-system-builder = - args: - core-inputs.nixpkgs.lib.nixosSystem ( - args - // { - specialArgs = args.specialArgs // { - format = "linux"; - }; - modules = args.modules ++ [ - ../../modules/nixos/user/default.nix - ]; - } - ); - in - if virtual-system-type != "" then - virtual-system-builder - else if is-darwin target then - darwin-system-builder - else - linux-system-builder; - - ## Get the flake output attribute for a system target. - ## Example Usage: - ## ```nix - ## get-system-output "aarch64-darwin" - ## ``` - ## Result: - ## ```nix - ## "darwinConfigurations" - ## ``` - #@ String -> String - get-system-output = - target: - let - virtual-system-type = get-virtual-system-type target; - in - if virtual-system-type != "" then - "${virtual-system-type}Configurations" - else if is-darwin target then - "darwinConfigurations" - else - "nixosConfigurations"; - - ## Get the resolved (non-virtual) system target. - ## Example Usage: - ## ```nix - ## get-resolved-system-target "x86_64-iso" - ## ``` - ## Result: - ## ```nix - ## "x86_64-linux" - ## ``` - #@ String -> String - get-resolved-system-target = - target: - let - virtual-system-type = get-virtual-system-type target; - in - if virtual-system-type != "" then - builtins.replaceStrings [ virtual-system-type ] [ "linux" ] target - else - target; - - ## Create a system. - ## Example Usage: - ## ```nix - ## create-system { path = ./systems/my-system; } - ## ``` - ## Result: - ## ```nix - ## - ## ``` - #@ Attrs -> Attrs - create-system = - { - target ? "x86_64-linux", - system ? get-resolved-system-target target, - path, - name ? builtins.unsafeDiscardStringContext (get-inferred-system-name path), - modules ? [ ], - specialArgs ? { }, - channelName ? "nixpkgs", - builder ? get-system-builder target, - output ? get-system-output target, - systems ? { }, - homes ? { }, - }: - let - lib = snowfall-lib.internal.system-lib; - home-system-modules = snowfall-lib.home.create-home-system-modules homes; - home-manager-module = - if is-darwin system then - user-inputs.home-manager.darwinModules.home-manager - else - user-inputs.home-manager.nixosModules.home-manager; - home-manager-modules = [ home-manager-module ] ++ home-system-modules; - in - { - inherit - channelName - system - builder - output - ; - - modules = [ path ] ++ modules ++ (optionals (user-inputs ? home-manager) home-manager-modules); - - specialArgs = specialArgs // { - inherit - target - system - systems - lib - ; - host = name; - - virtual = (get-virtual-system-type target) != ""; - inputs = snowfall-lib.flake.without-src user-inputs; - namespace = snowfall-config.namespace; - }; - }; - - ## Create all available systems. - ## Example Usage: - ## ```nix - ## create-systems { hosts.my-host.specialArgs.x = true; modules.nixos = [ my-shared-module ]; } - ## ``` - ## Result: - ## ```nix - ## { my-host = ; } - ## ``` - #@ Attrs -> Attrs - create-systems = - { - systems ? { }, - homes ? { }, - }: - let - targets = snowfall-lib.fs.get-directories user-systems-root; - target-systems-metadata = concatMap get-target-systems-metadata targets; - user-nixos-modules = snowfall-lib.module.create-modules { - src = "${user-modules-root}/nixos"; - }; - user-darwin-modules = snowfall-lib.module.create-modules { - src = "${user-modules-root}/darwin"; - }; - nixos-modules = systems.modules.nixos or [ ]; - darwin-modules = systems.modules.darwin or [ ]; - - create-system' = - created-systems: system-metadata: - let - overrides = systems.hosts.${system-metadata.name} or { }; - user-modules = if is-darwin system-metadata.target then user-darwin-modules else user-nixos-modules; - user-modules-list = builtins.attrValues user-modules; - system-modules = if is-darwin system-metadata.target then darwin-modules else nixos-modules; - in - { - ${system-metadata.name} = create-system ( - overrides - // system-metadata + ## Get the system builder for a given target. + ## Example Usage: + ## ```nix + ## get-system-builder "x86_64-iso" + ## ``` + ## Result: + ## ```nix + ## (args: ) + ## ``` + #@ String -> Function + get-system-builder = + target: + let + virtual-system-type = get-virtual-system-type target; + virtual-system-builder = + args: + assert assertMsg ( + user-inputs ? nixos-generators + ) "In order to create virtual systems, you must include `nixos-generators` as a flake input."; + user-inputs.nixos-generators.nixosGenerate ( + args // { - systems = created-systems; - modules = user-modules-list ++ (overrides.modules or [ ]) ++ system-modules; - inherit homes; + format = virtual-system-type; + specialArgs = args.specialArgs // { + format = virtual-system-type; + }; + modules = args.modules ++ [ + ../../modules/nixos/user/default.nix + ]; } ); + darwin-system-builder = + args: + assert assertMsg ( + user-inputs ? darwin + ) "In order to create virtual systems, you must include `darwin` as a flake input."; + user-inputs.darwin.lib.darwinSystem ( + (builtins.removeAttrs args [ + "system" + "modules" + ]) + // { + specialArgs = args.specialArgs // { + format = "darwin"; + }; + modules = args.modules ++ [ + ../../modules/darwin/user/default.nix + ]; + } + ); + linux-system-builder = + args: + core-inputs.nixpkgs.lib.nixosSystem ( + args + // { + specialArgs = args.specialArgs // { + format = "linux"; + }; + modules = args.modules ++ [ + ../../modules/nixos/user/default.nix + ]; + } + ); + in + if virtual-system-type != "" then + virtual-system-builder + else if is-darwin target then + darwin-system-builder + else + linux-system-builder; + + ## Get the flake output attribute for a system target. + ## Example Usage: + ## ```nix + ## get-system-output "aarch64-darwin" + ## ``` + ## Result: + ## ```nix + ## "darwinConfigurations" + ## ``` + #@ String -> String + get-system-output = + target: + let + virtual-system-type = get-virtual-system-type target; + in + if virtual-system-type != "" then + "${virtual-system-type}Configurations" + else if is-darwin target then + "darwinConfigurations" + else + "nixosConfigurations"; + + ## Get the resolved (non-virtual) system target. + ## Example Usage: + ## ```nix + ## get-resolved-system-target "x86_64-iso" + ## ``` + ## Result: + ## ```nix + ## "x86_64-linux" + ## ``` + #@ String -> String + get-resolved-system-target = + target: + let + virtual-system-type = get-virtual-system-type target; + in + if virtual-system-type != "" then + builtins.replaceStrings [ virtual-system-type ] [ "linux" ] target + else + target; + + ## Create a system. + ## Example Usage: + ## ```nix + ## create-system { path = ./systems/my-system; } + ## ``` + ## Result: + ## ```nix + ## + ## ``` + #@ Attrs -> Attrs + create-system = + { + target ? "x86_64-linux", + system ? get-resolved-system-target target, + path, + name ? builtins.unsafeDiscardStringContext (get-inferred-system-name path), + modules ? [ ], + specialArgs ? { }, + channelName ? "nixpkgs", + builder ? get-system-builder target, + output ? get-system-output target, + systems ? { }, + homes ? { }, + }: + let + lib = snowfall-lib.internal.system-lib; + home-system-modules = snowfall-lib.home.create-home-system-modules homes; + home-manager-module = + if is-darwin system then + user-inputs.home-manager.darwinModules.home-manager + else + user-inputs.home-manager.nixosModules.home-manager; + home-manager-modules = [ home-manager-module ] ++ home-system-modules; + in + { + inherit + channelName + system + builder + output + ; + + modules = [ path ] ++ modules ++ (optionals (user-inputs ? home-manager) home-manager-modules); + + specialArgs = specialArgs // { + inherit + target + system + systems + lib + ; + host = name; + + virtual = (get-virtual-system-type target) != ""; + inputs = snowfall-lib.flake.without-src user-inputs; + namespace = snowfall-config.namespace; }; - created-systems = fix ( - created-systems: - foldl ( - systems: system-metadata: systems // (create-system' created-systems system-metadata) - ) { } target-systems-metadata - ); - in - created-systems; - in { - inherit - get-inferred-system-name - is-darwin - is-linux - is-virtual - get-virtual-system-type - get-target-systems-metadata - get-system-builder - get-system-output - get-resolved-system-target - create-system - create-systems - ; - }; + }; + + ## Create all available systems. + ## Example Usage: + ## ```nix + ## create-systems { hosts.my-host.specialArgs.x = true; modules.nixos = [ my-shared-module ]; } + ## ``` + ## Result: + ## ```nix + ## { my-host = ; } + ## ``` + #@ Attrs -> Attrs + create-systems = + { + systems ? { }, + homes ? { }, + }: + let + targets = snowfall-lib.fs.get-directories user-systems-root; + target-systems-metadata = concatMap get-target-systems-metadata targets; + user-nixos-modules = snowfall-lib.module.create-modules { + src = "${user-modules-root}/nixos"; + }; + user-darwin-modules = snowfall-lib.module.create-modules { + src = "${user-modules-root}/darwin"; + }; + nixos-modules = systems.modules.nixos or [ ]; + darwin-modules = systems.modules.darwin or [ ]; + + create-system' = + created-systems: system-metadata: + let + overrides = systems.hosts.${system-metadata.name} or { }; + user-modules = if is-darwin system-metadata.target then user-darwin-modules else user-nixos-modules; + user-modules-list = builtins.attrValues user-modules; + system-modules = if is-darwin system-metadata.target then darwin-modules else nixos-modules; + in + { + ${system-metadata.name} = create-system ( + overrides + // system-metadata + // { + systems = created-systems; + modules = user-modules-list ++ (overrides.modules or [ ]) ++ system-modules; + inherit homes; + } + ); + }; + created-systems = fix ( + created-systems: + foldl ( + systems: system-metadata: systems // (create-system' created-systems system-metadata) + ) { } target-systems-metadata + ); + in + created-systems; + in + { + inherit + get-inferred-system-name + is-darwin + is-linux + is-virtual + get-virtual-system-type + get-target-systems-metadata + get-system-builder + get-system-output + get-resolved-system-target + create-system + create-systems + ; + }; } diff --git a/snowfall-lib/template/default.nix b/snowfall-lib/template/default.nix index 0ad43e3..0020614 100644 --- a/snowfall-lib/template/default.nix +++ b/snowfall-lib/template/default.nix @@ -56,7 +56,8 @@ in unused-overrides = builtins.removeAttrs overrides ( builtins.map (metadata: metadata.name) templates-metadata ); - templates = snowfall-lib.attrs.merge-with-aliases merge-templates templates-metadata alias // unused-overrides; + templates = + snowfall-lib.attrs.merge-with-aliases merge-templates templates-metadata alias // unused-overrides; in templates; };