feat: aliases and custom snowfall root

This commit is contained in:
Jake Hamilton 2023-01-09 05:22:28 -08:00
parent d8a08681a9
commit cbe1b6e0fb
No known key found for this signature in database
GPG key ID: 9762169A1B35EA68
9 changed files with 126 additions and 85 deletions

View file

@ -81,6 +81,10 @@ library instance with `mkLib`.
# your flake. # your flake.
inherit inputs; inherit inputs;
src = ./.; src = ./.;
# You can optionally place your Snowfall-related files in another
# directory.
snowfall.root = ./nix;
}; };
in in
# We'll cover what to do here next. # We'll cover what to do here next.
@ -100,6 +104,10 @@ let
lib = inputs.snowfall-lib.mkLib { lib = inputs.snowfall-lib.mkLib {
inherit inputs; inherit inputs;
src = ./.; src = ./.;
# You can optionally place your Snowfall-related files in another
# directory.
snowfall.root = ./nix;
}; };
in lib.mkFlake { 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. 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. │ Your Nix flake.
├─ flake.nix ├─ flake.nix
@ -383,7 +394,7 @@ on `pkgs` and consumers of your flake can use the generated `<your-flake>.overla
Snowfall Lib will create packages and shells based on your `packages/` and `shells` 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 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. mapping the `default` package or shell to the name of the one you want.
```nix ```nix
@ -411,16 +422,22 @@ mapping the `default` package or shell to the name of the one you want.
}; };
in in
lib.mkFlake { lib.mkFlake {
# You can also pass through external packages or dynamically create new ones alias = {
# in addition to the ones that `lib` will create from your `packages/` directory.
outputs-builder = channels: {
packages = { packages = {
default = "my-package"; default = "my-package";
}; };
devShells = { shells = {
default = "my-shell"; default = "my-shell";
}; };
modules = {
default = "my-module";
};
templates = {
default = "my-template";
};
}; };
}; };
} }
@ -742,6 +759,24 @@ Result:
"/user-source/systems" "/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` #### `lib.snowfall.fs.internal-get-file`
Get a file relative to the Snowfall Lib flake. You probably shouldn't use this! 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" ] [ "./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` ### `lib.snowfall.attrs`
Utilities for working with attribute sets. Utilities for working with attribute sets.
@ -1226,7 +1283,7 @@ Type: `Attrs -> Attrs`
Usage: Usage:
```nix ```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: Result:
@ -1248,7 +1305,7 @@ Type: `Attrs -> Attrs`
Usage: Usage:
```nix ```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: Result:
@ -1321,7 +1378,7 @@ Type: `Attrs -> Attrs`
Usage: Usage:
```nix ```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: Result:

View file

@ -46,6 +46,7 @@ rec {
"channels-config" "channels-config"
"templates" "templates"
"overlay-package-namespace" "overlay-package-namespace"
"alias"
]; ];
# Transform an attribute set of inputs into an attribute set where # Transform an attribute set of inputs into an attribute set where
@ -70,13 +71,16 @@ rec {
mkFlake = full-flake-options: mkFlake = full-flake-options:
let let
custom-flake-options = flake.without-snowfall-options full-flake-options; 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 { }); systems = snowfall-lib.system.create-systems (full-flake-options.systems or { });
hosts = snowfall-lib.attrs.merge-shallow [ (full-flake-options.systems.hosts or { }) systems ]; hosts = snowfall-lib.attrs.merge-shallow [ (full-flake-options.systems.hosts or { }) systems ];
templates = snowfall-lib.template.create-templates { templates = snowfall-lib.template.create-templates {
overrides = (full-flake-options.templates or { }); overrides = (full-flake-options.templates or { });
alias = alias.templates or { };
}; };
modules = snowfall-lib.module.create-modules { modules = snowfall-lib.module.create-modules {
overrides = (full-flake-options.modules or { }); overrides = (full-flake-options.modules or { });
alias = alias.modules or { };
}; };
overlays = snowfall-lib.overlay.create-overlays { overlays = snowfall-lib.overlay.create-overlays {
overlay-package-namespace = full-flake-options.overlay-package-namespace or null; overlay-package-namespace = full-flake-options.overlay-package-namespace or null;
@ -93,10 +97,12 @@ rec {
packages = snowfall-lib.package.create-packages { packages = snowfall-lib.package.create-packages {
inherit channels; inherit channels;
overrides = (full-flake-options.packages or { }) // (user-outputs.packages or { }); overrides = (full-flake-options.packages or { }) // (user-outputs.packages or { });
alias = alias.packages or { };
}; };
shells = snowfall-lib.shell.create-shells { shells = snowfall-lib.shell.create-shells {
inherit channels; inherit channels;
overrides = (full-flake-options.shells or { }) // (user-outputs.devShells or { }); overrides = (full-flake-options.shells or { }) // (user-outputs.devShells or { });
alias = alias.shells or { };
}; };
outputs = { outputs = {

View file

@ -27,6 +27,12 @@ in
# result: "/user-source/systems" # result: "/user-source/systems"
get-file = path: "${user-inputs.src}/${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-snowfall-file = path: "${user-inputs.snowfall.root or user-inputs.src}/${path}";
# Get a file path relative to the this flake. # Get a file path relative to the this flake.
# Type: Path -> Path # Type: Path -> Path
# Usage: get-file "systems" # Usage: get-file "systems"
@ -41,7 +47,7 @@ in
if pathExists path then if pathExists path then
readDir path readDir path
else else
{}; { };
# Get directories at a given path. # Get directories at a given path.
# Type: Path -> [Path] # Type: Path -> [Path]
@ -52,7 +58,7 @@ in
entries = safe-read-directory path; entries = safe-read-directory path;
filtered-entries = filterAttrs (name: kind: is-directory-kind kind) entries; filtered-entries = filterAttrs (name: kind: is-directory-kind kind) entries;
in in
mapAttrsToList (name: kind: "${path}/${name}") filtered-entries; mapAttrsToList (name: kind: "${path}/${name}") filtered-entries;
# Get files at a given path. # Get files at a given path.
# Type: Path -> [Path] # Type: Path -> [Path]
@ -63,7 +69,7 @@ in
entries = safe-read-directory path; entries = safe-read-directory path;
filtered-entries = filterAttrs (name: kind: is-file-kind kind) entries; filtered-entries = filterAttrs (name: kind: is-file-kind kind) entries;
in 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. # Get files at a given path, traversing any directories within.
# Type: Path -> [Path] # Type: Path -> [Path]
@ -79,7 +85,8 @@ in
map-file = name: kind: map-file = name: kind:
let let
path' = "${path}/${name}"; path' = "${path}/${name}";
in if is-directory-kind kind then in
if is-directory-kind kind then
get-files-recursive path' get-files-recursive path'
else else
path'; path';
@ -122,8 +129,8 @@ in
# result: [ "./something/some-directory/default.nix" ] # result: [ "./something/some-directory/default.nix" ]
get-default-nix-files-recursive = path: get-default-nix-files-recursive = path:
builtins.filter builtins.filter
(name: builtins.baseNameOf name == "default.nix") (name: builtins.baseNameOf name == "default.nix")
(get-files-recursive path); (get-files-recursive path);
# Get nix files at a given path not named "default.nix". # Get nix files at a given path not named "default.nix".
# Type: Path -> [Path] # Type: Path -> [Path]
@ -144,10 +151,10 @@ in
# result: [ "./something/some-directory/a.nix" ] # result: [ "./something/some-directory/a.nix" ]
get-non-default-nix-files-recursive = path: get-non-default-nix-files-recursive = path:
builtins.filter builtins.filter
(name: (name:
(snowfall-lib.path.has-file-extension "nix" name) (snowfall-lib.path.has-file-extension "nix" name)
&& (builtins.baseNameOf name != "default.nix") && (builtins.baseNameOf name != "default.nix")
) )
(get-files-recursive path); (get-files-recursive path);
}; };
} }

View file

@ -5,19 +5,20 @@
let let
inherit (builtins) baseNameOf; 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 in
{ {
module = { module = {
# Create flake output modules. # Create flake output modules.
# Type: Attrs -> Attrs # 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 = ...; } # result: { another-module = ...; my-module = ...; default = ...; }
create-modules = create-modules =
{ src ? user-modules-root { src ? user-modules-root
, overrides ? { } , overrides ? { }
, alias ? { }
}: }:
let let
user-modules = snowfall-lib.fs.get-default-nix-files-recursive src; user-modules = snowfall-lib.fs.get-default-nix-files-recursive src;
@ -30,18 +31,9 @@ in
modules // { modules // {
${metadata.name} = import metadata.path; ${metadata.name} = import metadata.path;
}; };
modules-without-default = foldl merge-modules { } modules-metadata; modules-without-aliases = foldl merge-modules { } modules-metadata;
default-module = aliased-modules = mapAttrs (name: value: modules-without-aliases.${value}) alias;
if overrides.default or null == null then modules = modules-without-aliases // aliased-modules // overrides;
{ }
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;
in in
modules; modules;
}; };

View file

@ -6,8 +6,8 @@
let let
inherit (core-inputs.nixpkgs.lib) assertMsg foldl concatStringsSep; inherit (core-inputs.nixpkgs.lib) assertMsg foldl concatStringsSep;
user-overlays-root = snowfall-lib.fs.get-file "overlays"; user-overlays-root = snowfall-lib.fs.get-snowfall-file "overlays";
user-packages-root = snowfall-lib.fs.get-file "packages"; user-packages-root = snowfall-lib.fs.get-snowfall-file "packages";
in in
{ {
overlay = { overlay = {

View file

@ -5,21 +5,22 @@
let let
inherit (core-inputs.flake-utils-plus.lib) filterPackages; 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 in
{ {
package = { package = {
# Create flake output packages. # Create flake output packages.
# Type: Attrs -> Attrs # 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 = ...; } # result: { another-package = ...; my-package = ...; default = ...; }
create-packages = create-packages =
{ channels { channels
, src ? user-packages-root , src ? user-packages-root
, pkgs ? channels.nixpkgs , pkgs ? channels.nixpkgs
, overrides ? { } , overrides ? { }
, alias ? { }
}: }:
let let
user-packages = snowfall-lib.fs.get-default-nix-files-recursive src; user-packages = snowfall-lib.fs.get-default-nix-files-recursive src;
@ -36,18 +37,9 @@ in
packages // { packages // {
${metadata.name} = metadata.drv; ${metadata.name} = metadata.drv;
}; };
packages-without-default = foldl merge-packages { } packages-metadata; packages-without-aliases = foldl merge-packages { } packages-metadata;
default-package = aliased-packages = mapAttrs (name: value: packages-without-aliases.${value}) alias;
if overrides.default or null == null then packages = packages-without-aliases // aliased-packages // overrides;
{ }
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;
in in
filterPackages pkgs.system packages; filterPackages pkgs.system packages;
}; };

View file

@ -4,20 +4,22 @@
}: }:
let 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 in
{ {
shell = { shell = {
# Create flake output packages. # Create flake output packages.
# Type: Attrs -> Attrs # 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 = ...; } # result: { another-shell = ...; my-shell = ...; default = ...; }
create-shells = create-shells =
{ channels { channels
, src ? user-shells-root , src ? user-shells-root
, overrides ? { } , overrides ? { }
, alias ? { }
}: }:
let let
user-shells = snowfall-lib.fs.get-default-nix-files-recursive src; user-shells = snowfall-lib.fs.get-default-nix-files-recursive src;
@ -35,19 +37,12 @@ in
shells // { shells // {
${metadata.name} = metadata.drv; ${metadata.name} = metadata.drv;
}; };
shells-without-default = foldl merge-shells { } shells-metadata; shells-without-aliases = foldl merge-shells { } shells-metadata;
default-shell = aliased-shells = mapAttrs (name: value: shells-without-aliases.${value}) alias;
if overrides.default or null == null then shells = shells-without-aliases // aliased-shells // overrides;
{ }
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;
in in
shells; filterPackages
channels.nixpkgs.system
shells;
}; };
} }

View file

@ -9,8 +9,8 @@ let
virtual-systems = import ./virtual-systems.nix; virtual-systems = import ./virtual-systems.nix;
user-systems-root = snowfall-lib.fs.get-file "systems"; user-systems-root = snowfall-lib.fs.get-snowfall-file "systems";
user-modules-root = snowfall-lib.fs.get-file "modules"; user-modules-root = snowfall-lib.fs.get-snowfall-file "modules";
get-inferred-system-name = path: get-inferred-system-name = path:
if snowfall-lib.path.has-file-extension "nix" path then if snowfall-lib.path.has-file-extension "nix" path then

View file

@ -5,19 +5,20 @@
let let
inherit (builtins) baseNameOf; 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 in
{ {
template = { template = {
# Create flake templates. # Create flake templates.
# Type: Attrs -> Attrs # 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 = ...; } # result: { another-template = ...; my-template = ...; default = ...; }
create-templates = create-templates =
{ src ? user-templates-root { src ? user-templates-root
, overrides ? { } , overrides ? { }
, alias ? { }
}: }:
let let
user-templates = snowfall-lib.fs.get-directories src; user-templates = snowfall-lib.fs.get-directories src;
@ -32,18 +33,9 @@ in
inherit (metadata) path; inherit (metadata) path;
}; };
}; };
templates-without-default = foldl merge-templates { } templates-metadata; templates-without-aliases = foldl merge-templates { } templates-metadata;
default-template = aliased-templates = mapAttrs (name: value: templates-without-aliases.${value}) alias;
if overrides.default or null == null then templates = templates-without-aliases // aliased-templates // overrides;
{ }
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;
in in
templates; templates;
}; };