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.
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 `<your-flake>.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:

View file

@ -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 = {

View file

@ -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);
};
}

View file

@ -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;
};

View file

@ -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 = {

View file

@ -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;
};

View file

@ -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;
};
}

View file

@ -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

View file

@ -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;
};