From 07d478036cefb8e8cd168fd619e05f9cfdb4c361 Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Wed, 28 Dec 2022 23:18:18 -0800 Subject: [PATCH 01/26] feat: add inputs to callPackage --- README.md | 31 ++++++++++++++++++++++++++----- lib/package/default.nix | 1 + lib/shell/default.nix | 2 ++ lib/system/default.nix | 10 +++++++++- 4 files changed, 38 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 80a7e65..66c6a76 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ cd config 2. Create a new flake with one of the templates from [@snowfallorg/templates](https://github.com/snowfallorg/templates). | Name | Description | -|-----------|---------------------------------------------------| +| --------- | ------------------------------------------------- | | `system` | A NixOS system and modules ready to modify. | | `package` | A Nix Flake that exports packages and an overlay. | | `module` | A Nix Flake that exports NixOS modules. | @@ -114,7 +114,7 @@ inputs.snowfall-lib.mkFlake { }; ``` -See [`lib.mkFlake`](#lib.mkflake) for information on how to configure your flake's outputs. +See [`lib.mkFlake`](#libmkflake) for information on how to configure your flake's outputs. ## `lib` @@ -150,7 +150,7 @@ Snowfall Lib has opinions about how a flake's files are laid out. This lets the structure that `lib` expects to find at the root of your flake. ``` -flake-root/ +flake-root/ │ │ Your Nix flake. ├─ flake.nix @@ -161,7 +161,7 @@ flake-root/ │ │ A Nix function called with `inputs`, `snowfall-inputs`, and `lib`. │ │ The function should return an attribute set to merge with `lib`. │ ├─ default.nix -│ │ +│ │ │ │ Any (nestable) directory name. │ └─ **/ │ │ @@ -701,8 +701,11 @@ Result: File system utilities. #### `lib.snowfall.fs.is-file-kind` + #### `lib.snowfall.fs.is-symlink-kind` + #### `lib.snowfall.fs.is-directory-kind` + #### `lib.snowfall.fs.is-unknown-kind` Matchers for file kinds. These are often used with `readDir`. @@ -1066,6 +1069,24 @@ Result: false ``` +#### `lib.snowfall.system.is-virtual` + +Check whether a named system is virtual. + +Type: `String -> Bool` + +Usage: + +```nix +is-linux "x86_64-iso" +``` + +Result: + +```nix +true +``` + #### `lib.snowfall.system.get-virtual-system-type` Get the virtual system type of a system target. @@ -1175,7 +1196,7 @@ Result: ``` #### `lib.snowfall.system.create-systems` - + Create all available systems. Type: `Attrs -> Attrs` diff --git a/lib/package/default.nix b/lib/package/default.nix index 0103103..5031050 100644 --- a/lib/package/default.nix +++ b/lib/package/default.nix @@ -27,6 +27,7 @@ in drv = pkgs.callPackage package { inherit channels; lib = snowfall-lib.internal.system-lib; + inputs = snowfall-lib.flake.without-src user-inputs; }; }; packages-metadata = builtins.map create-package-metadata user-packages; diff --git a/lib/shell/default.nix b/lib/shell/default.nix index bbf37b1..a99dac4 100644 --- a/lib/shell/default.nix +++ b/lib/shell/default.nix @@ -25,7 +25,9 @@ in { name = builtins.unsafeDiscardStringContext (snowfall-lib.path.get-parent-directory shell); drv = channels.nixpkgs.callPackage shell { + inherit channels; lib = snowfall-lib.internal.system-lib; + inputs = snowfall-lib.flake.without-src user-inputs; }; }; shells-metadata = builtins.map create-shell-metadata user-shells; diff --git a/lib/system/default.nix b/lib/system/default.nix index f4a356d..edb2f26 100644 --- a/lib/system/default.nix +++ b/lib/system/default.nix @@ -32,6 +32,13 @@ in # result: false is-linux = hasInfix "linux"; + # Check whether a named system is virtual. + # Type: String -> Bool + # Usage: is-virtual "x86_64-iso" + # result: true + is-virtual = target: + (get-virtual-system-type target) != ""; + # Get the virtual system type of a system target. # Type: String -> String # Usage: get-virtual-system-type "x86_64-iso" @@ -161,8 +168,9 @@ in modules = [ path ] ++ modules; specialArgs = specialArgs // { - inherit system name systems lib; + inherit target system name systems lib; + virtual = (get-virtual-system-type target) != ""; inputs = snowfall-lib.flake.without-src user-inputs; }; }; From 23c08d04f9c78aaaf511f3be2849f2875071ad0e Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Wed, 28 Dec 2022 23:40:05 -0800 Subject: [PATCH 02/26] feat(overlay): only namespace package overlays BREAKING CHANGE This commit modifies the overlay builder's original behavior in a non-backward compatible way. Previously, all overlays would be namespaced with "nixpkgs/". This was often unnecessary or would cause conflicts with package overlays if they shared a name. After this change, all overlays retain their directory name (eg. "my-overlay") and all package overlays are prefixed with "package/" to differentiate them and avoid name conflicts. --- README.md | 12 ++++++------ lib/overlay/default.nix | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 66c6a76..555c27a 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ library instance with `mkLib`. description = "My Flake"; inputs = { - nixpkgs.url = "github:nixos/nixpkgs/nixos-22.05"; + nixpkgs.url = "github:nixos/nixpkgs/nixos-22.11"; snowfall-lib = { url = "github:snowfallorg/lib"; @@ -247,7 +247,7 @@ packages, overlays, and shells specified by the [Flake Structure](#flake-structu description = "My Flake"; inputs = { - nixpkgs.url = "github:nixos/nixpkgs/nixos-22.05"; + nixpkgs.url = "github:nixos/nixpkgs/nixos-22.11"; snowfall-lib = { url = "github:snowfallorg/lib"; @@ -279,7 +279,7 @@ You can apply overlays and modules from your flake's inputs with the following o description = "My Flake"; inputs = { - nixpkgs.url = "github:nixos/nixpkgs/nixos-22.05"; + nixpkgs.url = "github:nixos/nixpkgs/nixos-22.11"; snowfall-lib = { url = "github:snowfallorg/lib"; @@ -338,7 +338,7 @@ on `pkgs` and consumers of your flake can use the generated `.overla description = "My Flake"; inputs = { - nixpkgs.url = "github:nixos/nixpkgs/nixos-22.05"; + nixpkgs.url = "github:nixos/nixpkgs/nixos-22.11"; snowfall-lib = { url = "github:snowfallorg/lib"; @@ -391,7 +391,7 @@ mapping the `default` package or shell to the name of the one you want. description = "My Flake"; inputs = { - nixpkgs.url = "github:nixos/nixpkgs/nixos-22.05"; + nixpkgs.url = "github:nixos/nixpkgs/nixos-22.11"; snowfall-lib = { url = "github:snowfallorg/lib"; @@ -437,7 +437,7 @@ include `darwin` and/or `nixos-generators` as inputs. description = "My Flake"; inputs = { - nixpkgs.url = "github:nixos/nixpkgs/nixos-22.05"; + nixpkgs.url = "github:nixos/nixpkgs/nixos-22.11"; snowfall-lib = { url = "github:snowfallorg/lib"; diff --git a/lib/overlay/default.nix b/lib/overlay/default.nix index d8edf25..bb2a26b 100644 --- a/lib/overlay/default.nix +++ b/lib/overlay/default.nix @@ -118,7 +118,7 @@ in overlays else overlays // { - "nixpkgs/${name}" = overlay; + ${name} = overlay; } ); @@ -151,7 +151,7 @@ in in package-overlays // { - "nixpkgs/${name}" = overlay; + "package/${name}" = overlay; }; package-overlays = From b72380280826383b25feb6ce2e24fb3da2e07cee Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Fri, 6 Jan 2023 09:50:28 -0800 Subject: [PATCH 03/26] fix: export modules as functions instead of paths --- lib/module/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/module/default.nix b/lib/module/default.nix index 5b7d49c..5e9f874 100644 --- a/lib/module/default.nix +++ b/lib/module/default.nix @@ -28,7 +28,7 @@ in modules-metadata = builtins.map create-module-metadata user-modules; merge-modules = modules: metadata: modules // { - ${metadata.name} = metadata.path; + ${metadata.name} = import metadata.path; }; modules-without-default = foldl merge-modules { } modules-metadata; default-module = From d8a08681a9a6fbabededa439ba6bf236f8b9e6e9 Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Fri, 6 Jan 2023 09:50:58 -0800 Subject: [PATCH 04/26] fix: filter packages for outputs --- lib/package/default.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/package/default.nix b/lib/package/default.nix index 5031050..20339a7 100644 --- a/lib/package/default.nix +++ b/lib/package/default.nix @@ -4,6 +4,7 @@ }: let + inherit (core-inputs.flake-utils-plus.lib) filterPackages; inherit (core-inputs.nixpkgs.lib) assertMsg foldl; user-packages-root = snowfall-lib.fs.get-file "packages"; @@ -48,6 +49,6 @@ in overrides-without-default = builtins.removeAttrs overrides [ "default" ]; packages = packages-without-default // default-package // overrides-without-default; in - packages; + filterPackages pkgs.system packages; }; } From cbe1b6e0fb04243b1c3cd25f6fc0ce86c5248024 Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Mon, 9 Jan 2023 05:22:28 -0800 Subject: [PATCH 05/26] feat: aliases and custom snowfall root --- README.md | 75 +++++++++++++++++++++++++++++++++++----- lib/flake/default.nix | 6 ++++ lib/fs/default.nix | 29 ++++++++++------ lib/module/default.nix | 22 ++++-------- lib/overlay/default.nix | 4 +-- lib/package/default.nix | 22 ++++-------- lib/shell/default.nix | 27 ++++++--------- lib/system/default.nix | 4 +-- lib/template/default.nix | 22 ++++-------- 9 files changed, 126 insertions(+), 85 deletions(-) diff --git a/README.md b/README.md index 555c27a..7921c79 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,10 @@ library instance with `mkLib`. # your flake. inherit inputs; src = ./.; + + # You can optionally place your Snowfall-related files in another + # directory. + snowfall.root = ./nix; }; in # We'll cover what to do here next. @@ -100,6 +104,10 @@ let lib = inputs.snowfall-lib.mkLib { inherit inputs; src = ./.; + + # You can optionally place your Snowfall-related files in another + # directory. + snowfall.root = ./nix; }; in lib.mkFlake { } @@ -150,7 +158,10 @@ Snowfall Lib has opinions about how a flake's files are laid out. This lets the structure that `lib` expects to find at the root of your flake. ``` -flake-root/ +snowfall-root/ +│ The Snowfall root defaults to "src", but can be changed by setting "snowfall.root". +│ This is useful if you want to add a flake to a project, but don't want to clutter the +│ root of the repository with directories. │ │ Your Nix flake. ├─ flake.nix @@ -383,7 +394,7 @@ on `pkgs` and consumers of your flake can use the generated `.overla Snowfall Lib will create packages and shells based on your `packages/` and `shells` directories. However, it is common to additionally map one of those packages or shells -to be their respective default. This can be achieved by using `outputs-builder` and +to be their respective default. This can be achieved by setting an `alias` and mapping the `default` package or shell to the name of the one you want. ```nix @@ -411,16 +422,22 @@ mapping the `default` package or shell to the name of the one you want. }; in lib.mkFlake { - # You can also pass through external packages or dynamically create new ones - # in addition to the ones that `lib` will create from your `packages/` directory. - outputs-builder = channels: { + alias = { packages = { default = "my-package"; }; - devShells = { + shells = { default = "my-shell"; }; + + modules = { + default = "my-module"; + }; + + templates = { + default = "my-template"; + }; }; }; } @@ -742,6 +759,24 @@ Result: "/user-source/systems" ``` +#### `lib.snowfall.fs.get-snowfall-file` + +Get a file path relative to the user's snowfall directory. + +Type: `Path -> Path` + +Usage: + +```nix +get-snowfall-file "systems" +``` + +Result: + +```nix +"/user-source/snowfall-dir/systems" +``` + #### `lib.snowfall.fs.internal-get-file` Get a file relative to the Snowfall Lib flake. You probably shouldn't use this! @@ -940,6 +975,28 @@ Result: [ "./something/some-directory/a.nix" ] ``` +### `lib.snowfall.module` + +Utilities for working with NixOS modules. + +#### `lib.snowfall.module.create-modules` + +Create flake output modules. + +Type: `Attrs -> Attrs` + +Usage: + +```nix +create-modules { src = ./my-modules; overrides = { inherit another-module; }; alias = { default = "another-module" }; } +``` + +Result: + +```nix +{ another-module = ...; my-module = ...; default = ...; } +``` + ### `lib.snowfall.attrs` Utilities for working with attribute sets. @@ -1226,7 +1283,7 @@ Type: `Attrs -> Attrs` Usage: ```nix -create-packages { inherit channels; src = ./my-packages; overrides = { inherit another-package; default = "my-package"; }; } +create-packages { inherit channels; src = ./my-packages; overrides = { inherit another-package; }; alias = { default = "another-package"; }; } ``` Result: @@ -1248,7 +1305,7 @@ Type: `Attrs -> Attrs` Usage: ```nix -create-shells { inherit channels; src = ./my-shells; overrides = { inherit another-shell; default = "my-shell"; }; } +create-shells { inherit channels; src = ./my-shells; overrides = { inherit another-shell; }; alias = { default = "another-shell"; }; } ``` Result: @@ -1321,7 +1378,7 @@ Type: `Attrs -> Attrs` Usage: ```nix -create-templates { src = ./my-templates; overrides = { inherit another-template; default = "my-template"; }; } +create-templates { src = ./my-templates; overrides = { inherit another-template; }; alias = { default = "another-template"; }; } ``` Result: diff --git a/lib/flake/default.nix b/lib/flake/default.nix index 318739b..60f2dbe 100644 --- a/lib/flake/default.nix +++ b/lib/flake/default.nix @@ -46,6 +46,7 @@ rec { "channels-config" "templates" "overlay-package-namespace" + "alias" ]; # Transform an attribute set of inputs into an attribute set where @@ -70,13 +71,16 @@ rec { mkFlake = full-flake-options: let custom-flake-options = flake.without-snowfall-options full-flake-options; + alias = full-flake-options.alias or { }; systems = snowfall-lib.system.create-systems (full-flake-options.systems or { }); hosts = snowfall-lib.attrs.merge-shallow [ (full-flake-options.systems.hosts or { }) systems ]; templates = snowfall-lib.template.create-templates { overrides = (full-flake-options.templates or { }); + alias = alias.templates or { }; }; modules = snowfall-lib.module.create-modules { overrides = (full-flake-options.modules or { }); + alias = alias.modules or { }; }; overlays = snowfall-lib.overlay.create-overlays { overlay-package-namespace = full-flake-options.overlay-package-namespace or null; @@ -93,10 +97,12 @@ rec { packages = snowfall-lib.package.create-packages { inherit channels; overrides = (full-flake-options.packages or { }) // (user-outputs.packages or { }); + alias = alias.packages or { }; }; shells = snowfall-lib.shell.create-shells { inherit channels; overrides = (full-flake-options.shells or { }) // (user-outputs.devShells or { }); + alias = alias.shells or { }; }; outputs = { diff --git a/lib/fs/default.nix b/lib/fs/default.nix index 48910ad..3791a81 100644 --- a/lib/fs/default.nix +++ b/lib/fs/default.nix @@ -27,6 +27,12 @@ in # result: "/user-source/systems" get-file = path: "${user-inputs.src}/${path}"; + # Get a file path relative to the user's snowfall directory. + # Type: Path -> Path + # Usage: get-snowfall-file "systems" + # result: "/user-source/snowfall-dir/systems" + get-snowfall-file = path: "${user-inputs.snowfall.root or user-inputs.src}/${path}"; + # Get a file path relative to the this flake. # Type: Path -> Path # Usage: get-file "systems" @@ -41,7 +47,7 @@ in if pathExists path then readDir path else - {}; + { }; # Get directories at a given path. # Type: Path -> [Path] @@ -52,7 +58,7 @@ in entries = safe-read-directory path; filtered-entries = filterAttrs (name: kind: is-directory-kind kind) entries; in - mapAttrsToList (name: kind: "${path}/${name}") filtered-entries; + mapAttrsToList (name: kind: "${path}/${name}") filtered-entries; # Get files at a given path. # Type: Path -> [Path] @@ -63,7 +69,7 @@ in entries = safe-read-directory path; filtered-entries = filterAttrs (name: kind: is-file-kind kind) entries; in - mapAttrsToList (name: kind: "${path}/${name}") filtered-entries; + mapAttrsToList (name: kind: "${path}/${name}") filtered-entries; # Get files at a given path, traversing any directories within. # Type: Path -> [Path] @@ -79,7 +85,8 @@ in map-file = name: kind: let path' = "${path}/${name}"; - in if is-directory-kind kind then + in + if is-directory-kind kind then get-files-recursive path' else path'; @@ -122,8 +129,8 @@ in # result: [ "./something/some-directory/default.nix" ] get-default-nix-files-recursive = path: builtins.filter - (name: builtins.baseNameOf name == "default.nix") - (get-files-recursive path); + (name: builtins.baseNameOf name == "default.nix") + (get-files-recursive path); # Get nix files at a given path not named "default.nix". # Type: Path -> [Path] @@ -144,10 +151,10 @@ in # result: [ "./something/some-directory/a.nix" ] get-non-default-nix-files-recursive = path: builtins.filter - (name: - (snowfall-lib.path.has-file-extension "nix" name) - && (builtins.baseNameOf name != "default.nix") - ) - (get-files-recursive path); + (name: + (snowfall-lib.path.has-file-extension "nix" name) + && (builtins.baseNameOf name != "default.nix") + ) + (get-files-recursive path); }; } diff --git a/lib/module/default.nix b/lib/module/default.nix index 5e9f874..9243d0d 100644 --- a/lib/module/default.nix +++ b/lib/module/default.nix @@ -5,19 +5,20 @@ let inherit (builtins) baseNameOf; - inherit (core-inputs.nixpkgs.lib) assertMsg foldl; + inherit (core-inputs.nixpkgs.lib) assertMsg foldl mapAttrs; - user-modules-root = snowfall-lib.fs.get-file "modules"; + user-modules-root = snowfall-lib.fs.get-snowfall-file "modules"; in { module = { # Create flake output modules. # Type: Attrs -> Attrs - # Usage: create-modules { src = ./my-modules; overrides = { inherit another-module; default = "my-module"; }; } + # Usage: create-modules { src = ./my-modules; overrides = { inherit another-module; }; alias = { default = "another-module" }; } # result: { another-module = ...; my-module = ...; default = ...; } create-modules = { src ? user-modules-root , overrides ? { } + , alias ? { } }: let user-modules = snowfall-lib.fs.get-default-nix-files-recursive src; @@ -30,18 +31,9 @@ in modules // { ${metadata.name} = import metadata.path; }; - modules-without-default = foldl merge-modules { } modules-metadata; - default-module = - if overrides.default or null == null then - { } - else if builtins.isAttrs overrides.default then - { default = overrides.default; } - else if modules-without-default.${overrides.default} or null != null then - { default = modules-without-default.${overrides.default}; } - else - { }; - overrides-without-default = builtins.removeAttrs overrides [ "default" ]; - modules = modules-without-default // default-module // overrides-without-default; + modules-without-aliases = foldl merge-modules { } modules-metadata; + aliased-modules = mapAttrs (name: value: modules-without-aliases.${value}) alias; + modules = modules-without-aliases // aliased-modules // overrides; in modules; }; diff --git a/lib/overlay/default.nix b/lib/overlay/default.nix index bb2a26b..176e9d7 100644 --- a/lib/overlay/default.nix +++ b/lib/overlay/default.nix @@ -6,8 +6,8 @@ let inherit (core-inputs.nixpkgs.lib) assertMsg foldl concatStringsSep; - user-overlays-root = snowfall-lib.fs.get-file "overlays"; - user-packages-root = snowfall-lib.fs.get-file "packages"; + user-overlays-root = snowfall-lib.fs.get-snowfall-file "overlays"; + user-packages-root = snowfall-lib.fs.get-snowfall-file "packages"; in { overlay = { diff --git a/lib/package/default.nix b/lib/package/default.nix index 20339a7..a83fafe 100644 --- a/lib/package/default.nix +++ b/lib/package/default.nix @@ -5,21 +5,22 @@ let inherit (core-inputs.flake-utils-plus.lib) filterPackages; - inherit (core-inputs.nixpkgs.lib) assertMsg foldl; + inherit (core-inputs.nixpkgs.lib) assertMsg foldl mapAttrs; - user-packages-root = snowfall-lib.fs.get-file "packages"; + user-packages-root = snowfall-lib.fs.get-snowfall-file "packages"; in { package = { # Create flake output packages. # Type: Attrs -> Attrs - # Usage: create-packages { inherit channels; src = ./my-packages; overrides = { inherit another-package; default = "my-package"; }; } + # Usage: create-packages { inherit channels; src = ./my-packages; overrides = { inherit another-package; }; alias.default = "another-package"; } # result: { another-package = ...; my-package = ...; default = ...; } create-packages = { channels , src ? user-packages-root , pkgs ? channels.nixpkgs , overrides ? { } + , alias ? { } }: let user-packages = snowfall-lib.fs.get-default-nix-files-recursive src; @@ -36,18 +37,9 @@ in packages // { ${metadata.name} = metadata.drv; }; - packages-without-default = foldl merge-packages { } packages-metadata; - default-package = - if overrides.default or null == null then - { } - else if builtins.isAttrs overrides.default then - { default = overrides.default; } - else if packages-without-default.${overrides.default} or null != null then - { default = packages-without-default.${overrides.default}; } - else - { }; - overrides-without-default = builtins.removeAttrs overrides [ "default" ]; - packages = packages-without-default // default-package // overrides-without-default; + packages-without-aliases = foldl merge-packages { } packages-metadata; + aliased-packages = mapAttrs (name: value: packages-without-aliases.${value}) alias; + packages = packages-without-aliases // aliased-packages // overrides; in filterPackages pkgs.system packages; }; diff --git a/lib/shell/default.nix b/lib/shell/default.nix index a99dac4..47161b6 100644 --- a/lib/shell/default.nix +++ b/lib/shell/default.nix @@ -4,20 +4,22 @@ }: let - inherit (core-inputs.nixpkgs.lib) assertMsg foldl; + inherit (core-inputs.flake-utils-plus.lib) filterPackages; + inherit (core-inputs.nixpkgs.lib) assertMsg foldl mapAttrs; - user-shells-root = snowfall-lib.fs.get-file "shells"; + user-shells-root = snowfall-lib.fs.get-snowfall-file "shells"; in { shell = { # Create flake output packages. # Type: Attrs -> Attrs - # Usage: create-shells { inherit channels; src = ./my-shells; overrides = { inherit another-shell; default = "my-shell"; }; } + # Usage: create-shells { inherit channels; src = ./my-shells; overrides = { inherit another-shell; }; alias = { default = "another-shell"; }; } # result: { another-shell = ...; my-shell = ...; default = ...; } create-shells = { channels , src ? user-shells-root , overrides ? { } + , alias ? { } }: let user-shells = snowfall-lib.fs.get-default-nix-files-recursive src; @@ -35,19 +37,12 @@ in shells // { ${metadata.name} = metadata.drv; }; - shells-without-default = foldl merge-shells { } shells-metadata; - default-shell = - if overrides.default or null == null then - { } - else if builtins.isAttrs overrides.default then - { default = overrides.default; } - else if shells-without-default.${overrides.default} or null != null then - { default = shells-without-default.${overrides.default}; } - else - { }; - overrides-without-default = builtins.removeAttrs overrides [ "default" ]; - shells = shells-without-default // default-shell // overrides-without-default; + shells-without-aliases = foldl merge-shells { } shells-metadata; + aliased-shells = mapAttrs (name: value: shells-without-aliases.${value}) alias; + shells = shells-without-aliases // aliased-shells // overrides; in - shells; + filterPackages + channels.nixpkgs.system + shells; }; } diff --git a/lib/system/default.nix b/lib/system/default.nix index edb2f26..b2a5d1e 100644 --- a/lib/system/default.nix +++ b/lib/system/default.nix @@ -9,8 +9,8 @@ let virtual-systems = import ./virtual-systems.nix; - user-systems-root = snowfall-lib.fs.get-file "systems"; - user-modules-root = snowfall-lib.fs.get-file "modules"; + user-systems-root = snowfall-lib.fs.get-snowfall-file "systems"; + user-modules-root = snowfall-lib.fs.get-snowfall-file "modules"; get-inferred-system-name = path: if snowfall-lib.path.has-file-extension "nix" path then diff --git a/lib/template/default.nix b/lib/template/default.nix index 6f2a47b..3e04626 100644 --- a/lib/template/default.nix +++ b/lib/template/default.nix @@ -5,19 +5,20 @@ let inherit (builtins) baseNameOf; - inherit (core-inputs.nixpkgs.lib) assertMsg foldl; + inherit (core-inputs.nixpkgs.lib) assertMsg foldl mapAttrs; - user-templates-root = snowfall-lib.fs.get-file "templates"; + user-templates-root = snowfall-lib.fs.get-snowfall-file "templates"; in { template = { # Create flake templates. # Type: Attrs -> Attrs - # Usage: create-templates { src = ./my-templates; overrides = { inherit another-template; default = "my-template"; }; } + # Usage: create-templates { src = ./my-templates; overrides = { inherit another-template; }; alias = { default = "another-template"; }; } # result: { another-template = ...; my-template = ...; default = ...; } create-templates = { src ? user-templates-root , overrides ? { } + , alias ? { } }: let user-templates = snowfall-lib.fs.get-directories src; @@ -32,18 +33,9 @@ in inherit (metadata) path; }; }; - templates-without-default = foldl merge-templates { } templates-metadata; - default-template = - if overrides.default or null == null then - { } - else if builtins.isAttrs overrides.default then - { default = overrides.default; } - else if templates-without-default.${overrides.default} or null != null then - { default = templates-without-default.${overrides.default}; } - else - { }; - overrides-without-default = builtins.removeAttrs overrides [ "default" ]; - templates = templates-without-default // default-template // overrides-without-default; + templates-without-aliases = foldl merge-templates { } templates-metadata; + aliased-templates = mapAttrs (name: value: templates-without-aliases.${value}) alias; + templates = templates-without-aliases // aliased-templates // overrides; in templates; }; From 0ba4256dbd02e1c54f7c61b09ae8b8442de32f62 Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Sun, 15 Jan 2023 04:59:16 -0800 Subject: [PATCH 06/26] feat: update flake description --- flake.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index 87dac1b..15dd30f 100644 --- a/flake.nix +++ b/flake.nix @@ -1,5 +1,5 @@ { - description = "A very basic flake"; + description = "Snowfall Lib"; inputs = { nixpkgs.url = "github:nixos/nixpkgs/release-22.05"; @@ -34,7 +34,7 @@ }; flake-options = builtins.removeAttrs flake-and-lib-options [ "inputs" "src" ]; in - lib.mkFlake flake-options; + lib.mkFlake flake-options; in { inherit mkLib mkFlake; From 7def9101defc63dec9982cd6381469764c08db3c Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Sun, 15 Jan 2023 14:52:52 -0800 Subject: [PATCH 07/26] feat: internal namespacing and callPackageWith for better ux --- README.md | 6 +++--- lib/default.nix | 12 +++++------ lib/flake/default.nix | 10 ++++----- lib/internal/default.nix | 11 ++++++---- lib/overlay/default.nix | 46 ++++++++++++++++++---------------------- lib/package/default.nix | 29 ++++++++++++++++--------- lib/shell/default.nix | 16 ++++++++------ 7 files changed, 70 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index 7921c79..6ea7ca0 100644 --- a/README.md +++ b/README.md @@ -377,7 +377,7 @@ on `pkgs` and consumers of your flake can use the generated `.overla # Optionally place all packages under a namespace when used in an overlay. # Instead of accessing packages with `pkgs.`, your internal packages # will be available at `pkgs..`. - overlay-package-namespace = "my-namespace"; + package-namespace = "my-namespace"; # You can also pass through external packages or dynamically create new ones # in addition to the ones that `lib` will create from your `packages/` directory. @@ -1327,7 +1327,7 @@ Type: `Attrs -> Attrs -> [(a -> b -> c)]` Usage: ```nix -create-overlays-builder { src = ./my-overlays; overlay-package-namespace = "my-packages"; extra-overlays = []; } +create-overlays-builder { src = ./my-overlays; package-namespace = "my-packages"; extra-overlays = []; } ``` Result: @@ -1348,7 +1348,7 @@ Usage: create-overlays { src = ./my-overlays; packages-src = ./my-packages; - overlay-package-namespace = "my-namespace"; + package-namespace = "my-namespace"; extra-overlays = { my-example = final: prev: {}; }; diff --git a/lib/default.nix b/lib/default.nix index fd22b10..ee1c6e8 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -8,7 +8,7 @@ user-options: let user-inputs = user-options.inputs // { src = user-options.src; }; - inherit (core-inputs.nixpkgs.lib) assertMsg fix filterAttrs mergeAttrs fold recursiveUpdate; + inherit (core-inputs.nixpkgs.lib) assertMsg fix filterAttrs mergeAttrs fold recursiveUpdate callPackageWith; # Recursively merge a list of attribute sets. # Type: [Attrs] -> Attrs @@ -87,10 +87,10 @@ let attrs = { inherit (user-options) inputs; snowfall-inputs = core-inputs; - lib = merge-shallow [ base-lib user-lib ]; + lib = merge-shallow [ base-lib { internal = user-lib; } ]; }; libs = builtins.map - (path: import path attrs) + (path: callPackageWith attrs path { }) user-lib-modules; in merge-deep libs @@ -104,6 +104,6 @@ let user-inputs-has-self = builtins.elem "self" (builtins.attrNames user-inputs); user-inputs-has-src = builtins.elem "src" (builtins.attrNames user-inputs); in - assert (assertMsg (user-inputs-has-self) "Missing attribute `self` for mkLib."); - assert (assertMsg (user-inputs-has-src) "Missing attribute `src` for mkLib."); - lib +assert (assertMsg (user-inputs-has-self) "Missing attribute `self` for mkLib."); +assert (assertMsg (user-inputs-has-src) "Missing attribute `src` for mkLib."); +lib diff --git a/lib/flake/default.nix b/lib/flake/default.nix index 60f2dbe..77feed2 100644 --- a/lib/flake/default.nix +++ b/lib/flake/default.nix @@ -45,7 +45,7 @@ rec { "hosts" "channels-config" "templates" - "overlay-package-namespace" + "package-namespace" "alias" ]; @@ -65,11 +65,11 @@ rec { builtins.mapAttrs (name: input: input.lib) attrs-with-libs; in libs; - }; mkFlake = full-flake-options: let + package-namespace = full-flake-options.package-namespace or "internal"; custom-flake-options = flake.without-snowfall-options full-flake-options; alias = full-flake-options.alias or { }; systems = snowfall-lib.system.create-systems (full-flake-options.systems or { }); @@ -83,7 +83,7 @@ rec { alias = alias.modules or { }; }; overlays = snowfall-lib.overlay.create-overlays { - overlay-package-namespace = full-flake-options.overlay-package-namespace or null; + inherit package-namespace; extra-overlays = full-flake-options.extra-exported-overlays or { }; }; @@ -95,7 +95,7 @@ rec { or (const { }); user-outputs = user-outputs-builder channels; packages = snowfall-lib.package.create-packages { - inherit channels; + inherit channels package-namespace; overrides = (full-flake-options.packages or { }) // (user-outputs.packages or { }); alias = alias.packages or { }; }; @@ -125,7 +125,7 @@ rec { channelsConfig = full-flake-options.channels-config or { }; channels.nixpkgs.overlaysBuilder = snowfall-lib.overlay.create-overlays-builder { - overlay-package-namespace = full-flake-options.overlay-package-namespace or null; + package-namespace = full-flake-options.package-namespace or null; extra-overlays = full-flake-options.overlays or [ ]; }; diff --git a/lib/internal/default.nix b/lib/internal/default.nix index 687fb62..dfa4a78 100644 --- a/lib/internal/default.nix +++ b/lib/internal/default.nix @@ -4,7 +4,7 @@ }: let - inherit (core-inputs.nixpkgs.lib) assertMsg fix fold filterAttrs; + inherit (core-inputs.nixpkgs.lib) assertMsg fix fold filterAttrs callPackageWith; core-inputs-libs = snowfall-lib.flake.get-libs (snowfall-lib.flake.without-self core-inputs); user-inputs-libs = snowfall-lib.flake.get-libs (snowfall-lib.flake.without-self user-inputs); @@ -27,10 +27,13 @@ let attrs = { inputs = snowfall-lib.flake.without-snowfall-inputs user-inputs; snowfall-inputs = core-inputs; - lib = snowfall-lib.attrs.merge-shallow [ base-lib user-lib ]; + lib = snowfall-lib.attrs.merge-shallow [ + base-lib + { internal = user-lib; } + ]; }; libs = builtins.map - (path: import path attrs) + (path: callPackageWith attrs path { }) user-lib-modules; in snowfall-lib.attrs.merge-deep libs @@ -38,7 +41,7 @@ let system-lib = snowfall-lib.attrs.merge-shallow [ base-lib - user-lib + { internal = user-lib; } ]; in { diff --git a/lib/overlay/default.nix b/lib/overlay/default.nix index 176e9d7..cc8dccd 100644 --- a/lib/overlay/default.nix +++ b/lib/overlay/default.nix @@ -13,11 +13,11 @@ in overlay = { # Create a flake-utils-plus overlays builder. # Type: Attrs -> Attrs -> [(a -> b -> c)] - # Usage: create-overlays { src = ./my-overlays; overlay-package-namespace = "my-packages"; } + # Usage: create-overlays { src = ./my-overlays; package-namespace = "my-packages"; } # result: (channels: [ ... ]) create-overlays-builder = { src ? user-overlays-root - , overlay-package-namespace ? null + , package-namespace ? "internal" , extra-overlays ? [ ] }: channels: let @@ -29,18 +29,14 @@ in pkgs = final; channels = channels; }; - user-packages-without-default = builtins.removeAttrs - (user-packages) [ "default" ]; in - if overlay-package-namespace == null then - user-packages-without-default - else - { - ${overlay-package-namespace} = - (prev.${overlay-package-namespace} or { }) - // user-packages-without-default; - }; - overlays = [ user-packages-overlay ] ++ extra-overlays ++ (builtins.map create-overlay user-overlays); + { + ${package-namespace} = + (prev.${package-namespace} or { }) + // user-packages; + }; + overlays = + [ user-packages-overlay ] ++ extra-overlays ++ (builtins.map create-overlay user-overlays); in overlays; @@ -48,12 +44,12 @@ in # Adapted from flake-utils-plus: # https://github.com/gytis-ivaskevicius/flake-utils-plus/blob/2bf0f91643c2e5ae38c1b26893ac2927ac9bd82a/lib/exportOverlays.nix # Type: Attrs -> Attrs - # Usage: create-overlays { src = ./my-overlays; packages-src = ./my-packages; overlay-package-namespace = "my-namespace"; extra-overlays = {}; } + # Usage: create-overlays { src = ./my-overlays; packages-src = ./my-packages; package-namespace = "my-namespace"; extra-overlays = {}; } # result: { default = final: prev: ...; some-overlay = final: prev: ...; } create-overlays = { src ? user-overlays-root , packages-src ? user-packages-root - , overlay-package-namespace ? null + , package-namespace ? null , extra-overlays ? { } }: let @@ -75,12 +71,12 @@ in channels = channel-systems.${prev.system}; }; in - if overlay-package-namespace == null then + if package-namespace == null then user-packages else { - ${overlay-package-namespace} = - (prev.${overlay-package-namespace} or { }) + ${package-namespace} = + (prev.${package-namespace} or { }) // user-packages; }; @@ -93,13 +89,13 @@ in user-overlay = import file (user-inputs // { inherit channels; }); packages = user-packages-overlay final prev; prev-with-packages = - if overlay-package-namespace == null then + if package-namespace == null then prev // packages else prev // { - ${overlay-package-namespace} = - (prev.${overlay-package-namespace} or { }) - // packages.${overlay-package-namespace}; + ${package-namespace} = + (prev.${package-namespace} or { }) + // packages.${package-namespace}; }; user-overlay-packages = user-overlay @@ -140,12 +136,12 @@ in channels = channel-systems.${prev.system}; }; in - if overlay-package-namespace == null then + if package-namespace == null then { ${name} = packages.${name}; } else { - ${overlay-package-namespace} = - (prev.${overlay-package-namespace} or { }) + ${package-namespace} = + (prev.${package-namespace} or { }) // { ${name} = packages.${name}; }; }; in diff --git a/lib/package/default.nix b/lib/package/default.nix index a83fafe..3968ecd 100644 --- a/lib/package/default.nix +++ b/lib/package/default.nix @@ -4,13 +4,13 @@ }: let - inherit (core-inputs.flake-utils-plus.lib) filterPackages; - inherit (core-inputs.nixpkgs.lib) assertMsg foldl mapAttrs; + inherit (core-inputs.flake-utils-plus.lib) filterPackages allSystems; + inherit (core-inputs.nixpkgs.lib) assertMsg foldl mapAttrs filterAttrs callPackageWith; user-packages-root = snowfall-lib.fs.get-snowfall-file "packages"; in { - package = { + package = rec { # Create flake output packages. # Type: Attrs -> Attrs # Usage: create-packages { inherit channels; src = ./my-packages; overrides = { inherit another-package; }; alias.default = "another-package"; } @@ -21,17 +21,26 @@ in , pkgs ? channels.nixpkgs , overrides ? { } , alias ? { } + , package-namespace ? "internal" }: let user-packages = snowfall-lib.fs.get-default-nix-files-recursive src; - create-package-metadata = package: { - name = builtins.unsafeDiscardStringContext (snowfall-lib.path.get-parent-directory package); - drv = pkgs.callPackage package { - inherit channels; - lib = snowfall-lib.internal.system-lib; - inputs = snowfall-lib.flake.without-src user-inputs; + create-package-metadata = package: + let + namespaced-packages = { + ${package-namespace} = packages-without-aliases; + }; + extra-inputs = pkgs // namespaced-packages // { + inherit channels; + lib = snowfall-lib.internal.system-lib; + pkgs = pkgs // namespaced-packages; + inputs = snowfall-lib.flake.without-snowfall-inputs user-inputs; + }; + in + { + name = builtins.unsafeDiscardStringContext (snowfall-lib.path.get-parent-directory package); + drv = callPackageWith extra-inputs package { }; }; - }; packages-metadata = builtins.map create-package-metadata user-packages; merge-packages = packages: metadata: packages // { diff --git a/lib/shell/default.nix b/lib/shell/default.nix index 47161b6..aecd0e2 100644 --- a/lib/shell/default.nix +++ b/lib/shell/default.nix @@ -5,7 +5,7 @@ let inherit (core-inputs.flake-utils-plus.lib) filterPackages; - inherit (core-inputs.nixpkgs.lib) assertMsg foldl mapAttrs; + inherit (core-inputs.nixpkgs.lib) assertMsg foldl mapAttrs callPackageWith; user-shells-root = snowfall-lib.fs.get-snowfall-file "shells"; in @@ -18,19 +18,23 @@ in create-shells = { channels , src ? user-shells-root + , pkgs ? channels.nixpkgs , overrides ? { } , alias ? { } }: let user-shells = snowfall-lib.fs.get-default-nix-files-recursive src; create-shell-metadata = shell: - { - name = builtins.unsafeDiscardStringContext (snowfall-lib.path.get-parent-directory shell); - drv = channels.nixpkgs.callPackage shell { + let + extra-inputs = pkgs // { inherit channels; lib = snowfall-lib.internal.system-lib; inputs = snowfall-lib.flake.without-src user-inputs; }; + in + { + name = builtins.unsafeDiscardStringContext (snowfall-lib.path.get-parent-directory shell); + drv = callPackageWith extra-inputs shell { }; }; shells-metadata = builtins.map create-shell-metadata user-shells; merge-shells = shells: metadata: @@ -41,8 +45,6 @@ in aliased-shells = mapAttrs (name: value: shells-without-aliases.${value}) alias; shells = shells-without-aliases // aliased-shells // overrides; in - filterPackages - channels.nixpkgs.system - shells; + filterPackages pkgs.system shells; }; } From af06876391103ccfb3553b73d64797e765b88105 Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Mon, 13 Feb 2023 00:12:43 -0800 Subject: [PATCH 08/26] chore: add license --- LICENSE | 193 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..191bee1 --- /dev/null +++ b/LICENSE @@ -0,0 +1,193 @@ +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS +AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + + "Legal Entity" shall mean the +union of the acting entity and all other entities that control, are controlled +by, or are under common control with that entity. For the purposes of this +definition, "control" means (i) the power, direct or indirect, to cause the +direction or management of such entity, whether by contract or otherwise, or (ii) +ownership of fifty percent (50%) or more of the outstanding shares, or (iii) +beneficial ownership of such entity. + + "You" (or "Your") shall mean +an individual or Legal Entity exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, +including but not limited to software source code, documentation source, and +configuration files. + + "Object" form shall mean any form resulting +from mechanical transformation or translation of a Source form, including but not +limited to compiled object code, generated documentation, and conversions to +other media types. + + "Work" shall mean the work of authorship, +whether in Source or Object form, made available under the License, as indicated +by a copyright notice that is included in or attached to the work (an example is +provided in the Appendix below). + + "Derivative Works" shall mean any +work, whether in Source or Object form, that is based on (or derived from) the +Work and for which the editorial revisions, annotations, elaborations, or other +modifications represent, as a whole, an original work of authorship. For the +purposes of this License, Derivative Works shall not include works that remain +separable from, or merely link (or bind by name) to the interfaces of, the Work +and Derivative Works thereof. + + "Contribution" shall mean any work +of authorship, including the original version of the Work and any modifications +or additions to that Work or Derivative Works thereof, that is intentionally +submitted to Licensor for inclusion in the Work by the copyright owner or by an +individual or Legal Entity authorized to submit on behalf of the copyright owner. +For the purposes of this definition, "submitted" means any form of electronic, +verbal, or written communication sent to the Licensor or its representatives, +including but not limited to communication on electronic mailing lists, source +code control systems, and issue tracking systems that are managed by, or on +behalf of, the Licensor for the purpose of discussing and improving the Work, but +excluding communication that is conspicuously marked or otherwise designated in +writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of +whom a Contribution has been received by Licensor and subsequently incorporated +within the Work. + + 2. Grant of Copyright License. Subject to the terms and +conditions of this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license +to reproduce, prepare Derivative Works of, publicly display, publicly perform, +sublicense, and distribute the Work and such Derivative Works in Source or Object +form. + + 3. Grant of Patent License. Subject to the terms and conditions of this +License, each Contributor hereby grants to You a perpetual, worldwide, +non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this +section) patent license to make, have made, use, offer to sell, sell, import, and +otherwise transfer the Work, where such license applies only to those patent +claims licensable by such Contributor that are necessarily infringed by their +Contribution(s) alone or by combination of their Contribution(s) with the Work to +which such Contribution(s) was submitted. If You institute patent litigation +against any entity (including a cross-claim or counterclaim in a lawsuit) +alleging that the Work or a Contribution incorporated within the Work constitutes +direct or contributory patent infringement, then any patent licenses granted to +You under this License for that Work shall terminate as of the date such +litigation is filed. + + 4. Redistribution. You may reproduce and distribute +copies of the Work or Derivative Works thereof in any medium, with or without +modifications, and in Source or Object form, provided that You meet the following +conditions: + + (a) You must give any other recipients of the Work or +Derivative Works a copy of this License; and + + (b) You must cause any +modified files to carry prominent notices stating that You changed the files; +and + + (c) You must retain, in the Source form of any Derivative Works that +You distribute, all copyright, patent, trademark, and attribution notices from +the Source form of the Work, excluding those notices that do not pertain to any +part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text +file as part of its distribution, then any Derivative Works that You distribute +must include a readable copy of the attribution notices contained within such +NOTICE file, excluding those notices that do not pertain to any part of the +Derivative Works, in at least one of the following places: within a NOTICE text +file distributed as part of the Derivative Works; within the Source form or +documentation, if provided along with the Derivative Works; or, within a display +generated by the Derivative Works, if and wherever such third-party notices +normally appear. The contents of the NOTICE file are for informational purposes +only and do not modify the License. You may add Your own attribution notices +within Derivative Works that You distribute, alongside or as an addendum to the +NOTICE text from the Work, provided that such additional attribution notices +cannot be construed as modifying the License. + + You may add Your own +copyright statement to Your modifications and may provide additional or different +license terms and conditions for use, reproduction, or distribution of Your +modifications, or for any such Derivative Works as a whole, provided Your use, +reproduction, and distribution of the Work otherwise complies with the conditions +stated in this License. + + 5. Submission of Contributions. Unless You explicitly +state otherwise, any Contribution intentionally submitted for inclusion in the +Work by You to the Licensor shall be under the terms and conditions of this +License, without any additional terms or conditions. Notwithstanding the above, +nothing herein shall supersede or modify the terms of any separate license +agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, +trademarks, service marks, or product names of the Licensor, except as required +for reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless +required by applicable law or agreed to in writing, Licensor provides the Work +(and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, +without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, +MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible +for determining the appropriateness of using or redistributing the Work and +assume any risks associated with Your exercise of permissions under this +License. + + 8. Limitation of Liability. In no event and under no legal theory, +whether in tort (including negligence), contract, or otherwise, unless required +by applicable law (such as deliberate and grossly negligent acts) or agreed to in +writing, shall any Contributor be liable to You for damages, including any +direct, indirect, special, incidental, or consequential damages of any character +arising as a result of this License or out of the use or inability to use the +Work (including but not limited to damages for loss of goodwill, work stoppage, +computer failure or malfunction, or any and all other commercial damages or +losses), even if such Contributor has been advised of the possibility of such +damages. + + 9. Accepting Warranty or Additional Liability. While redistributing +the Work or Derivative Works thereof, You may choose to offer, and charge a fee +for, acceptance of support, warranty, indemnity, or other liability obligations +and/or rights consistent with this License. However, in accepting such +obligations, You may act only on Your own behalf and on Your sole responsibility, +not on behalf of any other Contributor, and only if You agree to indemnify, +defend, and hold each Contributor harmless for any liability incurred by, or +claims asserted against, such Contributor by reason of your accepting any such +warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, +attach the following boilerplate notice, with the fields enclosed by brackets +"[]" replaced with your own identifying information. (Don't include the +brackets!) The text should be enclosed in the appropriate comment syntax for the +file format. We also recommend that a file or class name and description of +purpose be included on the same "printed page" as the copyright notice for easier +identification within third-party archives. + +Copyright 2023 Jake Hamilton + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and +limitations under the License. From b428b981b96114612414313fa62f3ed14cc8f168 Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Tue, 21 Feb 2023 17:41:34 -0800 Subject: [PATCH 09/26] feat: proxy nixos modules, remove deprecated overlay attribute --- flake.lock | 8 ++++---- flake.nix | 2 +- lib/flake/default.nix | 1 - lib/module/default.nix | 43 +++++++++++++++++++++++++++++++++++++++--- 4 files changed, 45 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index d8f9b49..369ec0e 100644 --- a/flake.lock +++ b/flake.lock @@ -51,16 +51,16 @@ }, "nixpkgs": { "locked": { - "lastModified": 1665216225, - "narHash": "sha256-SUuvJXGEXhmyaGJlDlptbc9I2Wai9tUx83QYIqvipfE=", + "lastModified": 1677028070, + "narHash": "sha256-sUKqd8HYBrtPxCRXFWvsnQDnwqnw1uIDwu4khcZuL2k=", "owner": "nixos", "repo": "nixpkgs", - "rev": "1a9935bf90e0f4225756f99e772f06d5fea9edb6", + "rev": "d3a15cd8dc917f4364ba0b332a1c389dc3177603", "type": "github" }, "original": { "owner": "nixos", - "ref": "release-22.05", + "ref": "release-22.11", "repo": "nixpkgs", "type": "github" } diff --git a/flake.nix b/flake.nix index 15dd30f..49ba302 100644 --- a/flake.nix +++ b/flake.nix @@ -2,7 +2,7 @@ description = "Snowfall Lib"; inputs = { - nixpkgs.url = "github:nixos/nixpkgs/release-22.05"; + nixpkgs.url = "github:nixos/nixpkgs/release-22.11"; flake-utils-plus.url = "github:gytis-ivaskevicius/flake-utils-plus"; flake-compat = { diff --git a/lib/flake/default.nix b/lib/flake/default.nix index 77feed2..e4af712 100644 --- a/lib/flake/default.nix +++ b/lib/flake/default.nix @@ -138,7 +138,6 @@ rec { flake-outputs = flake-utils-plus-outputs // { inherit overlays; - overlay = overlays.default; }; in flake-outputs; diff --git a/lib/module/default.nix b/lib/module/default.nix index 9243d0d..cb10acf 100644 --- a/lib/module/default.nix +++ b/lib/module/default.nix @@ -5,7 +5,7 @@ let inherit (builtins) baseNameOf; - inherit (core-inputs.nixpkgs.lib) assertMsg foldl mapAttrs; + inherit (core-inputs.nixpkgs.lib) assertMsg foldl mapAttrs hasPrefix; user-modules-root = snowfall-lib.fs.get-snowfall-file "modules"; in @@ -23,13 +23,50 @@ in let user-modules = snowfall-lib.fs.get-default-nix-files-recursive src; create-module-metadata = module: { - name = builtins.unsafeDiscardStringContext (snowfall-lib.path.get-parent-directory module); + name = + let + path-name = builtins.replaceStrings [ src "/default.nix" ] [ "" "" ] (builtins.unsafeDiscardStringContext module); + in + if hasPrefix "/" path-name then + builtins.substring 1 ((builtins.stringLength path-name) - 1) path-name + else + path-name; path = module; }; modules-metadata = builtins.map create-module-metadata user-modules; merge-modules = modules: metadata: modules // { - ${metadata.name} = import metadata.path; + ${metadata.name} = args: + let + system = args.system or args.pkgs.system; + target = args.target or system; + + format = + let + virtual-system-type = snowfall-lib.system.get-virtual-system-type target; + in + if virtual-system-type != "" then + virtual-system-type + else if snowfall-lib.system.is-darwin target then + "darwin" + else + "linux"; + + # Replicates the specialArgs from Snowfall Lib's system builder. + modified-args = args // { + inherit system target format; + virtual = args.virtual or (snowfall-lib.system.get-virtual-system-type target != ""); + systems = args.systems or { }; + + + lib = snowfall-lib.internal.system-lib; + pkgs = user-inputs.self.pkgs.${system}.nixpkgs; + + inputs = snowfall-lib.flake.without-src user-inputs; + }; + user-module = import metadata.path modified-args; + in + user-module // { _file = metadata.path; }; }; modules-without-aliases = foldl merge-modules { } modules-metadata; aliased-modules = mapAttrs (name: value: modules-without-aliases.${value}) alias; From 17ef1c563d6dfd2e55dfbd1fbbfe46abc088ef0a Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Mon, 10 Apr 2023 15:59:57 -0700 Subject: [PATCH 10/26] wip: faulty first attempt at home-manager integration --- lib/flake/default.nix | 29 ++++- lib/home/default.nix | 214 +++++++++++++++++++++++++++++++ lib/home/nix-registry-module.nix | 11 ++ lib/module/default.nix | 6 +- lib/system/default.nix | 74 ++++++++--- modules/darwin/home/default.nix | 33 +++++ modules/home/os/default.nix | 28 ++++ modules/nixos/home/default.nix | 33 +++++ 8 files changed, 400 insertions(+), 28 deletions(-) create mode 100644 lib/home/default.nix create mode 100644 lib/home/nix-registry-module.nix create mode 100644 modules/darwin/home/default.nix create mode 100644 modules/home/os/default.nix create mode 100644 modules/nixos/home/default.nix diff --git a/lib/flake/default.nix b/lib/flake/default.nix index e4af712..979b3e2 100644 --- a/lib/flake/default.nix +++ b/lib/flake/default.nix @@ -72,15 +72,30 @@ rec { package-namespace = full-flake-options.package-namespace or "internal"; custom-flake-options = flake.without-snowfall-options full-flake-options; alias = full-flake-options.alias or { }; - systems = snowfall-lib.system.create-systems (full-flake-options.systems or { }); - hosts = snowfall-lib.attrs.merge-shallow [ (full-flake-options.systems.hosts or { }) systems ]; + homes = snowfall-lib.home.create-homes (full-flake-options.homes or { }); + systems = snowfall-lib.system.create-systems { + systems = (full-flake-options.systems or { }); + homes = (full-flake-options.homes or { }); + }; + hosts = snowfall-lib.attrs.merge-shallow [ (full-flake-options.systems.hosts or { }) systems homes ]; templates = snowfall-lib.template.create-templates { overrides = (full-flake-options.templates or { }); alias = alias.templates or { }; }; - modules = snowfall-lib.module.create-modules { - overrides = (full-flake-options.modules or { }); - alias = alias.modules or { }; + nixos-modules = snowfall-lib.module.create-modules { + src = snowfall-lib.fs.get-snowfall-file "modules/nixos"; + overrides = (full-flake-options.modules.nixos or { }); + alias = alias.modules.nixos or { }; + }; + darwin-modules = snowfall-lib.module.create-modules { + src = snowfall-lib.fs.get-snowfall-file "modules/darwin"; + overrides = (full-flake-options.modules.darwin or { }); + alias = alias.modules.darwin or { }; + }; + home-modules = snowfall-lib.module.create-modules { + src = snowfall-lib.fs.get-snowfall-file "modules/home"; + overrides = (full-flake-options.modules.home or { }); + alias = alias.modules.home or { }; }; overlays = snowfall-lib.overlay.create-overlays { inherit package-namespace; @@ -120,7 +135,9 @@ rec { lib = snowfall-lib.internal.user-lib; inputs = snowfall-lib.flake.without-src user-inputs; - nixosModules = modules; + nixosModules = nixos-modules; + darwinModules = darwin-modules; + homeModules = home-modules; channelsConfig = full-flake-options.channels-config or { }; diff --git a/lib/home/default.nix b/lib/home/default.nix new file mode 100644 index 0000000..a956e39 --- /dev/null +++ b/lib/home/default.nix @@ -0,0 +1,214 @@ +{ core-inputs, user-inputs, snowfall-lib }: + +let + inherit (core-inputs.nixpkgs.lib) assertMsg foldl head tail concatMap optionalAttrs mkIf filterAttrs mapAttrs' mkMerge mapAttrsToList; + + user-homes-root = snowfall-lib.fs.get-snowfall-file "homes"; + user-modules-root = snowfall-lib.fs.get-snowfall-file "modules"; +in +{ + home = rec { + # Modules in home-manager expect `hm` to be available directly on `lib` itself. + home-lib = snowfall-lib.internal.system-lib.extend (final: prev: + # @NOTE(jakehamilton): 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; + }); + + split-user-and-host = target: + let + raw-name-parts = builtins.split "@" target; + name-parts = builtins.filter builtins.isString raw-name-parts; + + 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-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; + + # @NOTE(jakehamilton): home-manager has trouble with `pkgs` recursion if it isn't passed in here. + pkgs = user-inputs.self.pkgs.${system}.${channelName} // { lib = home-lib; }; + 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 != "") "Snowfall Lib homes must be named with the format: user@system"; + { + inherit channelName system; + + output = "homeConfigurations"; + + modules = [ path ] ++ modules; + + specialArgs = { + inherit name; + inherit (user-metadata) user host; + + format = "home"; + + inputs = snowfall-lib.flake.without-src user-inputs; + + # @NOTE(jakehamilton): 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; + })) + ]; + + extraSpecialArgs = specialArgs // args.specialArgs; + }); + }; + + get-target-homes-metadata = target: + let + homes = snowfall-lib.fs.get-directories target; + existing-homes = builtins.filter (home: builtins.pathExists "${home}/default.nix") homes; + create-home-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. + system = builtins.unsafeDiscardStringContext (builtins.baseNameOf target); + }; + home-configurations = builtins.map create-home-metadata existing-homes; + in + home-configurations; + + # Create all available homes. + # Type: Attrs -> Attrs + # Usage: create-homes { users."my-user@my-system".specialArgs.x = true; modules = [ my-shared-module ]; } + # result: { "my-user@my-system" = ; } + 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 = builtins.attrValues 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-home-system-modules = users: + let + created-users = create-homes users; + extra-special-args-module = + args@{ config + , pkgs + , system ? pkgs.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; + + lib = home-lib; + # pkgs = user-inputs.self.pkgs.${system}.nixpkgs; + + 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 = tail created-user.modules; + user-name = created-user.specialArgs.user; + in + args@{ config + , pkgs + , host ? "" + , ... + }: + let + host-matches = created-user.specialArgs.host == host; + + wrapped-user-module = home-args: + let + modified-args = args // { + inherit (created-user.specialArgs) user; + }; + user-module-result = (import user-module (home-args // modified-args)) // { + _file = user-module; + }; + in + user-module-result; + in + { + _file = "virtual:snowfallorg/home/user/${name}"; + + imports = + if snowfall-lib.system.is-darwin created-user.system then + [ ../../modules/darwin/home/default.nix ] + else + [ ../../modules/nixos/home/default.nix ]; + + config = mkIf host-matches { + home-manager = { + users.${user-name} = wrapped-user-module args; + sharedModules = other-modules; + }; + }; + } + ) + (builtins.attrNames created-users); + in + [ extra-special-args-module ] ++ system-modules; + }; +} diff --git a/lib/home/nix-registry-module.nix b/lib/home/nix-registry-module.nix new file mode 100644 index 0000000..c15f9e2 --- /dev/null +++ b/lib/home/nix-registry-module.nix @@ -0,0 +1,11 @@ +# This code is adapted from flake-utils-plus: +# https://github.com/gytis-ivaskevicius/flake-utils-plus/blob/2bf0f91643c2e5ae38c1b26893ac2927ac9bd82a/lib/options.nix +{ lib, config, user-inputs, core-inputs, ... }: + +{ + disabledModules = [ + # The module from flake-utils-plus only works on NixOS and nix-darwin. For home-manager + # to build, this module needs to be disabled. + "${core-inputs.flake-utils-plus}/lib/options.nix" + ]; +} diff --git a/lib/module/default.nix b/lib/module/default.nix index cb10acf..7b647cb 100644 --- a/lib/module/default.nix +++ b/lib/module/default.nix @@ -16,7 +16,7 @@ in # Usage: create-modules { src = ./my-modules; overrides = { inherit another-module; }; alias = { default = "another-module" }; } # result: { another-module = ...; my-module = ...; default = ...; } create-modules = - { src ? user-modules-root + { src ? "${user-modules-root}/nixos" , overrides ? { } , alias ? { } }: @@ -36,7 +36,9 @@ in modules-metadata = builtins.map create-module-metadata user-modules; merge-modules = modules: metadata: modules // { - ${metadata.name} = args: + # @NOTE(jakehamilton): home-manager *requires* modules to specify named arguments or it will not + # pass values in. For this reason we must specify things like `pkgs` as a named attribute. + ${metadata.name} = args@{ pkgs, ... }: let system = args.system or args.pkgs.system; target = args.target or system; diff --git a/lib/system/default.nix b/lib/system/default.nix index b2a5d1e..9df24f9 100644 --- a/lib/system/default.nix +++ b/lib/system/default.nix @@ -5,21 +5,25 @@ let inherit (builtins) dirOf baseNameOf; - inherit (core-inputs.nixpkgs.lib) assertMsg fix hasInfix concatMap foldl; + inherit (core-inputs.nixpkgs.lib) assertMsg fix hasInfix concatMap foldl optionals singleton; virtual-systems = import ./virtual-systems.nix; user-systems-root = snowfall-lib.fs.get-snowfall-file "systems"; user-modules-root = snowfall-lib.fs.get-snowfall-file "modules"; - - 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; in { system = rec { + # Get the name of a system based on its file path. + # Type: Path -> String + # Usage: get-inferred-system-name "/systems/my-system/default.nix" + # result: "my-system" + 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. # Type: String -> Bool # Usage: is-darwin "x86_64-linux" @@ -85,7 +89,7 @@ in 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."); + 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; @@ -94,12 +98,13 @@ in }; }); 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" ]) // { - specialArgs = args.specialArgs // { - format = "darwin"; - }; - }); + 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" ]) // { + specialArgs = args.specialArgs // { + format = "darwin"; + }; + }); linux-system-builder = args: core-inputs.nixpkgs.lib.nixosSystem (args // { @@ -158,17 +163,26 @@ in , 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; + modules = [ path ] ++ modules ++ (optionals (user-inputs ? home-manager) home-manager-modules); specialArgs = specialArgs // { - inherit target system name systems lib; + inherit target system systems lib; + host = name; virtual = (get-virtual-system-type target) != ""; inputs = snowfall-lib.flake.without-src user-inputs; @@ -177,21 +191,41 @@ in # Create all available systems. # Type: Attrs -> Attrs - # Usage: create-systems { hosts.my-host.specialArgs.x = true; modules = [ my-shared-module ]; } + # Usage: create-systems { hosts.my-host.specialArgs.x = true; modules.nixos = [ my-shared-module ]; } # result: { my-host = ; } - create-systems = systems: + create-systems = { systems ? { }, homes ? { } }: let targets = snowfall-lib.fs.get-directories user-systems-root; target-systems-metadata = concatMap get-target-systems-metadata targets; - user-modules = snowfall-lib.fs.get-default-nix-files-recursive user-modules-root; + 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 ++ (overrides.modules or [ ]) ++ (systems.modules or [ ]); + modules = user-modules-list ++ (overrides.modules or [ ]) ++ system-modules; + inherit homes; }); }; created-systems = fix (created-systems: diff --git a/modules/darwin/home/default.nix b/modules/darwin/home/default.nix new file mode 100644 index 0000000..e9cd0a8 --- /dev/null +++ b/modules/darwin/home/default.nix @@ -0,0 +1,33 @@ +{ lib, config, ... }: + +let + inherit (lib) types mkOption mkMerge mapAttrsToList; + + home-submodule = { name, ... }: { + options = { + proxy = mkOption { + type = types.attrs; + default = { }; + description = "Configuration to be proxied to the home-manager configuration for `home-manager.users.`."; + }; + }; + }; + + cfg = config.snowfallorg; +in +{ + options.snowfallorg = { + home = mkOption { + type = types.attrsOf (types.submodule home-submodule); + default = { }; + description = "Options for configuring home environments."; + }; + }; + + config = mkMerge + (mapAttrsToList + (name: value: { + home-manager.users.${name} = value.proxy; + }) + (cfg.home)); +} diff --git a/modules/home/os/default.nix b/modules/home/os/default.nix new file mode 100644 index 0000000..2da065f --- /dev/null +++ b/modules/home/os/default.nix @@ -0,0 +1,28 @@ +{ lib, osConfig ? { }, ... }: + +let + inherit (lib) types mkOption; + + home-submodule = { name, ... }: { + options = { + proxy = mkOption { + type = types.attrs; + default = { }; + description = "Configuration to be proxied to the home-manager configuration for `home-manager.users.`."; + }; + }; + }; +in +{ + options.snowfallorg = { + home = mkOption { + type = types.attrsOf (types.submodule home-submodule); + default = { }; + description = "Options for configuring home environments."; + }; + }; + + config = { + # snowfallorg.home = osConfig.snowfallorg.home or { }; + }; +} diff --git a/modules/nixos/home/default.nix b/modules/nixos/home/default.nix new file mode 100644 index 0000000..e9cd0a8 --- /dev/null +++ b/modules/nixos/home/default.nix @@ -0,0 +1,33 @@ +{ lib, config, ... }: + +let + inherit (lib) types mkOption mkMerge mapAttrsToList; + + home-submodule = { name, ... }: { + options = { + proxy = mkOption { + type = types.attrs; + default = { }; + description = "Configuration to be proxied to the home-manager configuration for `home-manager.users.`."; + }; + }; + }; + + cfg = config.snowfallorg; +in +{ + options.snowfallorg = { + home = mkOption { + type = types.attrsOf (types.submodule home-submodule); + default = { }; + description = "Options for configuring home environments."; + }; + }; + + config = mkMerge + (mapAttrsToList + (name: value: { + home-manager.users.${name} = value.proxy; + }) + (cfg.home)); +} From 4d6fdba39012848c267ce58aa59a315fb2623dbc Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Mon, 10 Apr 2023 16:50:47 -0700 Subject: [PATCH 11/26] wip: better home-manager integration --- flake.nix | 4 +++ lib/home/default.nix | 48 ++++++++++++++++++++------------- modules/darwin/home/default.nix | 33 ----------------------- modules/home/os/default.nix | 28 ------------------- modules/home/user/default.nix | 23 ++++++++++++++++ modules/nixos/home/default.nix | 33 ----------------------- 6 files changed, 57 insertions(+), 112 deletions(-) delete mode 100644 modules/darwin/home/default.nix delete mode 100644 modules/home/os/default.nix create mode 100644 modules/home/user/default.nix delete mode 100644 modules/nixos/home/default.nix diff --git a/flake.nix b/flake.nix index 49ba302..a023d2a 100644 --- a/flake.nix +++ b/flake.nix @@ -38,5 +38,9 @@ in { inherit mkLib mkFlake; + + homeModules = { + user = ./user/default.nix; + }; }; } diff --git a/lib/home/default.nix b/lib/home/default.nix index a956e39..d4e0ad3 100644 --- a/lib/home/default.nix +++ b/lib/home/default.nix @@ -1,7 +1,7 @@ { core-inputs, user-inputs, snowfall-lib }: let - inherit (core-inputs.nixpkgs.lib) assertMsg foldl head tail concatMap optionalAttrs mkIf filterAttrs mapAttrs' mkMerge mapAttrsToList; + inherit (core-inputs.nixpkgs.lib) assertMsg foldl head tail concatMap optionalAttrs mkIf filterAttrs mapAttrs' mkMerge mapAttrsToList optionals mkDefault; user-homes-root = snowfall-lib.fs.get-snowfall-file "homes"; user-modules-root = snowfall-lib.fs.get-snowfall-file "modules"; @@ -157,7 +157,6 @@ in inherit system target format virtual systems host; lib = home-lib; - # pkgs = user-inputs.self.pkgs.${system}.nixpkgs; inputs = snowfall-lib.flake.without-src user-inputs; }; @@ -179,30 +178,43 @@ in let host-matches = created-user.specialArgs.host == host; - wrapped-user-module = home-args: + # @NOTE(jakehamilton): We *must* specify named attributes here in order + # for home-manager to provide them. + wrapped-user-module = home-args@{ pkgs, lib, ... }: let - modified-args = args // { - inherit (created-user.specialArgs) user; - }; - user-module-result = (import user-module (home-args // modified-args)) // { - _file = user-module; - }; + user-module-result = import user-module home-args; + user-imports = + if user-module-result ? imports then + user-module-result.imports + else + [ ]; + user-config = + if user-module-result ? config then + user-module-result.config + else + builtins.removeAttrs user-module-result [ "imports" "options" "_file" ]; in - user-module-result; + { + _file = builtins.toString user-module; + imports = user-imports; + + config = mkMerge [ + user-config + ({ + snowfallorg.user.name = mkDefault created-user.specialArgs.user; + }) + ]; + }; in { _file = "virtual:snowfallorg/home/user/${name}"; - imports = - if snowfall-lib.system.is-darwin created-user.system then - [ ../../modules/darwin/home/default.nix ] - else - [ ../../modules/nixos/home/default.nix ]; - config = mkIf host-matches { home-manager = { - users.${user-name} = wrapped-user-module args; - sharedModules = other-modules; + users.${user-name} = wrapped-user-module; + sharedModules = other-modules ++ [ + ../../modules/home/user/default.nix + ]; }; }; } diff --git a/modules/darwin/home/default.nix b/modules/darwin/home/default.nix deleted file mode 100644 index e9cd0a8..0000000 --- a/modules/darwin/home/default.nix +++ /dev/null @@ -1,33 +0,0 @@ -{ lib, config, ... }: - -let - inherit (lib) types mkOption mkMerge mapAttrsToList; - - home-submodule = { name, ... }: { - options = { - proxy = mkOption { - type = types.attrs; - default = { }; - description = "Configuration to be proxied to the home-manager configuration for `home-manager.users.`."; - }; - }; - }; - - cfg = config.snowfallorg; -in -{ - options.snowfallorg = { - home = mkOption { - type = types.attrsOf (types.submodule home-submodule); - default = { }; - description = "Options for configuring home environments."; - }; - }; - - config = mkMerge - (mapAttrsToList - (name: value: { - home-manager.users.${name} = value.proxy; - }) - (cfg.home)); -} diff --git a/modules/home/os/default.nix b/modules/home/os/default.nix deleted file mode 100644 index 2da065f..0000000 --- a/modules/home/os/default.nix +++ /dev/null @@ -1,28 +0,0 @@ -{ lib, osConfig ? { }, ... }: - -let - inherit (lib) types mkOption; - - home-submodule = { name, ... }: { - options = { - proxy = mkOption { - type = types.attrs; - default = { }; - description = "Configuration to be proxied to the home-manager configuration for `home-manager.users.`."; - }; - }; - }; -in -{ - options.snowfallorg = { - home = mkOption { - type = types.attrsOf (types.submodule home-submodule); - default = { }; - description = "Options for configuring home environments."; - }; - }; - - config = { - # snowfallorg.home = osConfig.snowfallorg.home or { }; - }; -} diff --git a/modules/home/user/default.nix b/modules/home/user/default.nix new file mode 100644 index 0000000..559edc5 --- /dev/null +++ b/modules/home/user/default.nix @@ -0,0 +1,23 @@ +{ lib, options, ... }: + +let + inherit (lib) types mkOption mkIf; + + cfg = options.snowfallorg; +in + # (builtins.trace (cfg.user.name or "no name")) +{ + options.snowfallorg = { + user = { + name = mkOption { + type = types.str; + description = "The user's name."; + }; + }; + }; + + # config = mkIf ((cfg.user.name or null) != null) { + # @TODO(jakehamilton): Get user home directory from osConfig if + # it exists. + # }; +} diff --git a/modules/nixos/home/default.nix b/modules/nixos/home/default.nix deleted file mode 100644 index e9cd0a8..0000000 --- a/modules/nixos/home/default.nix +++ /dev/null @@ -1,33 +0,0 @@ -{ lib, config, ... }: - -let - inherit (lib) types mkOption mkMerge mapAttrsToList; - - home-submodule = { name, ... }: { - options = { - proxy = mkOption { - type = types.attrs; - default = { }; - description = "Configuration to be proxied to the home-manager configuration for `home-manager.users.`."; - }; - }; - }; - - cfg = config.snowfallorg; -in -{ - options.snowfallorg = { - home = mkOption { - type = types.attrsOf (types.submodule home-submodule); - default = { }; - description = "Options for configuring home environments."; - }; - }; - - config = mkMerge - (mapAttrsToList - (name: value: { - home-manager.users.${name} = value.proxy; - }) - (cfg.home)); -} From 9e4d35969942c0d64b7554c783076da72217c5ef Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Sat, 27 May 2023 12:24:20 -0700 Subject: [PATCH 12/26] wip: home-manager support --- lib/home/default.nix | 20 +++++++++++++------- lib/system/default.nix | 5 ++++- modules/darwin/home/default.nix | 31 +++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 modules/darwin/home/default.nix diff --git a/lib/home/default.nix b/lib/home/default.nix index d4e0ad3..3f64fe1 100644 --- a/lib/home/default.nix +++ b/lib/home/default.nix @@ -1,7 +1,7 @@ { core-inputs, user-inputs, snowfall-lib }: let - inherit (core-inputs.nixpkgs.lib) assertMsg foldl head tail concatMap optionalAttrs mkIf filterAttrs mapAttrs' mkMerge mapAttrsToList optionals mkDefault; + inherit (core-inputs.nixpkgs.lib) assertMsg foldl head tail concatMap optionalAttrs mkIf filterAttrs mapAttrs' mkMerge mapAttrsToList optionals mkDefault mkAliasDefinitions; user-homes-root = snowfall-lib.fs.get-snowfall-file "homes"; user-modules-root = snowfall-lib.fs.get-snowfall-file "modules"; @@ -57,7 +57,10 @@ in output = "homeConfigurations"; - modules = [ path ] ++ modules; + modules = [ + path + ../../modules/home/user/default.nix + ] ++ modules; specialArgs = { inherit name; @@ -80,6 +83,9 @@ in (module-args: import ./nix-registry-module.nix (module-args // { inherit user-inputs core-inputs; })) + ({ + snowfallorg.user.name = mkDefault user-metadata.user; + }) ]; extraSpecialArgs = specialArgs // args.specialArgs; @@ -180,7 +186,7 @@ in # @NOTE(jakehamilton): We *must* specify named attributes here in order # for home-manager to provide them. - wrapped-user-module = home-args@{ pkgs, lib, ... }: + wrapped-user-module = home-args@{ pkgs, lib, osConfig ? {}, ... }: let user-module-result = import user-module home-args; user-imports = @@ -193,6 +199,7 @@ in user-module-result.config else builtins.removeAttrs user-module-result [ "imports" "options" "_file" ]; + user = created-user.specialArgs.user; in { _file = builtins.toString user-module; @@ -201,8 +208,9 @@ in config = mkMerge [ user-config ({ - snowfallorg.user.name = mkDefault created-user.specialArgs.user; + snowfallorg.user.name = mkDefault user; }) + (osConfig.snowfallorg.home.resolvedHomes.${user} or {}) ]; }; in @@ -212,9 +220,7 @@ in config = mkIf host-matches { home-manager = { users.${user-name} = wrapped-user-module; - sharedModules = other-modules ++ [ - ../../modules/home/user/default.nix - ]; + sharedModules = other-modules; }; }; } diff --git a/lib/system/default.nix b/lib/system/default.nix index 9df24f9..296bf3e 100644 --- a/lib/system/default.nix +++ b/lib/system/default.nix @@ -100,10 +100,13 @@ in 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" ]) // { + ((builtins.removeAttrs args [ "system" "modules" ]) // { specialArgs = args.specialArgs // { format = "darwin"; }; + modules = args.modules ++ [ + ../../modules/darwin/home/default.nix + ]; }); linux-system-builder = args: core-inputs.nixpkgs.lib.nixosSystem diff --git a/modules/darwin/home/default.nix b/modules/darwin/home/default.nix new file mode 100644 index 0000000..7466dd8 --- /dev/null +++ b/modules/darwin/home/default.nix @@ -0,0 +1,31 @@ +{ lib, options, ... }: + +let + inherit (lib) types mkOption mkIf mkMerge mkAliasDefinitions; + + cfg = options.snowfallorg; +in +{ + options.snowfallorg = { + home = mkOption { + description = "Configuration for home-manager."; + type = types.attrsOf (types.submodule ({ name, ... }: { + options.config = { + type = types.attrs; + default = { }; + }; + })); + }; + + resolvedHomes = mkOption { + type = types.attrs; + default = { }; + }; + }; + + config = mkMerge (builtins.map + (name: { + snowfallorg.resolvedHomes.${name} = mkAliasDefinitions options.snowfallorg.home.${name}.config; + }) + (builtins.attrNames cfg.home)); +} From f85f831b3366e65b5d04388fff4639a7770e611d Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Sat, 27 May 2023 21:29:41 -0700 Subject: [PATCH 13/26] feat: home-manager support --- README.md | 216 ++++++++++++++++++++++++++++++-- flake.nix | 10 +- lib/home/default.nix | 25 +++- lib/system/default.nix | 8 +- modules/darwin/home/default.nix | 31 ----- modules/darwin/user/default.nix | 71 +++++++++++ modules/home/user/default.nix | 43 +++++-- modules/nixos/user/default.nix | 84 +++++++++++++ 8 files changed, 432 insertions(+), 56 deletions(-) delete mode 100644 modules/darwin/home/default.nix create mode 100644 modules/darwin/user/default.nix create mode 100644 modules/nixos/user/default.nix diff --git a/README.md b/README.md index 6ea7ca0..7769dcd 100644 --- a/README.md +++ b/README.md @@ -37,12 +37,13 @@ cd config 2. Create a new flake with one of the templates from [@snowfallorg/templates](https://github.com/snowfallorg/templates). -| Name | Description | -| --------- | ------------------------------------------------- | -| `system` | A NixOS system and modules ready to modify. | -| `package` | A Nix Flake that exports packages and an overlay. | -| `module` | A Nix Flake that exports NixOS modules. | -| `lib` | A Nix Flake that exports a custom `lib` | +| Name | Description | +| --------- | ---------------------------------------------------- | +| `system` | A NixOS system and modules ready to modify. | +| `package` | A Nix Flake that exports packages and an overlay. | +| `module` | A Nix Flake that exports NixOS modules. | +| `lib` | A Nix Flake that exports a custom `lib` | +| `empty` | A basic Nix Flake for you to customize from scratch. | ```bash # For example, to use the system template. @@ -195,12 +196,20 @@ snowfall-root/ │ ├─ modules/ (optional modules) │ │ -│ │ Any (nestable) directory name. The name of the directory will be the -│ │ name of the module. -│ └─ **/ +│ │ A directory named after the `platform` type that will be used for modules within. +│ │ +│ │ Supported platforms are: +│ │ - nixos +│ │ - darwin +│ │ - home +│ └─ / │ │ -│ │ A NixOS module. -│ └─ default.nix +│ │ Any (nestable) directory name. The name of the directory will be the +│ │ name of the module. +│ └─ **/ +│ │ +│ │ A NixOS module. +│ └─ default.nix │ ├─ overlays/ (optional overlays) │ │ @@ -246,6 +255,37 @@ snowfall-root/ │ │ │ │ A NixOS module for your system's configuration. │ └─ default.nix +│ +├─ homes/ (optional homes configurations) +│ │ +│ │ A directory named after the `home` type that will be used for all homes within. +│ │ +│ │ The architecture is any supported architecture of NixPkgs, for example: +│ │ - x86_64 +│ │ - aarch64 +│ │ - i686 +│ │ +│ │ The format is any supported NixPkgs format *or* a format provided by either nix-darwin +│ │ or nixos-generators. However, in order to build systems with nix-darwin or nixos-generators, +│ │ you must add `darwin` and `nixos-generators` inputs to your flake respectively. Here +│ │ are some example formats: +│ │ - linux +│ │ - darwin +│ │ - iso +│ │ - install-iso +│ │ - do +│ │ - vmware +│ │ +│ │ With the architecture and format together (joined by a hyphen), you get the name of the +│ │ directory for the home type. +│ └─ -/ +│ │ +│ │ A directory that contains a single home's configuration. The directory name +│ │ will be the name of the home. +│ └─ / +│ │ +│ │ A NixOS module for your home's configuration. +│ └─ default.nix ``` #### Default Flake @@ -526,6 +566,48 @@ type. See the following table for a list of supported formats from NixOS Generat | vm-nogui | Same as vm, but without a GUI | | vmware | VMWare image (VMDK) | +#### Home Manager + +Snowfall Lib supports configuring [Home Manager](https://github.com/nix-community/home-manager) +for both standalone use and for use as a module with NixOS or nix-darwin. To use this feature, +your flake must include `home-manager` as an input. + +```nix +{ + description = "My Flake"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-22.11"; + + snowfall-lib = { + url = "github:snowfallorg/lib"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + # In order to use Home Manager. + home-manager = { + url = "github:nix-community/home-manager"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = inputs: + # This is an example and in your actual flake you can use `snowfall-lib.mkFlake` + # directly unless you explicitly need a feature of `lib`. + let + lib = inputs.snowfall-lib.mkLib { + # You must pass in both your flake's inputs and the root directory of + # your flake. + inherit inputs; + src = ./.; + }; + in + # No additional configuration is required to use this feature, you only + # have to add home-manager to your flake inputs. + lib.mkFlake { }; +} +``` + ### `lib.snowfall.flake` Helpers related to Nix flakes. @@ -1162,6 +1244,24 @@ Result: "iso" ``` +#### `lib.snowfall.system.get-inferred-system-name` + +Get the name of a system based on its file path. + +Type: `Path -> String` + +Usage: + +```nix +get-inferred-system-name "/systems/my-system/default.nix" +``` + +Result: + +```nix +"my-system" +``` + #### `lib.snowfall.system.get-target-systems-metadata` Get structured data about all systems for a given target. @@ -1261,7 +1361,7 @@ Type: `Attrs -> Attrs` Usage: ```nix -create-systems { hosts.my-host.specialArgs.x = true; modules = [ my-shared-module ]; } +create-systems { hosts.my-host.specialArgs.x = true; modules.nixos = [ my-shared-module ]; } ``` Result: @@ -1270,6 +1370,98 @@ Result: { my-host = ; } ``` +### `lib.snowfall.home` + +#### `lib.snowfall.home.split-user-and-host` + +Get the user and host from a combined string. + +Type: `String -> Attrs` + +Usage: + +```nix +split-user-and-host "myuser@myhost" +``` + +Result: + +```nix +{ user = "myuser"; host = "myhost"; } +``` + +#### `lib.snowfall.home.create-home` + +Create a home. + +Type: `Attrs -> Attrs` + +Usage: + +```nix +create-home { path = ./homes/my-home; } +``` + +Result: + +```nix + +``` + +#### `lib.snowfall.home.create-homes` + +Create all available homes. + +Type: `Attrs -> Attrs` + +Usage: + +```nix +create-homes { users."my-user@my-system".specialArgs.x = true; modules = [ my-shared-module ]; } +``` + +Result: + +```nix +{ "my-user@my-system" = ; } +``` + +#### `lib.snowfall.home.get-target-homes-metadata` + +Get structured data about all homes for a given target. + +Type: `String -> [Attrs]` + +Usage: + +```nix +get-target-homes-metadata ./homes +``` + +Result: + +```nix +[ { system = "x86_64-linux"; name = "my-home"; path = "/homes/x86_64-linux/my-home";} ] +``` + +#### `lib.snowfall.home.create-home-system-modules` + +Create system modules for home-manager integration. + +Type: `Attrs -> [Module]` + +Usage: + +```nix +create-home-system-modules { users."my-user@my-system".specialArgs.x = true; modules = [ my-shared-module ]; } +``` + +Result: + +```nix +[Module] +``` + ### `lib.snowfall.package` Utilities for working with flake packages. diff --git a/flake.nix b/flake.nix index a023d2a..9a5fda2 100644 --- a/flake.nix +++ b/flake.nix @@ -39,8 +39,16 @@ { inherit mkLib mkFlake; + nixosModules = { + user = ./modules/nixos/user/default.nix; + }; + + darwinModules = { + user = ./modules/darwin/user/default.nix; + }; + homeModules = { - user = ./user/default.nix; + user = ./modules/home/user/default.nix; }; }; } diff --git a/lib/home/default.nix b/lib/home/default.nix index 3f64fe1..59bb4e4 100644 --- a/lib/home/default.nix +++ b/lib/home/default.nix @@ -18,6 +18,10 @@ in hm = snowfall-lib.internal.system-lib.home-manager.hm; }); + # Get the user and host from a combined string. + # Type: String -> Attrs + # Usage: split-user-and-host "myuser@myhost" + # result: { user = "myuser"; host = "myhost"; } split-user-and-host = target: let raw-name-parts = builtins.split "@" target; @@ -35,6 +39,10 @@ in }; + # Create a home. + # Type: Attrs -> Attrs + # Usage: create-home { path = ./homes/my-home; } + # result: create-home = { path , name ? builtins.unsafeDiscardStringContext (snowfall-lib.system.get-inferred-system-name path) @@ -92,6 +100,10 @@ in }); }; + # Get structured data about all homes for a given target. + # Type: String -> [Attrs] + # Usage: get-target-homes-metadata ./homes + # result: [ { system = "x86_64-linux"; name = "my-home"; path = "/homes/x86_64-linux/my-home";} ] get-target-homes-metadata = target: let homes = snowfall-lib.fs.get-directories target; @@ -141,6 +153,10 @@ in in created-homes; + # Create system modules for home-manager integration. + # Type: Attrs -> [Module] + # Usage: create-home-system-modules { users."my-user@my-system".specialArgs.x = true; modules = [ my-shared-module ]; } + # result: [Module] create-home-system-modules = users: let created-users = create-homes users; @@ -186,10 +202,10 @@ in # @NOTE(jakehamilton): We *must* specify named attributes here in order # for home-manager to provide them. - wrapped-user-module = home-args@{ pkgs, lib, osConfig ? {}, ... }: + wrapped-user-module = home-args@{ pkgs, lib, osConfig ? { }, ... }: let user-module-result = import user-module home-args; - user-imports = + user-imports = if user-module-result ? imports then user-module-result.imports else @@ -210,7 +226,7 @@ in ({ snowfallorg.user.name = mkDefault user; }) - (osConfig.snowfallorg.home.resolvedHomes.${user} or {}) + (osConfig.snowfallorg.home.resolved-homes.${user} or { }) ]; }; in @@ -218,6 +234,9 @@ in _file = "virtual:snowfallorg/home/user/${name}"; config = mkIf host-matches { + # Initialize user information. + snowfallorg.user.${user-name} = { }; + home-manager = { users.${user-name} = wrapped-user-module; sharedModules = other-modules; diff --git a/lib/system/default.nix b/lib/system/default.nix index 296bf3e..cccf5c5 100644 --- a/lib/system/default.nix +++ b/lib/system/default.nix @@ -96,6 +96,9 @@ in 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."; @@ -105,7 +108,7 @@ in format = "darwin"; }; modules = args.modules ++ [ - ../../modules/darwin/home/default.nix + ../../modules/darwin/user/default.nix ]; }); linux-system-builder = args: @@ -114,6 +117,9 @@ in specialArgs = args.specialArgs // { format = "linux"; }; + modules = args.modules ++ [ + ../../modules/nixos/user/default.nix + ]; }); in if virtual-system-type != "" then diff --git a/modules/darwin/home/default.nix b/modules/darwin/home/default.nix deleted file mode 100644 index 7466dd8..0000000 --- a/modules/darwin/home/default.nix +++ /dev/null @@ -1,31 +0,0 @@ -{ lib, options, ... }: - -let - inherit (lib) types mkOption mkIf mkMerge mkAliasDefinitions; - - cfg = options.snowfallorg; -in -{ - options.snowfallorg = { - home = mkOption { - description = "Configuration for home-manager."; - type = types.attrsOf (types.submodule ({ name, ... }: { - options.config = { - type = types.attrs; - default = { }; - }; - })); - }; - - resolvedHomes = mkOption { - type = types.attrs; - default = { }; - }; - }; - - config = mkMerge (builtins.map - (name: { - snowfallorg.resolvedHomes.${name} = mkAliasDefinitions options.snowfallorg.home.${name}.config; - }) - (builtins.attrNames cfg.home)); -} diff --git a/modules/darwin/user/default.nix b/modules/darwin/user/default.nix new file mode 100644 index 0000000..13046cc --- /dev/null +++ b/modules/darwin/user/default.nix @@ -0,0 +1,71 @@ +{ pkgs, lib, options, config, ... }: + +let + inherit (lib) types mkOption mkDefault foldl optionalAttrs; + + cfg = config.snowfallorg; + + user-names = builtins.attrNames cfg.user; + + create-system-users = system-users: name: + let + user = cfg.user.${name}; + in + system-users // (optionalAttrs user.create { + ${name} = { + home = mkDefault user.home.path; + isHidden = mkDefault false; + }; + }); + + create-resolved-home = resolved-homes: name: + let + user = cfg.user.${name}; + in + resolved-homes // { + ${name} = user.home.config; + }; +in +{ + options.snowfallorg = { + user = mkOption { + description = "User configuration."; + default = { }; + type = types.attrsOf (types.submodule ({ name, ... }: { + options = { + create = mkOption { + description = "Whether to create the user automatically."; + type = types.bool; + default = true; + }; + + home = { + path = mkOption { + type = types.str; + default = "/Users/${name}"; + }; + + config = mkOption { + type = types.attrs; + default = { }; + }; + }; + }; + })); + }; + + resolved-homes = mkOption { + type = types.attrs; + default = { }; + internal = true; + }; + }; + + config = { + users.users = (foldl (create-system-users) { } (user-names)); + + snowfallorg = { + resolved-homes = (foldl (create-resolved-home) { } (user-names)); + }; + }; +} diff --git a/modules/home/user/default.nix b/modules/home/user/default.nix index 559edc5..3cc9cba 100644 --- a/modules/home/user/default.nix +++ b/modules/home/user/default.nix @@ -1,23 +1,50 @@ -{ lib, options, ... }: +inputs@{ pkgs, lib, options, config, ... }: let - inherit (lib) types mkOption mkIf; + inherit (lib) types mkOption mkIf mkDefault; - cfg = options.snowfallorg; + cfg = config.snowfallorg; + + # @NOTE(jakehamilton): The module system chokes if it finds `osConfig` named in the module arguments + # when being used in standalone home-manager. To remedy this, we have to refer to the arguments set directly. + os-user-home = inputs.osConfig.users.users.${cfg.name}.home or null; + + default-home-directory = + if (os-user-home != null) then + os-user-home + else if pkgs.stdenv.isDarwin then + "/Users/${cfg.user.name}" + else + "/home/${cfg.user.name}"; in - # (builtins.trace (cfg.user.name or "no name")) { options.snowfallorg = { user = { + enable = mkOption { + type = types.bool; + default = true; + description = "Whether to configure the user."; + }; + name = mkOption { type = types.str; description = "The user's name."; }; + + home = { + directory = mkOption { + type = types.str; + description = "The user's home directory."; + default = default-home-directory; + }; + }; }; }; - # config = mkIf ((cfg.user.name or null) != null) { - # @TODO(jakehamilton): Get user home directory from osConfig if - # it exists. - # }; + config = mkIf cfg.user.enable { + home = { + username = mkIf (cfg.user.name or null != null) (mkDefault cfg.user.name); + homeDirectory = mkIf (cfg.user.name or null != null) (mkDefault cfg.user.home.directory); + }; + }; } diff --git a/modules/nixos/user/default.nix b/modules/nixos/user/default.nix new file mode 100644 index 0000000..81410a4 --- /dev/null +++ b/modules/nixos/user/default.nix @@ -0,0 +1,84 @@ +{ pkgs, lib, options, config, ... }: + +let + inherit (lib) types mkOption mkDefault foldl optionalAttrs optional; + + cfg = config.snowfallorg; + + user-names = builtins.attrNames cfg.user; + + create-system-users = system-users: name: + let + user = cfg.user.${name}; + in + system-users // (optionalAttrs user.create { + ${name} = { + isNormalUser = mkDefault true; + + name = mkDefault cfg.name; + + home = mkDefault user.home.path; + group = mkDefault "users"; + + extraGroups = (builtins.trace user.admin) optional user.admin "wheel"; + }; + }); + + create-resolved-home = resolved-homes: name: + let + user = cfg.user.${name}; + in + resolved-homes // { + ${name} = user.home.config; + }; +in +(builtins.trace "hello") +{ + options.snowfallorg = { + user = mkOption { + description = "User configuration."; + default = { }; + type = types.attrsOf (types.submodule ({ name, ... }: { + options = { + create = mkOption { + description = "Whether to create the user automatically."; + type = types.bool; + default = true; + }; + + admin = mkOption { + description = "Whether the user should be added to the wheel group."; + type = types.bool; + default = true; + }; + + home = { + path = mkOption { + type = types.str; + default = "/home/${name}"; + }; + + config = mkOption { + type = types.attrs; + default = { }; + }; + }; + }; + })); + }; + + resolved-homes = mkOption { + type = types.attrs; + default = { }; + internal = true; + }; + }; + + config = { + users.users = (foldl (create-system-users) { } (user-names)); + + snowfallorg = { + resolved-homes = (foldl (create-resolved-home) { } (user-names)); + }; + }; +} From 37950e37a2c6d6ecb8f673a5b8a3c63dc7d1b557 Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Sat, 27 May 2023 21:32:31 -0700 Subject: [PATCH 14/26] fix: remove trace --- modules/nixos/user/default.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/nixos/user/default.nix b/modules/nixos/user/default.nix index 81410a4..490a923 100644 --- a/modules/nixos/user/default.nix +++ b/modules/nixos/user/default.nix @@ -32,7 +32,6 @@ let ${name} = user.home.config; }; in -(builtins.trace "hello") { options.snowfallorg = { user = mkOption { From 165d8bb203a6a00670659f03c021e9c580f3f575 Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Sun, 28 May 2023 12:20:05 -0700 Subject: [PATCH 15/26] fix: use updated resolved-homes config value --- lib/home/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/home/default.nix b/lib/home/default.nix index 59bb4e4..1526351 100644 --- a/lib/home/default.nix +++ b/lib/home/default.nix @@ -226,7 +226,7 @@ in ({ snowfallorg.user.name = mkDefault user; }) - (osConfig.snowfallorg.home.resolved-homes.${user} or { }) + (osConfig.snowfallorg.resolved-homes.${user} or { }) ]; }; in From cfaa78937e55ab3d84632cd240efb9c9bd95280e Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Sun, 25 Jun 2023 18:58:14 -0700 Subject: [PATCH 16/26] fix: rework home-manager modules to allow option merging --- lib/home/default.nix | 123 +++++++++++++++++++++++--------- modules/darwin/user/default.nix | 55 ++++++++------ modules/home/user/default.nix | 6 +- modules/nixos/user/default.nix | 51 +++++++------ 4 files changed, 154 insertions(+), 81 deletions(-) diff --git a/lib/home/default.nix b/lib/home/default.nix index 1526351..035d87b 100644 --- a/lib/home/default.nix +++ b/lib/home/default.nix @@ -1,7 +1,26 @@ { core-inputs, user-inputs, snowfall-lib }: let - inherit (core-inputs.nixpkgs.lib) assertMsg foldl head tail concatMap optionalAttrs mkIf filterAttrs mapAttrs' mkMerge mapAttrsToList optionals mkDefault mkAliasDefinitions; + inherit (core-inputs.nixpkgs.lib) + assertMsg + foldl + head + tail + concatMap + optionalAttrs + optional + mkIf + filterAttrs + mapAttrs' + mkMerge + mapAttrsToList + optionals + mkDefault + traceSeqN + mkAliasDefinitions + mkAliasAndWrapDefinitions + mkOption + types; user-homes-root = snowfall-lib.fs.get-snowfall-file "homes"; user-modules-root = snowfall-lib.fs.get-snowfall-file "modules"; @@ -136,7 +155,11 @@ in src = "${user-modules-root}/home"; }; - user-home-modules-list = builtins.attrValues user-home-modules; + 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 @@ -160,6 +183,30 @@ in 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 = 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 @@ -184,15 +231,17 @@ in }; }; }; + system-modules = builtins.map (name: let created-user = created-users.${name}; user-module = head created-user.modules; - other-modules = tail created-user.modules; + other-modules = users.users.${name}.modules or [ ]; user-name = created-user.specialArgs.user; in args@{ config + , options , pkgs , host ? "" , ... @@ -200,52 +249,56 @@ in let host-matches = created-user.specialArgs.host == host; - # @NOTE(jakehamilton): We *must* specify named attributes here in order - # for home-manager to provide them. - wrapped-user-module = home-args@{ pkgs, lib, osConfig ? { }, ... }: - let - user-module-result = import user-module home-args; - user-imports = - if user-module-result ? imports then - user-module-result.imports - else - [ ]; - user-config = - if user-module-result ? config then - user-module-result.config - else - builtins.removeAttrs user-module-result [ "imports" "options" "_file" ]; - user = created-user.specialArgs.user; - in - { - _file = builtins.toString user-module; - imports = user-imports; + # @NOTE(jakehamilton): 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.user.${user-name}` was not detected to be merged. - config = mkMerge [ - user-config - ({ - snowfallorg.user.name = mkDefault user; - }) - (osConfig.snowfallorg.resolved-homes.${user} or { }) - ]; - }; + 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; in { _file = "virtual:snowfallorg/home/user/${name}"; config = mkIf host-matches { # Initialize user information. - snowfallorg.user.${user-name} = { }; + snowfallorg.user.${user-name}.home.config = { + snowfallorg.user.name = mkDefault user-name; + }; home-manager = { - users.${user-name} = wrapped-user-module; - sharedModules = other-modules; + users.${user-name} = mkAliasAndWrapDefinitions wrap-user-options options.snowfallorg.user; + + # sharedModules = other-modules ++ optional config.snowfallorg.user.${user-name}.home.enable wrapped-user-module; + sharedModules = other-modules ++ optional config.snowfallorg.user.${user-name}.home.enable user-module; }; }; } ) (builtins.attrNames created-users); in - [ extra-special-args-module ] ++ system-modules; + [ + extra-special-args-module + snowfall-user-home-module + ] + ++ (users.modules or [ ]) + ++ shared-modules + ++ system-modules; }; } diff --git a/modules/darwin/user/default.nix b/modules/darwin/user/default.nix index 13046cc..28f0931 100644 --- a/modules/darwin/user/default.nix +++ b/modules/darwin/user/default.nix @@ -1,4 +1,4 @@ -{ pkgs, lib, options, config, ... }: +{ pkgs, lib, options, config, inputs, ... }: let inherit (lib) types mkOption mkDefault foldl optionalAttrs; @@ -17,14 +17,6 @@ let isHidden = mkDefault false; }; }); - - create-resolved-home = resolved-homes: name: - let - user = cfg.user.${name}; - in - resolved-homes // { - ${name} = user.home.config; - }; in { options.snowfallorg = { @@ -40,32 +32,51 @@ in }; home = { + enable = mkOption { + type = types.bool; + default = true; + }; + path = mkOption { type = types.str; default = "/Users/${name}"; }; config = mkOption { - type = types.attrs; - default = { }; + # HM-compatible options taken from: + # https://github.com/nix-community/home-manager/blob/0ee5ab611dc1fbb5180bd7d88d2aeb7841a4d179/nixos/common.nix#L14 + type = types.submoduleWith { + specialArgs = { + osConfig = config; + modulesPath = "${inputs.home-manager}/modules"; + } // config.home-manager.extraSpecialArgs; + modules = [ + ({ lib, modulesPath, ... }: { + imports = import "${modulesPath}/modules.nix" { + inherit pkgs lib; + useNixpkgsModule = !config.home-manager.useGlobalPkgs; + }; + + config = { + submoduleSupport.enable = true; + submoduleSupport.externalPackageInstall = cfg.useUserPackages; + + home.username = config.users.users.${name}.name; + home.homeDirectory = config.users.users.${name}.home; + + nix.package = config.nix.package; + }; + }) + ] ++ config.home-manager.sharedModules; + }; }; }; }; })); }; - - resolved-homes = mkOption { - type = types.attrs; - default = { }; - internal = true; - }; }; config = { - users.users = (foldl (create-system-users) { } (user-names)); - - snowfallorg = { - resolved-homes = (foldl (create-resolved-home) { } (user-names)); - }; + users.users = (foldl create-system-users { } (user-names)); }; } diff --git a/modules/home/user/default.nix b/modules/home/user/default.nix index 3cc9cba..b81fc7e 100644 --- a/modules/home/user/default.nix +++ b/modules/home/user/default.nix @@ -9,6 +9,8 @@ let # when being used in standalone home-manager. To remedy this, we have to refer to the arguments set directly. os-user-home = inputs.osConfig.users.users.${cfg.name}.home or null; + has-user-name = (cfg.user.name or null) != null; + default-home-directory = if (os-user-home != null) then os-user-home @@ -43,8 +45,8 @@ in config = mkIf cfg.user.enable { home = { - username = mkIf (cfg.user.name or null != null) (mkDefault cfg.user.name); - homeDirectory = mkIf (cfg.user.name or null != null) (mkDefault cfg.user.home.directory); + username = mkIf has-user-name (mkDefault cfg.user.name); + homeDirectory = mkIf has-user-name (mkDefault cfg.user.home.directory); }; }; } diff --git a/modules/nixos/user/default.nix b/modules/nixos/user/default.nix index 490a923..a4d12b3 100644 --- a/modules/nixos/user/default.nix +++ b/modules/nixos/user/default.nix @@ -1,4 +1,4 @@ -{ pkgs, lib, options, config, ... }: +{ pkgs, lib, options, config, inputs, ... }: let inherit (lib) types mkOption mkDefault foldl optionalAttrs optional; @@ -15,22 +15,15 @@ let ${name} = { isNormalUser = mkDefault true; - name = mkDefault cfg.name; + name = mkDefault name; home = mkDefault user.home.path; group = mkDefault "users"; - extraGroups = (builtins.trace user.admin) optional user.admin "wheel"; + extraGroups = optional user.admin "wheel"; }; }); - create-resolved-home = resolved-homes: name: - let - user = cfg.user.${name}; - in - resolved-homes // { - ${name} = user.home.config; - }; in { options.snowfallorg = { @@ -58,26 +51,40 @@ in }; config = mkOption { - type = types.attrs; - default = { }; + # HM-compatible options taken from: + # https://github.com/nix-community/home-manager/blob/0ee5ab611dc1fbb5180bd7d88d2aeb7841a4d179/nixos/common.nix#L14 + type = types.submoduleWith { + specialArgs = { + osConfig = config; + modulesPath = "${inputs.home-manager}/modules"; + } // config.home-manager.extraSpecialArgs; + modules = [ + ({ lib, modulesPath, ... }: { + imports = import "${modulesPath}/modules.nix" { + inherit pkgs lib; + useNixpkgsModule = !config.home-manager.useGlobalPkgs; + }; + + config = { + submoduleSupport.enable = true; + submoduleSupport.externalPackageInstall = cfg.useUserPackages; + + home.username = config.users.users.${name}.name; + home.homeDirectory = config.users.users.${name}.home; + + nix.package = config.nix.package; + }; + }) + ] ++ config.home-manager.sharedModules; + }; }; }; }; })); }; - - resolved-homes = mkOption { - type = types.attrs; - default = { }; - internal = true; - }; }; config = { users.users = (foldl (create-system-users) { } (user-names)); - - snowfallorg = { - resolved-homes = (foldl (create-resolved-home) { } (user-names)); - }; }; } From 880d907905481fd5360534ba8b2fa11e90cb078c Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Sat, 1 Jul 2023 12:22:29 -0700 Subject: [PATCH 17/26] fix: only enable matched user homes --- lib/home/default.nix | 6 ++++-- modules/home/user/default.nix | 2 +- modules/nixos/user/default.nix | 5 +++++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/home/default.nix b/lib/home/default.nix index 035d87b..6a56fb8 100644 --- a/lib/home/default.nix +++ b/lib/home/default.nix @@ -16,7 +16,6 @@ let mapAttrsToList optionals mkDefault - traceSeqN mkAliasDefinitions mkAliasAndWrapDefinitions mkOption @@ -279,7 +278,10 @@ in config = mkIf host-matches { # Initialize user information. snowfallorg.user.${user-name}.home.config = { - snowfallorg.user.name = mkDefault user-name; + snowfallorg.user = { + enable = true; + name = mkDefault user-name; + }; }; home-manager = { diff --git a/modules/home/user/default.nix b/modules/home/user/default.nix index b81fc7e..7c7c93a 100644 --- a/modules/home/user/default.nix +++ b/modules/home/user/default.nix @@ -24,7 +24,7 @@ in user = { enable = mkOption { type = types.bool; - default = true; + default = false; description = "Whether to configure the user."; }; diff --git a/modules/nixos/user/default.nix b/modules/nixos/user/default.nix index a4d12b3..757997d 100644 --- a/modules/nixos/user/default.nix +++ b/modules/nixos/user/default.nix @@ -45,6 +45,11 @@ in }; home = { + enable = mkOption { + type = types.bool; + default = true; + }; + path = mkOption { type = types.str; default = "/home/${name}"; From 7d7546913d79a3376ac4ea1d505fc7808a564a91 Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Sat, 1 Jul 2023 17:00:35 -0700 Subject: [PATCH 18/26] fix: pass through snowfall configuration to mkLib --- flake.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index 9a5fda2..e0deb3d 100644 --- a/flake.nix +++ b/flake.nix @@ -27,10 +27,10 @@ # A convenience wrapper to create the library and then call `lib.mkFlake`. # Usage: mkFlake { inherit inputs; src = ./.; ... } # result: - mkFlake = flake-and-lib-options@{ inputs, src, ... }: + mkFlake = flake-and-lib-options@{ inputs, src, snowfall ? { }, ... }: let lib = mkLib { - inherit inputs src; + inherit inputs src snowfall; }; flake-options = builtins.removeAttrs flake-and-lib-options [ "inputs" "src" ]; in From 66e133580374d96700cde9396865ba996dfd2a78 Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Sat, 1 Jul 2023 17:44:12 -0700 Subject: [PATCH 19/26] fix: pass snowfall-config through to modules --- lib/attrs/default.nix | 1 + lib/default.nix | 7 ++++++- lib/flake/default.nix | 1 + lib/fp/default.nix | 1 + lib/fs/default.nix | 3 ++- lib/home/default.nix | 6 +++++- lib/internal/default.nix | 1 + lib/module/default.nix | 1 + lib/overlay/default.nix | 1 + lib/package/default.nix | 1 + lib/path/default.nix | 1 + lib/shell/default.nix | 1 + lib/system/default.nix | 1 + lib/template/default.nix | 1 + 14 files changed, 24 insertions(+), 3 deletions(-) diff --git a/lib/attrs/default.nix b/lib/attrs/default.nix index 9896757..c7a171f 100644 --- a/lib/attrs/default.nix +++ b/lib/attrs/default.nix @@ -1,6 +1,7 @@ { core-inputs , user-inputs , snowfall-lib +, snowfall-config }: let diff --git a/lib/default.nix b/lib/default.nix index ee1c6e8..05f0c3d 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -6,6 +6,11 @@ core-inputs: user-options: let + raw-snowfall-config = user-options.snowfall or { }; + snowfall-config = raw-snowfall-config // { + root = raw-snowfall-config.root or user-options.src; + }; + user-inputs = user-options.inputs // { src = user-options.src; }; inherit (core-inputs.nixpkgs.lib) assertMsg fix filterAttrs mergeAttrs fold recursiveUpdate callPackageWith; @@ -60,7 +65,7 @@ let snowfall-lib = fix (snowfall-lib: let attrs = { - inherit snowfall-lib core-inputs user-inputs; + inherit snowfall-lib snowfall-config core-inputs user-inputs; }; libs = builtins.map (dir: import "${snowfall-lib-root}/${dir}" attrs) diff --git a/lib/flake/default.nix b/lib/flake/default.nix index 979b3e2..26909ae 100644 --- a/lib/flake/default.nix +++ b/lib/flake/default.nix @@ -1,6 +1,7 @@ { core-inputs , user-inputs , snowfall-lib +, snowfall-config }: let diff --git a/lib/fp/default.nix b/lib/fp/default.nix index 78da0ee..63e0826 100644 --- a/lib/fp/default.nix +++ b/lib/fp/default.nix @@ -1,6 +1,7 @@ { core-inputs , user-inputs , snowfall-lib +, snowfall-config }: let diff --git a/lib/fs/default.nix b/lib/fs/default.nix index 3791a81..54cbe64 100644 --- a/lib/fs/default.nix +++ b/lib/fs/default.nix @@ -1,6 +1,7 @@ { core-inputs , user-inputs , snowfall-lib +, snowfall-config }: let @@ -31,7 +32,7 @@ in # Type: Path -> Path # Usage: get-snowfall-file "systems" # result: "/user-source/snowfall-dir/systems" - get-snowfall-file = path: "${user-inputs.snowfall.root or user-inputs.src}/${path}"; + get-snowfall-file = path: "${snowfall-config.root}/${path}"; # Get a file path relative to the this flake. # Type: Path -> Path diff --git a/lib/home/default.nix b/lib/home/default.nix index 6a56fb8..c2ea41b 100644 --- a/lib/home/default.nix +++ b/lib/home/default.nix @@ -1,4 +1,8 @@ -{ core-inputs, user-inputs, snowfall-lib }: +{ core-inputs +, user-inputs +, snowfall-lib +, snowfall-config +}: let inherit (core-inputs.nixpkgs.lib) diff --git a/lib/internal/default.nix b/lib/internal/default.nix index dfa4a78..40aa8b3 100644 --- a/lib/internal/default.nix +++ b/lib/internal/default.nix @@ -1,6 +1,7 @@ { core-inputs , user-inputs , snowfall-lib +, snowfall-config }: let diff --git a/lib/module/default.nix b/lib/module/default.nix index 7b647cb..6ef087a 100644 --- a/lib/module/default.nix +++ b/lib/module/default.nix @@ -1,6 +1,7 @@ { core-inputs , user-inputs , snowfall-lib +, snowfall-config }: let diff --git a/lib/overlay/default.nix b/lib/overlay/default.nix index cc8dccd..be2ea5d 100644 --- a/lib/overlay/default.nix +++ b/lib/overlay/default.nix @@ -1,6 +1,7 @@ { core-inputs , user-inputs , snowfall-lib +, snowfall-config }: let diff --git a/lib/package/default.nix b/lib/package/default.nix index 3968ecd..b77b51c 100644 --- a/lib/package/default.nix +++ b/lib/package/default.nix @@ -1,6 +1,7 @@ { core-inputs , user-inputs , snowfall-lib +, snowfall-config }: let diff --git a/lib/path/default.nix b/lib/path/default.nix index 216f194..602f42f 100644 --- a/lib/path/default.nix +++ b/lib/path/default.nix @@ -1,6 +1,7 @@ { core-inputs , user-inputs , snowfall-lib +, snowfall-config }: let diff --git a/lib/shell/default.nix b/lib/shell/default.nix index aecd0e2..4eb5aec 100644 --- a/lib/shell/default.nix +++ b/lib/shell/default.nix @@ -1,6 +1,7 @@ { core-inputs , user-inputs , snowfall-lib +, snowfall-config }: let diff --git a/lib/system/default.nix b/lib/system/default.nix index cccf5c5..6d9bfa5 100644 --- a/lib/system/default.nix +++ b/lib/system/default.nix @@ -1,6 +1,7 @@ { core-inputs , user-inputs , snowfall-lib +, snowfall-config }: let diff --git a/lib/template/default.nix b/lib/template/default.nix index 3e04626..6527c3a 100644 --- a/lib/template/default.nix +++ b/lib/template/default.nix @@ -1,6 +1,7 @@ { core-inputs , user-inputs , snowfall-lib +, snowfall-config }: let From 6b09a4b7b53c3c2531b6955a1d5e041fa10330f2 Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Sat, 1 Jul 2023 18:47:47 -0700 Subject: [PATCH 20/26] fix: do not pass snowfall config through to flake output --- lib/flake/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/flake/default.nix b/lib/flake/default.nix index 26909ae..15de25a 100644 --- a/lib/flake/default.nix +++ b/lib/flake/default.nix @@ -48,6 +48,7 @@ rec { "templates" "package-namespace" "alias" + "snowfall" ]; # Transform an attribute set of inputs into an attribute set where From 116971f60d713550264cdebf5e78d809f4ef42d0 Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Wed, 16 Aug 2023 23:46:29 -0700 Subject: [PATCH 21/26] wip: initial frost support --- flake.nix | 27 ++++++++++++- modules/nixos/user/default.nix | 39 +++++++++++-------- {lib => snowfall-lib}/attrs/default.nix | 0 {lib => snowfall-lib}/default.nix | 10 ++++- {lib => snowfall-lib}/flake/default.nix | 8 +++- {lib => snowfall-lib}/fp/default.nix | 0 {lib => snowfall-lib}/fs/default.nix | 0 {lib => snowfall-lib}/home/default.nix | 23 +++++++---- .../home/nix-registry-module.nix | 0 {lib => snowfall-lib}/internal/default.nix | 2 +- {lib => snowfall-lib}/module/default.nix | 0 {lib => snowfall-lib}/overlay/default.nix | 0 {lib => snowfall-lib}/package/default.nix | 12 +++++- {lib => snowfall-lib}/path/default.nix | 0 {lib => snowfall-lib}/shell/default.nix | 0 {lib => snowfall-lib}/system/default.nix | 0 .../system/virtual-systems.nix | 0 {lib => snowfall-lib}/template/default.nix | 0 18 files changed, 91 insertions(+), 30 deletions(-) rename {lib => snowfall-lib}/attrs/default.nix (100%) rename {lib => snowfall-lib}/default.nix (89%) rename {lib => snowfall-lib}/flake/default.nix (96%) rename {lib => snowfall-lib}/fp/default.nix (100%) rename {lib => snowfall-lib}/fs/default.nix (100%) rename {lib => snowfall-lib}/home/default.nix (94%) rename {lib => snowfall-lib}/home/nix-registry-module.nix (100%) rename {lib => snowfall-lib}/internal/default.nix (96%) rename {lib => snowfall-lib}/module/default.nix (100%) rename {lib => snowfall-lib}/overlay/default.nix (100%) rename {lib => snowfall-lib}/package/default.nix (86%) rename {lib => snowfall-lib}/path/default.nix (100%) rename {lib => snowfall-lib}/shell/default.nix (100%) rename {lib => snowfall-lib}/system/default.nix (100%) rename {lib => snowfall-lib}/system/virtual-systems.nix (100%) rename {lib => snowfall-lib}/template/default.nix (100%) diff --git a/flake.nix b/flake.nix index e0deb3d..3a6cf7e 100644 --- a/flake.nix +++ b/flake.nix @@ -22,7 +22,7 @@ # `lib.flake-utils-plus.mkApp`. # Usage: mkLib { inherit inputs; src = ./.; } # result: lib - mkLib = import ./lib core-inputs; + mkLib = import ./snowfall-lib core-inputs; # A convenience wrapper to create the library and then call `lib.mkFlake`. # Usage: mkFlake { inherit inputs; src = ./.; ... } @@ -50,5 +50,30 @@ homeModules = { user = ./modules/home/user/default.nix; }; + + _snowfall = rec { + raw-config = config; + + config = { + root = ./.; + src = ./.; + namespace = "snowfall"; + lib-dir = "snowfall-lib"; + }; + + internal-lib = + let + lib = mkLib { + src = ./.; + + inputs = inputs // { + self = { }; + }; + }; + in + builtins.removeAttrs + lib.snowfall + [ "internal" ]; + }; }; } diff --git a/modules/nixos/user/default.nix b/modules/nixos/user/default.nix index 757997d..e8483f1 100644 --- a/modules/nixos/user/default.nix +++ b/modules/nixos/user/default.nix @@ -1,10 +1,12 @@ -{ pkgs, lib, options, config, inputs, ... }: +args@{ pkgs, lib, options, config, ... }: let inherit (lib) types mkOption mkDefault foldl optionalAttrs optional; cfg = config.snowfallorg; + inputs = args.inputs or { }; + user-names = builtins.attrNames cfg.user; create-system-users = system-users: name: @@ -58,29 +60,32 @@ in config = mkOption { # HM-compatible options taken from: # https://github.com/nix-community/home-manager/blob/0ee5ab611dc1fbb5180bd7d88d2aeb7841a4d179/nixos/common.nix#L14 + # @NOTE(jakehamilton): This has been adapted to support documentation generation without + # having home-manager options fully declared. type = types.submoduleWith { specialArgs = { osConfig = config; - modulesPath = "${inputs.home-manager}/modules"; - } // config.home-manager.extraSpecialArgs; + modulesPath = "${inputs.home-manager or "/"}/modules"; + } // (config.home-manager.extraSpecialArgs or { }); modules = [ - ({ lib, modulesPath, ... }: { - imports = import "${modulesPath}/modules.nix" { - inherit pkgs lib; - useNixpkgsModule = !config.home-manager.useGlobalPkgs; - }; + ({ lib, modulesPath, ... }: + if inputs ? home-manager then { + imports = import "${modulesPath}/modules.nix" { + inherit pkgs lib; + useNixpkgsModule = !(config.home-manager.useGlobalPkgs or false); + }; - config = { - submoduleSupport.enable = true; - submoduleSupport.externalPackageInstall = cfg.useUserPackages; + config = { + submoduleSupport.enable = true; + submoduleSupport.externalPackageInstall = cfg.useUserPackages; - home.username = config.users.users.${name}.name; - home.homeDirectory = config.users.users.${name}.home; + home.username = config.users.users.${name}.name; + home.homeDirectory = config.users.users.${name}.home; - nix.package = config.nix.package; - }; - }) - ] ++ config.home-manager.sharedModules; + nix.package = config.nix.package; + }; + } else { }) + ] ++ (config.home-manager.sharedModules or [ ]); }; }; }; diff --git a/lib/attrs/default.nix b/snowfall-lib/attrs/default.nix similarity index 100% rename from lib/attrs/default.nix rename to snowfall-lib/attrs/default.nix diff --git a/lib/default.nix b/snowfall-lib/default.nix similarity index 89% rename from lib/default.nix rename to snowfall-lib/default.nix index 05f0c3d..988142c 100644 --- a/lib/default.nix +++ b/snowfall-lib/default.nix @@ -8,7 +8,13 @@ user-options: let raw-snowfall-config = user-options.snowfall or { }; snowfall-config = raw-snowfall-config // { + src = user-options.src; root = raw-snowfall-config.root or user-options.src; + namespace = raw-snowfall-config.namespace or "internal"; + meta = { + name = raw-snowfall-config.meta.name or null; + title = raw-snowfall-config.meta.title or null; + }; }; user-inputs = user-options.inputs // { src = user-options.src; }; @@ -53,7 +59,9 @@ let core-inputs-libs = get-libs (without-self core-inputs); user-inputs-libs = get-libs (without-self user-inputs); - snowfall-lib-root = "${core-inputs.src}/lib"; + # @NOTE(jakehamilton): This root is different to accomodate the creation + # of a fake user-lib in order to run documentation on this flake. + snowfall-lib-root = "${core-inputs.src}/snowfall-lib"; snowfall-lib-dirs = let files = builtins.readDir snowfall-lib-root; diff --git a/lib/flake/default.nix b/snowfall-lib/flake/default.nix similarity index 96% rename from lib/flake/default.nix rename to snowfall-lib/flake/default.nix index 15de25a..3178e3e 100644 --- a/lib/flake/default.nix +++ b/snowfall-lib/flake/default.nix @@ -71,7 +71,7 @@ rec { mkFlake = full-flake-options: let - package-namespace = full-flake-options.package-namespace or "internal"; + package-namespace = full-flake-options.package-namespace or snowfall-config.namespace or "internal"; custom-flake-options = flake.without-snowfall-options full-flake-options; alias = full-flake-options.alias or { }; homes = snowfall-lib.home.create-homes (full-flake-options.homes or { }); @@ -149,6 +149,12 @@ rec { }; outputsBuilder = outputs-builder; + + _snowfall = { + config = snowfall-config; + raw-config = full-flake-options.snowfall or { }; + user-lib = snowfall-lib.internal.user-lib; + }; }; flake-utils-plus-outputs = diff --git a/lib/fp/default.nix b/snowfall-lib/fp/default.nix similarity index 100% rename from lib/fp/default.nix rename to snowfall-lib/fp/default.nix diff --git a/lib/fs/default.nix b/snowfall-lib/fs/default.nix similarity index 100% rename from lib/fs/default.nix rename to snowfall-lib/fs/default.nix diff --git a/lib/home/default.nix b/snowfall-lib/home/default.nix similarity index 94% rename from lib/home/default.nix rename to snowfall-lib/home/default.nix index c2ea41b..fe81473 100644 --- a/lib/home/default.nix +++ b/snowfall-lib/home/default.nix @@ -31,14 +31,21 @@ in { home = rec { # Modules in home-manager expect `hm` to be available directly on `lib` itself. - home-lib = snowfall-lib.internal.system-lib.extend (final: prev: - # @NOTE(jakehamilton): 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; - }); + home-lib = + # @NOTE(jakehamilton): 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(jakehamilton): 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. # Type: String -> Attrs diff --git a/lib/home/nix-registry-module.nix b/snowfall-lib/home/nix-registry-module.nix similarity index 100% rename from lib/home/nix-registry-module.nix rename to snowfall-lib/home/nix-registry-module.nix diff --git a/lib/internal/default.nix b/snowfall-lib/internal/default.nix similarity index 96% rename from lib/internal/default.nix rename to snowfall-lib/internal/default.nix index 40aa8b3..e61eb73 100644 --- a/lib/internal/default.nix +++ b/snowfall-lib/internal/default.nix @@ -42,7 +42,7 @@ let system-lib = snowfall-lib.attrs.merge-shallow [ base-lib - { internal = user-lib; } + { "${snowfall-config.namespace}" = user-lib; } ]; in { diff --git a/lib/module/default.nix b/snowfall-lib/module/default.nix similarity index 100% rename from lib/module/default.nix rename to snowfall-lib/module/default.nix diff --git a/lib/overlay/default.nix b/snowfall-lib/overlay/default.nix similarity index 100% rename from lib/overlay/default.nix rename to snowfall-lib/overlay/default.nix diff --git a/lib/package/default.nix b/snowfall-lib/package/default.nix similarity index 86% rename from lib/package/default.nix rename to snowfall-lib/package/default.nix index b77b51c..f2b5a6d 100644 --- a/lib/package/default.nix +++ b/snowfall-lib/package/default.nix @@ -40,7 +40,17 @@ in in { name = builtins.unsafeDiscardStringContext (snowfall-lib.path.get-parent-directory package); - drv = callPackageWith extra-inputs 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; merge-packages = packages: metadata: diff --git a/lib/path/default.nix b/snowfall-lib/path/default.nix similarity index 100% rename from lib/path/default.nix rename to snowfall-lib/path/default.nix diff --git a/lib/shell/default.nix b/snowfall-lib/shell/default.nix similarity index 100% rename from lib/shell/default.nix rename to snowfall-lib/shell/default.nix diff --git a/lib/system/default.nix b/snowfall-lib/system/default.nix similarity index 100% rename from lib/system/default.nix rename to snowfall-lib/system/default.nix diff --git a/lib/system/virtual-systems.nix b/snowfall-lib/system/virtual-systems.nix similarity index 100% rename from lib/system/virtual-systems.nix rename to snowfall-lib/system/virtual-systems.nix diff --git a/lib/template/default.nix b/snowfall-lib/template/default.nix similarity index 100% rename from lib/template/default.nix rename to snowfall-lib/template/default.nix From 838d233474e3a8dfe97b1e88efbe8139c100f9be Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Thu, 17 Aug 2023 00:24:05 -0700 Subject: [PATCH 22/26] feat: convert comments to doc comments --- flake.nix | 6 + snowfall-lib/attrs/default.nix | 56 ++++++--- snowfall-lib/flake/default.nix | 73 +++++++---- snowfall-lib/fp/default.nix | 56 ++++++--- snowfall-lib/fs/default.nix | 197 +++++++++++++++++++++--------- snowfall-lib/home/default.nix | 70 ++++++++--- snowfall-lib/module/default.nix | 14 ++- snowfall-lib/overlay/default.nix | 31 +++-- snowfall-lib/package/default.nix | 14 ++- snowfall-lib/path/default.nix | 84 +++++++++---- snowfall-lib/shell/default.nix | 14 ++- snowfall-lib/system/default.nix | 154 ++++++++++++++++------- snowfall-lib/template/default.nix | 16 ++- 13 files changed, 559 insertions(+), 226 deletions(-) diff --git a/flake.nix b/flake.nix index 3a6cf7e..a1ab023 100644 --- a/flake.nix +++ b/flake.nix @@ -52,6 +52,7 @@ }; _snowfall = rec { + raw-config = config; config = { @@ -59,6 +60,11 @@ src = ./.; namespace = "snowfall"; lib-dir = "snowfall-lib"; + + meta = { + name = "snowfall-lib"; + title = "Snowfall Lib"; + }; }; internal-lib = diff --git a/snowfall-lib/attrs/default.nix b/snowfall-lib/attrs/default.nix index c7a171f..ea5dbee 100644 --- a/snowfall-lib/attrs/default.nix +++ b/snowfall-lib/attrs/default.nix @@ -17,29 +17,53 @@ let in { attrs = { - # Map and flatten an attribute set into a list. - # Type: (a -> b -> [c]) -> Attrs -> [c] - # Usage: map-concat-attrs-to-list (name: value: [name value]) { x = 1; y = 2; } - # result: [ "x" 1 "y" 2 ] + ## Map and flatten an attribute set into a list. + ## Example Usage: + ## ```nix + ## map-concat-attrs-to-list (name: value: [name value]) { x = 1; y = 2; } + ## ``` + ## Result: + ## ```nix + ## [ "x" 1 "y" 2 ] + ## ``` + #@ (a -> b -> [c]) -> Attrs -> [c] map-concat-attrs-to-list = f: attrs: flatten (mapAttrsToList f attrs); - # Recursively merge a list of attribute sets. - # Type: [Attrs] -> Attrs - # Usage: merge-deep [{ x = 1; } { x = 2; }] - # result: { x = 2; } + ## Recursively merge a list of attribute sets. + ## Example Usage: + ## ```nix + ## merge-deep [{ x = 1; } { x = 2; }] + ## ``` + ## Result: + ## ```nix + ## { x = 2; } + ## ``` + #@ [Attrs] -> Attrs merge-deep = foldl recursiveUpdate { }; - # Merge the root of a list of attribute sets. - # Type: [Attrs] -> Attrs - # Usage: merge-shallow [{ x = 1; } { x = 2; }] - # result: { x = 2; } + ## Merge the root of a list of attribute sets. + ## Example Usage: + ## ```nix + ## merge-shallow [{ x = 1; } { x = 2; }] + ## ``` + ## Result: + ## ```nix + ## { x = 2; } + ## ``` + #@ [Attrs] -> Attrs merge-shallow = foldl mergeAttrs { }; - # Merge shallow for packages, but allow one deeper layer of attribute sets. - # Type: [Attrs] -> Attrs - # Usage: merge-shallow-packages [ { inherit (pkgs) vim; some.value = true; } { some.value = false; } ] - # result: { vim = ...; some.value = false; } + ## Merge shallow for packages, but allow one deeper layer of attribute sets. + ## Example Usage: + ## ```nix + ## merge-shallow-packages [ { inherit (pkgs) vim; some.value = true; } { some.value = false; } ] + ## ``` + ## Result: + ## ```nix + ## { vim = ...; some.value = false; } + ## ``` + #@ [Attrs] -> Attrs merge-shallow-packages = items: foldl (result: item: diff --git a/snowfall-lib/flake/default.nix b/snowfall-lib/flake/default.nix index 3178e3e..223762e 100644 --- a/snowfall-lib/flake/default.nix +++ b/snowfall-lib/flake/default.nix @@ -9,29 +9,52 @@ let in rec { flake = rec { - # Remove the `self` attribute from an attribute set. - # Type: Attrs -> Attrs - # Usage: without-self { self = {}; x = true; } - # result: { x = true; } + ## 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. - # Type: Attrs -> Attrs - # Usage: without-src { src = ./.; x = true; } - # result: { x = true; } + ## 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" ]; - # Remove the `src` and `self` attributes from an attribute set. - # Type: Attrs -> Attrs - # Usage: without-snowfall-inputs { self = {}; src = ./.; x = true; } - # result: { x = true; } + ## 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. - # Type: Attrs -> Attrs - # Usage: without-snowfall-options { src = ./.; x = true; } - # result: { x = true; } + ## 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 @@ -51,12 +74,16 @@ rec { "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. - # Type: Attrs -> Attrs - # Usage: get-lib { x = nixpkgs; y = {}; } - # result: { x = nixpkgs.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: let # @PERF(jakehamilton): Replace filter+map with a fold. diff --git a/snowfall-lib/fp/default.nix b/snowfall-lib/fp/default.nix index 63e0826..83b7c74 100644 --- a/snowfall-lib/fp/default.nix +++ b/snowfall-lib/fp/default.nix @@ -10,28 +10,52 @@ let in { fp = rec { - # Compose two functions. - # Type: (b -> c) -> (a -> b) -> a -> c - # Usage: compose add-two add-one - # result: (x: add-two (add-one x)) + ## 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); - # Compose many functions. - # Type: [(x -> y)] -> a -> b - # Usage: compose-all [ add-two add-one ] - # result: (x: add-two (add-one x)) + ## 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; - # Call a function with an argument. - # Type: (a -> b) -> a -> b - # Usage: call (x: x + 1) 0 - # result: 1 + ## 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; - # Apply an argument to a function. - # Type: a -> (a -> b) -> b - # Usage: call (x: x + 1) 0 - # result: 1 + ## Apply an argument to a function. + ## Example Usage: + ## ```nix + ## call (x: x + 1) 0 + ## ``` + ## 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 54cbe64..3877408 100644 --- a/snowfall-lib/fs/default.nix +++ b/snowfall-lib/fs/default.nix @@ -13,47 +13,83 @@ let in { fs = rec { - # Matchers for file kinds. These are often used with `readDir`. - # Type: String -> Bool - # Usage: is-file-kind "directory" - # result: false + ## Matchers for file kinds. These are often used with `readDir`. + ## Example Usage: + ## ```nix + ## is-file-kind "directory" + ## ``` + ## Result: + ## ```nix + ## false + ## ``` + #@ String -> Bool is-file-kind = kind: kind == "regular"; is-symlink-kind = kind: kind == "symlink"; is-directory-kind = kind: kind == "directory"; is-unknown-kind = kind: kind == "unknown"; - # Get a file path relative to the user's flake. - # Type: Path -> Path - # Usage: get-file "systems" - # result: "/user-source/systems" + ## Get a file path relative to the user's flake. + ## Example Usage: + ## ```nix + ## get-file "systems" + ## ``` + ## Result: + ## ```nix + ## "/user-source/systems" + ## ``` + #@ Path -> Path get-file = path: "${user-inputs.src}/${path}"; - # Get a file path relative to the user's snowfall directory. - # Type: Path -> Path - # Usage: get-snowfall-file "systems" - # result: "/user-source/snowfall-dir/systems" + ## Get a file path relative to the user's snowfall directory. + ## Example Usage: + ## ```nix + ## get-snowfall-file "systems" + ## ``` + ## Result: + ## ```nix + ## "/user-source/snowfall-dir/systems" + ## ``` + #@ Path -> Path get-snowfall-file = path: "${snowfall-config.root}/${path}"; - # Get a file path relative to the this flake. - # Type: Path -> Path - # Usage: get-file "systems" - # result: "/user-source/systems" + ## Get a file path relative to the this flake. + ## Example Usage: + ## ```nix + ## get-file "systems" + ## ``` + ## Result: + ## ```nix + ## "/user-source/systems" + ## ``` + #@ Path -> Path internal-get-file = path: "${core-inputs.src}/${path}"; - # Safely read from a directory if it exists. - # Type: Path -> Attrs - # Usage: safe-read-directory ./some/path - # result: { "my-file.txt" = "regular"; } + ## Safely read from a directory if it exists. + ## Example Usage: + ## ```nix + ## safe-read-directory ./some/path + ## ``` + ## Result: + ## ```nix + ## { "my-file.txt" = "regular"; } + ## ``` + #@ Path -> Attrs safe-read-directory = path: if pathExists path then readDir path else { }; - # Get directories at a given path. - # Type: Path -> [Path] - # Usage: get-directories ./something - # result: [ "./something/a-directory" ] + ## Get directories at a given path. + ## Example Usage: + ## ```nix + ## get-directories ./something + ## ``` + ## Result: + ## ```nix + ## [ "./something/a-directory" ] + ## ``` + #@ Path -> [Path] get-directories = path: let entries = safe-read-directory path; @@ -61,10 +97,16 @@ in in mapAttrsToList (name: kind: "${path}/${name}") filtered-entries; - # Get files at a given path. - # Type: Path -> [Path] - # Usage: get-files ./something - # result: [ "./something/a-file" ] + ## Get files at a given path. + ## Example Usage: + ## ```nix + ## get-files ./something + ## ``` + ## Result: + ## ```nix + ## [ "./something/a-file" ] + ## ``` + #@ Path -> [Path] get-files = path: let entries = safe-read-directory path; @@ -72,10 +114,16 @@ in in mapAttrsToList (name: kind: "${path}/${name}") filtered-entries; - # Get files at a given path, traversing any directories within. - # Type: Path -> [Path] - # Usage: get-files-recursive ./something - # result: [ "./something/some-directory/a-file" ] + ## Get files at a given path, traversing any directories within. + ## Example Usage: + ## ```nix + ## get-files-recursive ./something + ## ``` + ## Result: + ## ```nix + ## [ "./something/some-directory/a-file" ] + ## ``` + #@ Path -> [Path] get-files-recursive = path: let entries = safe-read-directory path; @@ -97,46 +145,76 @@ in in files; - # Get nix files at a given path. - # Type: Path -> [Path] - # Usage: get-nix-files "./something" - # result: [ "./something/a.nix" ] + ## Get nix files at a given path. + ## Example Usage: + ## ```nix + ## get-nix-files "./something" + ## ``` + ## Result: + ## ```nix + ## [ "./something/a.nix" ] + ## ``` + #@ Path -> [Path] get-nix-files = path: builtins.filter (snowfall-lib.path.has-file-extension "nix") (get-files path); - # Get nix files at a given path, traversing any directories within. - # Type: Path -> [Path] - # Usage: get-nix-files "./something" - # result: [ "./something/a.nix" ] + ## Get nix files at a given path, traversing any directories within. + ## Example Usage: + ## ```nix + ## get-nix-files "./something" + ## ``` + ## Result: + ## ```nix + ## [ "./something/a.nix" ] + ## ``` + #@ Path -> [Path] get-nix-files-recursive = path: builtins.filter (snowfall-lib.path.has-file-extension "nix") (get-files-recursive path); - # Get nix files at a given path named "default.nix". - # Type: Path -> [Path] - # Usage: get-default-nix-files "./something" - # result: [ "./something/default.nix" ] + ## Get nix files at a given path named "default.nix". + ## Example Usage: + ## ```nix + ## get-default-nix-files "./something" + ## ``` + ## Result: + ## ```nix + ## [ "./something/default.nix" ] + ## ``` + #@ Path -> [Path] get-default-nix-files = path: builtins.filter (name: builtins.baseNameOf name == "default.nix") (get-files path); - # Get nix files at a given path named "default.nix", traversing any directories within. - # Type: Path -> [Path] - # Usage: get-default-nix-files-recursive "./something" - # result: [ "./something/some-directory/default.nix" ] + ## Get nix files at a given path named "default.nix", traversing any directories within. + ## Example Usage: + ## ```nix + ## get-default-nix-files-recursive "./something" + ## ``` + ## Result: + ## ```nix + ## [ "./something/some-directory/default.nix" ] + ## ``` + #@ Path -> [Path] get-default-nix-files-recursive = path: builtins.filter (name: builtins.baseNameOf name == "default.nix") (get-files-recursive path); - # Get nix files at a given path not named "default.nix". - # Type: Path -> [Path] - # Usage: get-non-default-nix-files "./something" - # result: [ "./something/a.nix" ] + ## Get nix files at a given path not named "default.nix". + ## Example Usage: + ## ```nix + ## get-non-default-nix-files "./something" + ## ``` + ## Result: + ## ```nix + ## [ "./something/a.nix" ] + ## ``` + #@ Path -> [Path] get-non-default-nix-files = path: builtins.filter (name: @@ -145,11 +223,16 @@ in ) (get-files path); - # Get nix files at a given path not named "default.nix", - # traversing any directories within. - # Type: Path -> [Path] - # Usage: get-non-default-nix-files-recursive "./something" - # result: [ "./something/some-directory/a.nix" ] + ## Get nix files at a given path not named "default.nix", traversing any directories within. + ## Example Usage: + ## ```nix + ## get-non-default-nix-files-recursive "./something" + ## ``` + ## Result: + ## ```nix + ## [ "./something/some-directory/a.nix" ] + ## ``` + #@ Path -> [Path] get-non-default-nix-files-recursive = path: builtins.filter (name: diff --git a/snowfall-lib/home/default.nix b/snowfall-lib/home/default.nix index fe81473..e5cac40 100644 --- a/snowfall-lib/home/default.nix +++ b/snowfall-lib/home/default.nix @@ -47,10 +47,16 @@ in else { }; - # Get the user and host from a combined string. - # Type: String -> Attrs - # Usage: split-user-and-host "myuser@myhost" - # result: { user = "myuser"; host = "myhost"; } + ## 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 raw-name-parts = builtins.split "@" target; @@ -68,10 +74,16 @@ in }; - # Create a home. - # Type: Attrs -> Attrs - # Usage: create-home { path = ./homes/my-home; } - # result: + ## 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) @@ -129,10 +141,16 @@ in }); }; - # Get structured data about all homes for a given target. - # Type: String -> [Attrs] - # Usage: get-target-homes-metadata ./homes - # result: [ { system = "x86_64-linux"; name = "my-home"; path = "/homes/x86_64-linux/my-home";} ] + ## 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 homes = snowfall-lib.fs.get-directories target; @@ -152,10 +170,16 @@ in in home-configurations; - # Create all available homes. - # Type: Attrs -> Attrs - # Usage: create-homes { users."my-user@my-system".specialArgs.x = true; modules = [ my-shared-module ]; } - # result: { "my-user@my-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; @@ -186,10 +210,16 @@ in in created-homes; - # Create system modules for home-manager integration. - # Type: Attrs -> [Module] - # Usage: create-home-system-modules { users."my-user@my-system".specialArgs.x = true; modules = [ my-shared-module ]; } - # result: [Module] + ## 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; diff --git a/snowfall-lib/module/default.nix b/snowfall-lib/module/default.nix index 6ef087a..7b12e45 100644 --- a/snowfall-lib/module/default.nix +++ b/snowfall-lib/module/default.nix @@ -12,10 +12,16 @@ let in { module = { - # Create flake output modules. - # Type: Attrs -> Attrs - # Usage: create-modules { src = ./my-modules; overrides = { inherit another-module; }; alias = { default = "another-module" }; } - # result: { another-module = ...; my-module = ...; default = ...; } + ## Create flake output modules. + ## Example Usage: + ## ```nix + ## create-modules { src = ./my-modules; overrides = { inherit another-module; }; alias = { default = "another-module" }; } + ## ``` + ## Result: + ## ```nix + ## { another-module = ...; my-module = ...; default = ...; } + ## ``` + #@ Attrs -> Attrs create-modules = { src ? "${user-modules-root}/nixos" , overrides ? { } diff --git a/snowfall-lib/overlay/default.nix b/snowfall-lib/overlay/default.nix index be2ea5d..f1fd589 100644 --- a/snowfall-lib/overlay/default.nix +++ b/snowfall-lib/overlay/default.nix @@ -12,10 +12,16 @@ let in { overlay = { - # Create a flake-utils-plus overlays builder. - # Type: Attrs -> Attrs -> [(a -> b -> c)] - # Usage: create-overlays { src = ./my-overlays; package-namespace = "my-packages"; } - # result: (channels: [ ... ]) + ## Create a flake-utils-plus overlays builder. + ## Example Usage: + ## ```nix + ## create-overlays { src = ./my-overlays; package-namespace = "my-packages"; } + ## ``` + ## Result: + ## ```nix + ## (channels: [ ... ]) + ## ``` + #@ Attrs -> Attrs -> [(a -> b -> c)] create-overlays-builder = { src ? user-overlays-root , package-namespace ? "internal" @@ -41,12 +47,17 @@ in in overlays; - # Create exported overlays from the user flake. - # Adapted from flake-utils-plus: - # https://github.com/gytis-ivaskevicius/flake-utils-plus/blob/2bf0f91643c2e5ae38c1b26893ac2927ac9bd82a/lib/exportOverlays.nix - # Type: Attrs -> Attrs - # Usage: create-overlays { src = ./my-overlays; packages-src = ./my-packages; package-namespace = "my-namespace"; extra-overlays = {}; } - # result: { default = final: prev: ...; some-overlay = final: prev: ...; } + ## Create exported overlays from the user flake. Adapted [from flake-utils-plus](https://github.com/gytis-ivaskevicius/flake-utils-plus/blob/2bf0f91643c2e5ae38c1b26893ac2927ac9bd82a/lib/exportOverlays.nix). + ## + ## Example Usage: + ## ```nix + ## create-overlays { src = ./my-overlays; packages-src = ./my-packages; package-namespace = "my-namespace"; extra-overlays = {}; } + ## ``` + ## Result: + ## ```nix + ## { default = final: prev: ...; some-overlay = final: prev: ...; } + ## ``` + #@ Attrs -> Attrs create-overlays = { src ? user-overlays-root , packages-src ? user-packages-root diff --git a/snowfall-lib/package/default.nix b/snowfall-lib/package/default.nix index f2b5a6d..3fea3b5 100644 --- a/snowfall-lib/package/default.nix +++ b/snowfall-lib/package/default.nix @@ -12,10 +12,16 @@ let in { package = rec { - # Create flake output packages. - # Type: Attrs -> Attrs - # Usage: create-packages { inherit channels; src = ./my-packages; overrides = { inherit another-package; }; alias.default = "another-package"; } - # result: { another-package = ...; my-package = ...; default = ...; } + ## 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 diff --git a/snowfall-lib/path/default.nix b/snowfall-lib/path/default.nix index 602f42f..d09173e 100644 --- a/snowfall-lib/path/default.nix +++ b/snowfall-lib/path/default.nix @@ -12,10 +12,16 @@ let in { path = rec { - # Split a file name and its extension. - # Type: String -> [String] - # Usage: split-file-extension "my-file.md" - # result: [ "my-file" "md" ] + ## Split a file name and its extension. + ## Example Usage: + ## ```nix + ## split-file-extension "my-file.md" + ## ``` + ## Result: + ## ```nix + ## [ "my-file" "md" ] + ## ``` + #@ String -> [String] split-file-extension = file: let match = builtins.match file-name-regex file; @@ -23,20 +29,32 @@ in assert assertMsg (match != null) "lib.snowfall.split-file-extension: File must have an extension to split."; match; - # Check if a file name has a file extension. - # Type: String -> Bool - # Usage: has-any-file-extension "my-file.txt" - # result: true + ## Check if a file name has a file extension. + ## Example Usage: + ## ```nix + ## has-any-file-extension "my-file.txt" + ## ``` + ## Result: + ## ```nix + ## true + ## ``` + #@ String -> Bool has-any-file-extension = file: let match = builtins.match file-name-regex (toString file); in match != null; - # Get the file extension of a file name. - # Type: String -> String - # Usage: get-file-extension "my-file.final.txt" - # result: "txt" + ## Get the file extension of a file name. + ## Example Usage: + ## ```nix + ## get-file-extension "my-file.final.txt" + ## ``` + ## Result: + ## ```nix + ## "txt" + ## ``` + #@ String -> String get-file-extension = file: if has-any-file-extension file then let @@ -46,26 +64,44 @@ in else ""; - # Check if a file name has a specific file extension. - # Type: String -> String -> Bool - # Usage: has-file-extension "txt" "my-file.txt" - # result: true + ## Check if a file name has a specific file extension. + ## Example Usage: + ## ```nix + ## has-file-extension "txt" "my-file.txt" + ## ``` + ## Result: + ## ```nix + ## true + ## ``` + #@ String -> String -> Bool has-file-extension = extension: file: if has-any-file-extension file then extension == get-file-extension file else false; - # Get the parent directory for a given path. - # Type: Path -> Path - # Usage: get-parent-directory "/a/b/c" - # result: "/a/b" + ## Get the parent directory for a given path. + ## Example Usage: + ## ```nix + ## get-parent-directory "/a/b/c" + ## ``` + ## Result: + ## ```nix + ## "/a/b" + ## ``` + #@ Path -> Path get-parent-directory = snowfall-lib.fp.compose baseNameOf dirOf; - # Get the file name of a path without its extension. - # Type: Path -> String - # Usage: get-file-name-without-extension ./some-directory/my-file.pdf - # result: "my-file" + ## Get the file name of a path without its extension. + ## Example Usage: + ## ```nix + ## get-file-name-without-extension ./some-directory/my-file.pdf + ## ``` + ## Result: + ## ```nix + ## "my-file" + ## ``` + #@ Path -> String get-file-name-without-extension = path: let file-name = baseNameOf path; diff --git a/snowfall-lib/shell/default.nix b/snowfall-lib/shell/default.nix index 4eb5aec..c1cb6a7 100644 --- a/snowfall-lib/shell/default.nix +++ b/snowfall-lib/shell/default.nix @@ -12,10 +12,16 @@ let in { shell = { - # Create flake output packages. - # Type: Attrs -> Attrs - # Usage: create-shells { inherit channels; src = ./my-shells; overrides = { inherit another-shell; }; alias = { default = "another-shell"; }; } - # result: { another-shell = ...; my-shell = ...; default = ...; } + ## Create flake output packages. + ## Example Usage: + ## ```nix + ## create-shells { inherit channels; src = ./my-shells; overrides = { inherit another-shell; }; alias = { default = "another-shell"; }; } + ## ``` + ## Result: + ## ```nix + ## { another-shell = ...; my-shell = ...; default = ...; } + ## ``` + #@ Attrs -> Attrs create-shells = { channels , src ? user-shells-root diff --git a/snowfall-lib/system/default.nix b/snowfall-lib/system/default.nix index 6d9bfa5..5e3e345 100644 --- a/snowfall-lib/system/default.nix +++ b/snowfall-lib/system/default.nix @@ -15,39 +15,69 @@ let in { system = rec { - # Get the name of a system based on its file path. - # Type: Path -> String - # Usage: get-inferred-system-name "/systems/my-system/default.nix" - # result: "my-system" + ## 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. - # Type: String -> Bool - # Usage: is-darwin "x86_64-linux" - # result: false + ## 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. - # Type: String -> Bool - # Usage: is-linux "x86_64-linux" - # result: false + ## 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. - # Type: String -> Bool - # Usage: is-virtual "x86_64-iso" - # result: true + ## 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. - # Type: String -> String - # Usage: get-virtual-system-type "x86_64-iso" - # result: "iso" + ## 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: @@ -59,10 +89,16 @@ in "" virtual-systems; - # Get structured data about all systems for a given target. - # Type: String -> [Attrs] - # Usage: get-target-systems-metadata "x86_64-linux" - # result: [ { target = "x86_64-linux"; name = "my-machine"; path = "/systems/x86_64-linux/my-machine"; } ] + ## 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 systems = snowfall-lib.fs.get-directories target; @@ -82,10 +118,16 @@ in in system-configurations; - # Get the system builder for a given target. - # Type: String -> Function - # Usage: get-system-builder "x86_64-iso" - # result: (args: ) + ## 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; @@ -130,10 +172,16 @@ in else linux-system-builder; - # Get the flake output attribute for a system target. - # Type: String -> String - # Usage: get-system-output "aarch64-darwin" - # result: "darwinConfigurations" + ## 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; @@ -145,10 +193,16 @@ in else "nixosConfigurations"; - # Get the resolved (non-virtual) system target. - # Type: String -> String - # Usage: get-resolved-system-target "x86_64-iso" - # result: "x86_64-linux" + ## 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; @@ -158,10 +212,16 @@ in else target; - # Create a system. - # Type: Attrs -> Attrs - # Usage: create-system { path = ./systems/my-system; } - # result: + ## 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 @@ -199,10 +259,16 @@ in }; }; - # Create all available systems. - # Type: Attrs -> Attrs - # Usage: create-systems { hosts.my-host.specialArgs.x = true; modules.nixos = [ my-shared-module ]; } - # result: { my-host = ; } + ## 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; diff --git a/snowfall-lib/template/default.nix b/snowfall-lib/template/default.nix index 6527c3a..40099e7 100644 --- a/snowfall-lib/template/default.nix +++ b/snowfall-lib/template/default.nix @@ -12,10 +12,18 @@ let in { template = { - # Create flake templates. - # Type: Attrs -> Attrs - # Usage: create-templates { src = ./my-templates; overrides = { inherit another-template; }; alias = { default = "another-template"; }; } - # result: { another-template = ...; my-template = ...; default = ...; } + ## Create flake templates. + ## + ## Example Usage: + ## ```nix + ## create-templates { src = ./my-templates; overrides = { inherit another-template; }; alias = { default = "another-template"; }; } + ## ``` + ## + ## Result: + ## ```nix + ## { another-template = ...; my-template = ...; default = ...; } + ## ``` + #@ Attrs -> Attrs create-templates = { src ? user-templates-root , overrides ? { } From 2261cb3d2c642f337006696bde1dc59a3b905421 Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Thu, 17 Aug 2023 00:34:38 -0700 Subject: [PATCH 23/26] docs: fix typo --- snowfall-lib/fp/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snowfall-lib/fp/default.nix b/snowfall-lib/fp/default.nix index 83b7c74..04dd03c 100644 --- a/snowfall-lib/fp/default.nix +++ b/snowfall-lib/fp/default.nix @@ -49,7 +49,7 @@ in ## Apply an argument to a function. ## Example Usage: ## ```nix - ## call (x: x + 1) 0 + ## apply 0 (x: x + 1) ## ``` ## Result: ## ```nix From 4d1333417926fc007bb4805a72176c7ada47fc85 Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Thu, 17 Aug 2023 01:02:50 -0700 Subject: [PATCH 24/26] feat: support universal namespace --- snowfall-lib/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snowfall-lib/default.nix b/snowfall-lib/default.nix index 988142c..4b4b70d 100644 --- a/snowfall-lib/default.nix +++ b/snowfall-lib/default.nix @@ -100,7 +100,7 @@ let attrs = { inherit (user-options) inputs; snowfall-inputs = core-inputs; - lib = merge-shallow [ base-lib { internal = user-lib; } ]; + lib = merge-shallow [ base-lib { ${snowfall-config.namespace} = user-lib; } ]; }; libs = builtins.map (path: callPackageWith attrs path { }) From 9be6d6714e51a4406e681f9a1d6e1192544f35e3 Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Thu, 17 Aug 2023 01:10:55 -0700 Subject: [PATCH 25/26] fix: use package namespace for overlays builder --- snowfall-lib/flake/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snowfall-lib/flake/default.nix b/snowfall-lib/flake/default.nix index 223762e..afd037e 100644 --- a/snowfall-lib/flake/default.nix +++ b/snowfall-lib/flake/default.nix @@ -171,7 +171,7 @@ rec { channelsConfig = full-flake-options.channels-config or { }; channels.nixpkgs.overlaysBuilder = snowfall-lib.overlay.create-overlays-builder { - package-namespace = full-flake-options.package-namespace or null; + inherit package-namespace; extra-overlays = full-flake-options.overlays or [ ]; }; From 32b5448e283b9ede9f88b393be31404e33099689 Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Thu, 17 Aug 2023 01:12:57 -0700 Subject: [PATCH 26/26] fix: enable user in standalone home-manager by default --- snowfall-lib/home/default.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/snowfall-lib/home/default.nix b/snowfall-lib/home/default.nix index e5cac40..e8d1844 100644 --- a/snowfall-lib/home/default.nix +++ b/snowfall-lib/home/default.nix @@ -133,7 +133,10 @@ in inherit user-inputs core-inputs; })) ({ - snowfallorg.user.name = mkDefault user-metadata.user; + snowfallorg.user = { + name = mkDefault user-metadata.user; + enable = mkDefault true; + }; }) ];