style: fmt

This commit is contained in:
anntnzrb
2025-10-08 21:56:09 -05:00
parent 592bb5148d
commit 9bd2ffc288
21 changed files with 1509 additions and 1308 deletions

View File

@@ -1,6 +1,4 @@
(
import
(
(import (
let
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
in
@@ -8,7 +6,4 @@
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash;
}
)
{src = ./.;}
)
.defaultNix
) { src = ./.; }).defaultNix

View File

@@ -11,13 +11,13 @@
};
};
outputs = {
outputs =
{
self,
...
} @ inputs: let
core-inputs =
inputs
// {
}@inputs:
let
core-inputs = inputs // {
src = self;
};
@@ -31,19 +31,25 @@
# A convenience wrapper to create the library and then call `lib.mkFlake`.
# Usage: mkFlake { inherit inputs; src = ./.; ... }
# result: <flake-outputs>
mkFlake = flake-and-lib-options @ {
mkFlake =
flake-and-lib-options@{
inputs,
src,
snowfall ? {},
snowfall ? { },
...
}: let
}:
let
lib = mkLib {
inherit inputs src snowfall;
};
flake-options = builtins.removeAttrs flake-and-lib-options ["inputs" "src"];
flake-options = builtins.removeAttrs flake-and-lib-options [
"inputs"
"src"
];
in
lib.mkFlake flake-options;
in {
in
{
inherit mkLib mkFlake;
nixosModules = {
@@ -80,20 +86,17 @@
};
};
internal-lib = let
internal-lib =
let
lib = mkLib {
src = self;
inputs =
inputs
// {
self = {};
inputs = inputs // {
self = { };
};
};
in
builtins.removeAttrs
lib.snowfall
["internal"];
builtins.removeAttrs lib.snowfall [ "internal" ];
};
};
}

View File

@@ -5,9 +5,9 @@
config,
inputs,
...
}: let
inherit
(lib)
}:
let
inherit (lib)
types
mkOption
mkDefault
@@ -20,7 +20,9 @@
user-names = builtins.attrNames cfg.users;
create-system-users = system-users: name: let
create-system-users =
system-users: name:
let
user = cfg.users.${name};
in
system-users
@@ -30,16 +32,20 @@
isHidden = mkDefault false;
};
});
in {
in
{
imports = [
(mkRenamedOptionModule ["snowfallorg" "user"] ["snowfallorg" "users"])
(mkRenamedOptionModule [ "snowfallorg" "user" ] [ "snowfallorg" "users" ])
];
options.snowfallorg = {
users = mkOption {
description = "User configuration.";
default = {};
type = types.attrsOf (types.submodule ({name, ...}: {
default = { };
type = types.attrsOf (
types.submodule (
{ name, ... }:
{
options = {
create = mkOption {
description = "Whether to create the user automatically.";
@@ -62,19 +68,19 @@ in {
# HM-compatible options taken from:
# https://github.com/nix-community/home-manager/blob/0ee5ab611dc1fbb5180bd7d88d2aeb7841a4d179/nixos/common.nix#L14
type = types.submoduleWith {
specialArgs =
{
specialArgs = {
osConfig = config;
modulesPath = "${inputs.home-manager}/modules";
}
// config.home-manager.extraSpecialArgs;
modules =
[
({
modules = [
(
{
lib,
modulesPath,
...
}: {
}:
{
imports = import "${modulesPath}/modules.nix" {
inherit pkgs lib;
useNixpkgsModule = !config.home-manager.useGlobalPkgs;
@@ -89,18 +95,21 @@ in {
nix.package = config.nix.package;
};
})
}
)
]
++ config.home-manager.sharedModules;
};
};
};
};
}));
}
)
);
};
};
config = {
users.users = foldl create-system-users {} user-names;
users.users = foldl create-system-users { } user-names;
};
}

View File

@@ -1,11 +1,17 @@
inputs @ {
inputs@{
pkgs,
lib,
options,
config,
...
}: let
inherit (lib) types mkOption mkIf mkDefault;
}:
let
inherit (lib)
types
mkOption
mkIf
mkDefault
;
cfg = config.snowfallorg;
@@ -16,12 +22,14 @@ inputs @ {
has-user-name = (cfg.user.name or null) != 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 {
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
{
options.snowfallorg = {
user = {
enable = mkOption {

View File

@@ -1,12 +1,12 @@
args @ {
args@{
pkgs,
lib,
options,
config,
...
}: let
inherit
(lib)
}:
let
inherit (lib)
types
mkOption
mkDefault
@@ -18,11 +18,13 @@ args @ {
cfg = config.snowfallorg;
inputs = args.inputs or {};
inputs = args.inputs or { };
user-names = builtins.attrNames cfg.users;
create-system-users = system-users: name: let
create-system-users =
system-users: name:
let
user = cfg.users.${name};
in
system-users
@@ -38,16 +40,20 @@ args @ {
extraGroups = optional user.admin "wheel";
};
});
in {
in
{
imports = [
(mkRenamedOptionModule ["snowfallorg" "user"] ["snowfallorg" "users"])
(mkRenamedOptionModule [ "snowfallorg" "user" ] [ "snowfallorg" "users" ])
];
options.snowfallorg = {
users = mkOption {
description = "User configuration.";
default = {};
type = types.attrsOf (types.submodule ({name, ...}: {
default = { };
type = types.attrsOf (
types.submodule (
{ name, ... }:
{
options = {
create = mkOption {
description = "Whether to create the user automatically.";
@@ -78,21 +84,20 @@ in {
# NOTE: This has been adapted to support documentation generation without
# having home-manager options fully declared.
type = types.submoduleWith {
specialArgs =
{
specialArgs = {
osConfig = config;
modulesPath = "${inputs.home-manager or "/"}/modules";
}
// (config.home-manager.extraSpecialArgs or {});
modules =
[
({
// (config.home-manager.extraSpecialArgs or { });
modules = [
(
{
lib,
modulesPath,
...
}:
if inputs ? home-manager
then {
if inputs ? home-manager then
{
imports = import "${modulesPath}/modules.nix" {
inherit pkgs lib;
useNixpkgsModule = !(config.home-manager.useGlobalPkgs or false);
@@ -108,18 +113,22 @@ in {
nix.package = config.nix.package;
};
}
else {})
else
{ }
)
]
++ (config.home-manager.sharedModules or []);
++ (config.home-manager.sharedModules or [ ]);
};
};
};
};
}));
}
)
);
};
};
config = {
users.users = foldl create-system-users {} user-names;
users.users = foldl create-system-users { } user-names;
};
}

View File

@@ -3,9 +3,9 @@
user-inputs,
snowfall-lib,
snowfall-config,
}: let
inherit
(core-inputs.nixpkgs.lib)
}:
let
inherit (core-inputs.nixpkgs.lib)
assertMsg
mapAttrsToList
mapAttrs
@@ -15,7 +15,8 @@
mergeAttrs
isDerivation
;
in {
in
{
attrs = {
## Map and flatten an attribute set into a list.
## Example Usage:
@@ -27,8 +28,7 @@ in {
## [ "x" 1 "y" 2 ]
## ```
#@ (a -> b -> [c]) -> Attrs -> [c]
map-concat-attrs-to-list = f: attrs:
flatten (mapAttrsToList f attrs);
map-concat-attrs-to-list = f: attrs: flatten (mapAttrsToList f attrs);
## Recursively merge a list of attribute sets.
## Example Usage:
@@ -40,7 +40,7 @@ in {
## { x = 2; }
## ```
#@ [Attrs] -> Attrs
merge-deep = foldl recursiveUpdate {};
merge-deep = foldl recursiveUpdate { };
## Merge the root of a list of attribute sets.
## Example Usage:
@@ -52,7 +52,7 @@ in {
## { x = 2; }
## ```
#@ [Attrs] -> Attrs
merge-shallow = foldl mergeAttrs {};
merge-shallow = foldl mergeAttrs { };
## Merge shallow for packages, but allow one deeper layer of attribute sets.
## Example Usage:
@@ -64,23 +64,20 @@ in {
## { vim = ...; some.value = false; }
## ```
#@ [Attrs] -> Attrs
merge-shallow-packages = items:
foldl
(
merge-shallow-packages =
items:
foldl (
result: item:
result
// (mapAttrs
(
// (mapAttrs (
name: value:
if isDerivation value
then value
else if builtins.isAttrs value
then (result.${name} or {}) // value
else value
)
item)
)
{}
items;
if isDerivation value then
value
else if builtins.isAttrs value then
(result.${name} or { }) // value
else
value
) item)
) { } items;
};
}

View File

@@ -3,12 +3,19 @@
user-inputs,
snowfall-lib,
snowfall-config,
}: let
}:
let
inherit (core-inputs.flake-utils-plus.lib) filterPackages;
inherit (core-inputs.nixpkgs.lib) assertMsg foldl mapAttrs callPackageWith;
inherit (core-inputs.nixpkgs.lib)
assertMsg
foldl
mapAttrs
callPackageWith
;
user-checks-root = snowfall-lib.fs.get-snowfall-file "checks";
in {
in
{
check = {
## Create flake output packages.
## Example Usage:
@@ -20,34 +27,38 @@ in {
## { another-check = ...; my-check = ...; default = ...; }
## ```
#@ Attrs -> Attrs
create-checks = {
create-checks =
{
channels,
src ? user-checks-root,
pkgs ? channels.nixpkgs,
overrides ? {},
alias ? {},
}: let
overrides ? { },
alias ? { },
}:
let
user-checks = snowfall-lib.fs.get-default-nix-files-recursive src;
create-check-metadata = check: let
extra-inputs =
pkgs
// {
create-check-metadata =
check:
let
extra-inputs = pkgs // {
inherit channels;
lib = snowfall-lib.internal.system-lib;
inputs = snowfall-lib.flake.without-src user-inputs;
namespace = snowfall-config.namespace;
};
in {
in
{
name = builtins.unsafeDiscardStringContext (snowfall-lib.path.get-parent-directory check);
drv = callPackageWith extra-inputs check {};
drv = callPackageWith extra-inputs check { };
};
checks-metadata = builtins.map create-check-metadata user-checks;
merge-checks = checks: metadata:
merge-checks =
checks: metadata:
checks
// {
${metadata.name} = metadata.drv;
};
checks-without-aliases = foldl merge-checks {} checks-metadata;
checks-without-aliases = foldl merge-checks { } checks-metadata;
aliased-checks = mapAttrs (name: value: checks-without-aliases.${value}) alias;
checks = checks-without-aliases // aliased-checks // overrides;
in

View File

@@ -2,11 +2,10 @@
# Snowfall library. There is some duplication shared between this
# file and the library itself due to the library needing to pass through
# another extended library for its own applications.
core-inputs: user-options: let
raw-snowfall-config = user-options.snowfall or {};
snowfall-config =
raw-snowfall-config
// {
core-inputs: 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";
@@ -16,21 +15,32 @@ core-inputs: user-options: let
};
};
user-inputs = user-options.inputs // {src = user-options.src;};
user-inputs = user-options.inputs // {
src = user-options.src;
};
inherit (core-inputs.nixpkgs.lib) assertMsg fix filterAttrs mergeAttrs fold recursiveUpdate callPackageWith isFunction;
inherit (core-inputs.nixpkgs.lib)
assertMsg
fix
filterAttrs
mergeAttrs
fold
recursiveUpdate
callPackageWith
isFunction
;
# Recursively merge a list of attribute sets.
# Type: [Attrs] -> Attrs
# Usage: merge-deep [{ x = 1; } { x = 2; }]
# result: { x = 2; }
merge-deep = fold recursiveUpdate {};
merge-deep = fold recursiveUpdate { };
# Merge the root of a list of attribute sets.
# Type: [Attrs] -> Attrs
# Usage: merge-shallow [{ x = 1; } { x = 2; }]
# result: { x = 2; }
merge-shallow = fold mergeAttrs {};
merge-shallow = fold mergeAttrs { };
# Transform an attribute set of inputs into an attribute set where
# the values are the inputs' `lib` attribute. Entries without a `lib`
@@ -38,14 +48,12 @@ core-inputs: user-options: let
# Type: Attrs -> Attrs
# Usage: get-lib { x = nixpkgs; y = {}; }
# result: { x = nixpkgs.lib; }
get-libs = attrs: let
get-libs =
attrs:
let
# @PERF(jakehamilton): Replace filter+map with a fold.
attrs-with-libs =
filterAttrs
(name: value: builtins.isAttrs (value.lib or null))
attrs;
libs =
builtins.mapAttrs (name: input: input.lib) attrs-with-libs;
attrs-with-libs = filterAttrs (name: value: builtins.isAttrs (value.lib or null)) attrs;
libs = builtins.mapAttrs (name: input: input.lib) attrs-with-libs;
in
libs;
@@ -53,7 +61,7 @@ core-inputs: user-options: let
# Type: Attrs -> Attrs
# Usage: without-self { self = {}; x = true; }
# result: { x = true; }
without-self = attrs: builtins.removeAttrs attrs ["self"];
without-self = attrs: builtins.removeAttrs attrs [ "self" ];
core-inputs-libs = get-libs (without-self core-inputs);
user-inputs-libs = get-libs (without-self user-inputs);
@@ -61,7 +69,8 @@ core-inputs: user-options: let
# NOTE: This root is different to accommodate 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
snowfall-lib-dirs =
let
files = builtins.readDir snowfall-lib-root;
dirs = filterAttrs (name: kind: kind == "directory") files;
names = builtins.attrNames dirs;
@@ -69,14 +78,17 @@ core-inputs: user-options: let
names;
snowfall-lib = fix (
snowfall-lib: let
snowfall-lib:
let
attrs = {
inherit snowfall-lib snowfall-config core-inputs user-inputs;
inherit
snowfall-lib
snowfall-config
core-inputs
user-inputs
;
};
libs =
builtins.map
(dir: import "${snowfall-lib-root}/${dir}" attrs)
snowfall-lib-dirs;
libs = builtins.map (dir: import "${snowfall-lib-root}/${dir}" attrs) snowfall-lib-dirs;
in
merge-deep libs
);
@@ -88,32 +100,35 @@ core-inputs: user-options: let
core-inputs-libs
user-inputs-libs
snowfall-top-level-lib
{snowfall = snowfall-lib;}
{ snowfall = snowfall-lib; }
];
user-lib-root = "${user-inputs.src}/lib";
user-lib-modules = snowfall-lib.fs.get-default-nix-files-recursive user-lib-root;
user-lib = fix (
user-lib: let
user-lib:
let
attrs = {
inherit (user-options) inputs;
snowfall-inputs = core-inputs;
namespace = snowfall-config.namespace;
lib = merge-shallow [base-lib {${snowfall-config.namespace} = user-lib;}];
lib = merge-shallow [
base-lib
{ ${snowfall-config.namespace} = user-lib; }
];
};
libs =
builtins.map
(
path: let
libs = builtins.map (
path:
let
imported-module = import path;
in
if isFunction imported-module
then callPackageWith attrs path {}
if isFunction imported-module then
callPackageWith attrs path { }
# the only difference is that there is no `override` and `overrideDerivation` on returned value
else imported-module
)
user-lib-modules;
else
imported-module
) user-lib-modules;
in
merge-deep libs
);
@@ -126,5 +141,6 @@ core-inputs: user-options: 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

View File

@@ -3,9 +3,22 @@
user-inputs,
snowfall-lib,
snowfall-config,
}: let
inherit (core-inputs.nixpkgs.lib) assertMsg foldl filterAttrs const mapAttrs mapAttrs' hasSuffix removeSuffix nameValuePair traceVal;
in rec {
}:
let
inherit (core-inputs.nixpkgs.lib)
assertMsg
foldl
filterAttrs
const
mapAttrs
mapAttrs'
hasSuffix
removeSuffix
nameValuePair
traceVal
;
in
rec {
flake = rec {
## Remove the `self` attribute from an attribute set.
## Example Usage:
@@ -17,7 +30,7 @@ in rec {
## { x = true; }
## ```
#@ Attrs -> Attrs
without-self = flake-inputs: builtins.removeAttrs flake-inputs ["self"];
without-self = flake-inputs: builtins.removeAttrs flake-inputs [ "self" ];
## Remove the `src` attribute from an attribute set.
## Example Usage:
@@ -29,7 +42,7 @@ in rec {
## { x = true; }
## ```
#@ Attrs -> Attrs
without-src = flake-inputs: builtins.removeAttrs flake-inputs ["src"];
without-src = flake-inputs: builtins.removeAttrs flake-inputs [ "src" ];
## Remove the `src` and `self` attributes from an attribute set.
## Example Usage:
@@ -53,10 +66,9 @@ in rec {
## { x = true; }
## ```
#@ Attrs -> Attrs
without-snowfall-options = flake-options:
builtins.removeAttrs
flake-options
[
without-snowfall-options =
flake-options:
builtins.removeAttrs flake-options [
"systems"
"modules"
"overlays"
@@ -83,73 +95,77 @@ in rec {
## { x = nixpkgs.lib; }
## ```
#@ Attrs -> Attrs
get-libs = attrs: let
get-libs =
attrs:
let
# @PERF(jakehamilton): Replace filter+map with a fold.
attrs-with-libs =
filterAttrs
(name: value: builtins.isAttrs (value.lib or null))
attrs;
libs =
builtins.mapAttrs (name: input: input.lib) attrs-with-libs;
attrs-with-libs = filterAttrs (name: value: builtins.isAttrs (value.lib or null)) attrs;
libs = builtins.mapAttrs (name: input: input.lib) attrs-with-libs;
in
libs;
};
mkFlake = full-flake-options: let
mkFlake =
full-flake-options:
let
namespace = 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 {});
alias = full-flake-options.alias or { };
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 {};
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];
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 {};
overrides = full-flake-options.templates or { };
alias = alias.templates 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 {};
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 {};
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 {};
overrides = full-flake-options.modules.home or { };
alias = alias.modules.home or { };
};
overlays = snowfall-lib.overlay.create-overlays {
inherit namespace;
extra-overlays = full-flake-options.extra-exported-overlays or {};
extra-overlays = full-flake-options.extra-exported-overlays or { };
};
channels = full-flake-options.channels or {};
channels = full-flake-options.channels or { };
outputs-builder = channels: let
outputs-builder =
channels:
let
user-outputs-builder =
full-flake-options.outputs-builder
or full-flake-options.outputsBuilder
or (const {});
full-flake-options.outputs-builder or full-flake-options.outputsBuilder or (const { });
user-outputs = user-outputs-builder channels;
packages = snowfall-lib.package.create-packages {
inherit channels namespace;
overrides = (full-flake-options.packages or {}) // (user-outputs.packages or {});
alias = alias.packages or {};
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 {};
overrides = (full-flake-options.shells or { }) // (user-outputs.devShells or { });
alias = alias.shells or { };
};
checks = snowfall-lib.check.create-checks {
inherit channels;
overrides = (full-flake-options.checks or {}) // (user-outputs.checks or {});
alias = alias.checks or {};
overrides = (full-flake-options.checks or { }) // (user-outputs.checks or { });
alias = alias.checks or { };
};
outputs = {
@@ -158,11 +174,12 @@ in rec {
devShells = shells;
};
in
snowfall-lib.attrs.merge-deep [user-outputs outputs];
snowfall-lib.attrs.merge-deep [
user-outputs
outputs
];
flake-options =
custom-flake-options
// {
flake-options = custom-flake-options // {
inherit hosts templates;
inherit (user-inputs) self;
@@ -173,38 +190,31 @@ in rec {
darwinModules = darwin-modules;
homeModules = home-modules;
channelsConfig =
full-flake-options.channels-config
or full-flake-options.channelsConfig
or {};
channelsConfig = full-flake-options.channels-config or full-flake-options.channelsConfig or { };
channels =
mapAttrs
(channel: config:
channels = mapAttrs (
channel: config:
config
// {
overlaysBuilder = snowfall-lib.overlay.create-overlays-builder {
inherit namespace;
extra-overlays = full-flake-options.overlays or [];
extra-overlays = full-flake-options.overlays or [ ];
};
})
({nixpkgs = {};} // channels);
}
) ({ nixpkgs = { }; } // channels);
outputsBuilder = outputs-builder;
snowfall = {
config = snowfall-config;
raw-config = full-flake-options.snowfall or {};
raw-config = full-flake-options.snowfall or { };
user-lib = snowfall-lib.internal.user-lib;
};
};
flake-utils-plus-outputs =
core-inputs.flake-utils-plus.lib.mkFlake flake-options;
flake-utils-plus-outputs = core-inputs.flake-utils-plus.lib.mkFlake flake-options;
flake-outputs =
flake-utils-plus-outputs
// {
flake-outputs = flake-utils-plus-outputs // {
inherit overlays;
};
in
@@ -215,20 +225,20 @@ in rec {
// (builtins.listToAttrs (
builtins.map (system: {
name = system;
value =
flake-outputs.packages.${system}
// {
homeConfigurations = let
value = flake-outputs.packages.${system} // {
homeConfigurations =
let
homeNames = filterAttrs (_: home: home.system == system) homes;
homeConfigurations = mapAttrs (home-name: _: flake-outputs.homeConfigurations.${home-name}) homeNames;
renamedHomeConfigurations =
mapAttrs' (
homeConfigurations = mapAttrs (
home-name: _: flake-outputs.homeConfigurations.${home-name}
) homeNames;
renamedHomeConfigurations = mapAttrs' (
name: value:
if hasSuffix "@${system}" name
then nameValuePair (removeSuffix "@${system}" name) value
else nameValuePair name value
)
homeConfigurations;
if hasSuffix "@${system}" name then
nameValuePair (removeSuffix "@${system}" name) value
else
nameValuePair name value
) homeConfigurations;
in
renamedHomeConfigurations;
};

View File

@@ -3,10 +3,12 @@
user-inputs,
snowfall-lib,
snowfall-config,
}: let
}:
let
inherit (builtins) baseNameOf dirOf;
inherit (core-inputs.nixpkgs.lib) id foldr flip;
in {
in
{
fp = rec {
## Compose two functions.
## Example Usage:
@@ -18,7 +20,9 @@ in {
## (x: add-two (add-one x))
## ```
#@ (b -> c) -> (a -> b) -> a -> c
compose = f: g: x: f (g x);
compose =
f: g: x:
f (g x);
## Compose many functions.
## Example Usage:

View File

@@ -3,13 +3,20 @@
user-inputs,
snowfall-lib,
snowfall-config,
}: let
}:
let
inherit (builtins) readDir pathExists;
inherit (core-inputs) flake-utils-plus;
inherit (core-inputs.nixpkgs.lib) assertMsg filterAttrs mapAttrsToList flatten;
inherit (core-inputs.nixpkgs.lib)
assertMsg
filterAttrs
mapAttrsToList
flatten
;
file-name-regex = "(.*)\\.(.*)$";
in {
in
{
fs = rec {
## Matchers for file kinds. These are often used with `readDir`.
## Example Usage:
@@ -72,10 +79,7 @@ in {
## { "my-file.txt" = "regular"; }
## ```
#@ Path -> Attrs
safe-read-directory = path:
if pathExists path
then readDir path
else {};
safe-read-directory = path: if pathExists path then readDir path else { };
## Get directories at a given path.
## Example Usage:
@@ -87,7 +91,9 @@ in {
## [ "./something/a-directory" ]
## ```
#@ Path -> [Path]
get-directories = path: let
get-directories =
path:
let
entries = safe-read-directory path;
filtered-entries = filterAttrs (name: kind: is-directory-kind kind) entries;
in
@@ -103,7 +109,9 @@ in {
## [ "./something/a-file" ]
## ```
#@ Path -> [Path]
get-files = path: let
get-files =
path:
let
entries = safe-read-directory path;
filtered-entries = filterAttrs (name: kind: is-file-kind kind) entries;
in
@@ -119,22 +127,20 @@ in {
## [ "./something/some-directory/a-file" ]
## ```
#@ Path -> [Path]
get-files-recursive = path: let
get-files-recursive =
path:
let
entries = safe-read-directory path;
filtered-entries =
filterAttrs
(name: kind: (is-file-kind kind) || (is-directory-kind kind))
entries;
map-file = name: kind: let
filtered-entries = filterAttrs (
name: kind: (is-file-kind kind) || (is-directory-kind kind)
) entries;
map-file =
name: kind:
let
path' = "${path}/${name}";
in
if is-directory-kind kind
then get-files-recursive path'
else path';
files =
snowfall-lib.attrs.map-concat-attrs-to-list
map-file
filtered-entries;
if is-directory-kind kind then get-files-recursive path' else path';
files = snowfall-lib.attrs.map-concat-attrs-to-list map-file filtered-entries;
in
files;
@@ -148,10 +154,7 @@ in {
## [ "./something/a.nix" ]
## ```
#@ Path -> [Path]
get-nix-files = path:
builtins.filter
(snowfall-lib.path.has-file-extension "nix")
(get-files 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.
## Example Usage:
@@ -163,10 +166,8 @@ in {
## [ "./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-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".
## Example Usage:
@@ -178,10 +179,8 @@ in {
## [ "./something/default.nix" ]
## ```
#@ Path -> [Path]
get-default-nix-files = path:
builtins.filter
(name: builtins.baseNameOf name == "default.nix")
(get-files 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.
## Example Usage:
@@ -193,10 +192,8 @@ in {
## [ "./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-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".
## Example Usage:
@@ -208,14 +205,12 @@ in {
## [ "./something/a.nix" ]
## ```
#@ Path -> [Path]
get-non-default-nix-files = path:
builtins.filter
(
get-non-default-nix-files =
path:
builtins.filter (
name:
(snowfall-lib.path.has-file-extension "nix" name)
&& (builtins.baseNameOf name != "default.nix")
)
(get-files path);
(snowfall-lib.path.has-file-extension "nix" name) && (builtins.baseNameOf name != "default.nix")
) (get-files path);
## Get nix files at a given path not named "default.nix", traversing any directories within.
## Example Usage:
@@ -227,13 +222,11 @@ in {
## [ "./something/some-directory/a.nix" ]
## ```
#@ Path -> [Path]
get-non-default-nix-files-recursive = path:
builtins.filter
(
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);
(snowfall-lib.path.has-file-extension "nix" name) && (builtins.baseNameOf name != "default.nix")
) (get-files-recursive path);
};
}

View File

@@ -3,9 +3,9 @@
user-inputs,
snowfall-lib,
snowfall-config,
}: let
inherit
(core-inputs.nixpkgs.lib)
}:
let
inherit (core-inputs.nixpkgs.lib)
assertMsg
foldl
head
@@ -30,24 +30,26 @@
user-homes-root = snowfall-lib.fs.get-snowfall-file "homes";
user-modules-root = snowfall-lib.fs.get-snowfall-file "modules";
in {
in
{
home = rec {
# Modules in home-manager expect `hm` to be available directly on `lib` itself.
home-lib =
# NOTE: This prevents an error during evaluation if the input does
# not exist.
if user-inputs ? home-manager
then
snowfall-lib.internal.system-lib.extend
(final: prev:
if user-inputs ? home-manager then
snowfall-lib.internal.system-lib.extend (
final: prev:
# NOTE: This order is important, this library's extend and other utilities must write
# _over_ the original `system-lib`.
snowfall-lib.internal.system-lib
// prev
// {
hm = snowfall-lib.internal.system-lib.home-manager.hm;
})
else {};
}
)
else
{ };
## Get the user and host from a combined string.
## Example Usage:
@@ -59,16 +61,16 @@ in {
## { user = "myuser"; host = "myhost"; }
## ```
#@ String -> Attrs
split-user-and-host = target: let
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 {
host = if builtins.length name-parts > 1 then builtins.elemAt name-parts 1 else "";
in
{
inherit user host;
};
@@ -82,32 +84,36 @@ in {
## <flake-utils-plus-home-configuration>
## ```
#@ Attrs -> Attrs
create-home = {
create-home =
{
path,
name ? builtins.unsafeDiscardStringContext (snowfall-lib.system.get-inferred-system-name path),
modules ? [],
specialArgs ? {},
modules ? [ ],
specialArgs ? { },
channelName ? "nixpkgs",
system ? "x86_64-linux",
}: let
}:
let
user-metadata = split-user-and-host name;
unique-name =
if user-metadata.host == ""
then "${user-metadata.user}@${system}"
else name;
unique-name = if user-metadata.host == "" then "${user-metadata.user}@${system}" else name;
# NOTE: home-manager has trouble with `pkgs` recursion if it isn't passed in here.
pkgs = user-inputs.self.pkgs.${system}.${channelName} // {lib = home-lib;};
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 != "") || !(hasInfix "@" name)) "Snowfall Lib homes must be named with the format: user@system"; {
assert assertMsg (user-inputs ? home-manager)
"In order to create home-manager configurations, you must include `home-manager` as a flake input.";
assert assertMsg (
(user-metadata.host != "") || !(hasInfix "@" name)
) "Snowfall Lib homes must be named with the format: user@system";
{
inherit channelName system;
output = "homeConfigurations";
modules =
[
modules = [
path
../../modules/home/user/default.nix
]
@@ -127,20 +133,26 @@ in {
inherit pkgs lib;
};
builder = args:
user-inputs.home-manager.lib.homeManagerConfiguration
((builtins.removeAttrs args ["system" "specialArgs"])
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
modules = args.modules ++ [
(
module-args:
import ./nix-registry-module.nix (
module-args
// {
inherit user-inputs core-inputs;
}))
}
)
)
{
snowfallorg.user = {
name = mkDefault user-metadata.user;
@@ -150,7 +162,8 @@ in {
];
extraSpecialArgs = specialArgs // args.specialArgs;
});
}
);
};
## Get structured data about all homes for a given target.
@@ -163,10 +176,14 @@ in {
## [ { system = "x86_64-linux"; name = "my-home"; path = "/homes/x86_64-linux/my-home";} ]
## ```
#@ String -> [Attrs]
get-target-homes-metadata = target: let
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: let
create-home-metadata =
path:
let
# We are building flake outputs based on file contents. Nix doesn't like this
# so we have to explicitly discard the string's path context to allow us to
# use the name as a variable.
@@ -175,11 +192,9 @@ in {
# so we have to explicitly discard the string's path context to allow us to
# use the name as a variable.
system = builtins.unsafeDiscardStringContext (builtins.baseNameOf target);
name =
if !(hasInfix "@" basename)
then "${basename}@${system}"
else basename;
in {
name = if !(hasInfix "@" basename) then "${basename}@${system}" else basename;
in
{
path = "${path}/default.nix";
inherit name system;
};
@@ -197,7 +212,9 @@ in {
## { "my-user@my-system" = <flake-utils-plus-home-configuration>; }
## ```
#@ Attrs -> Attrs
create-homes = homes: let
create-homes =
homes:
let
targets = snowfall-lib.fs.get-directories user-homes-root;
target-homes-metadata = concatMap get-target-homes-metadata targets;
@@ -205,27 +222,34 @@ in {
src = "${user-modules-root}/home";
};
user-home-modules-list =
mapAttrsToList
(module-path: module: args @ {pkgs, ...}:
user-home-modules-list = mapAttrsToList (
module-path: module:
args@{ pkgs, ... }:
(module args)
// {
_file = "${user-homes-root}/${module-path}/default.nix";
})
user-home-modules;
}
) user-home-modules;
create-home' = home-metadata: let
create-home' =
home-metadata:
let
inherit (home-metadata) name;
overrides = homes.users.${name} or {};
in {
"${name}" = create-home (overrides
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 []);
});
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;
created-homes = foldl (
homes: home-metadata: homes // (create-home' home-metadata)
) { } target-homes-metadata;
in
created-homes;
@@ -239,26 +263,25 @@ in {
## [Module]
## ```
#@ Attrs -> [Module]
create-home-system-modules = users: let
create-home-system-modules =
users:
let
created-users = create-homes users;
user-home-modules = snowfall-lib.module.create-modules {
src = "${user-modules-root}/home";
};
shared-modules = builtins.map (module: {
config.home-manager.sharedModules = [module];
}) (users.modules or []);
config.home-manager.sharedModules = [ module ];
}) (users.modules or [ ]);
shared-user-modules =
mapAttrsToList
(module-path: module: {
shared-user-modules = mapAttrsToList (module-path: module: {
_file = "${user-modules-root}/home/${module-path}/default.nix";
config = {
home-manager.sharedModules = [module];
home-manager.sharedModules = [ module ];
};
})
user-home-modules;
}) user-home-modules;
snowfall-user-home-module = {
_file = "virtual:snowfallorg/modules/home/user/default.nix";
@@ -270,7 +293,8 @@ in {
};
};
extra-special-args-module = args @ {
extra-special-args-module =
args@{
config,
pkgs,
system ? pkgs.stdenv.hostPlatform.system,
@@ -278,14 +302,22 @@ in {
format ? "home",
host ? "",
virtual ? (snowfall-lib.system.is-virtual target),
systems ? {},
systems ? { },
...
}: {
}:
{
_file = "virtual:snowfallorg/home/extra-special-args";
config = {
home-manager.extraSpecialArgs = {
inherit system target format virtual systems host;
inherit
system
target
format
virtual
systems
host
;
inherit (snowfall-config) namespace;
lib = home-lib;
@@ -295,42 +327,36 @@ in {
};
};
system-modules =
builtins.map
(
name: let
system-modules = builtins.map (
name:
let
created-user = created-users.${name};
user-module = head created-user.modules;
other-modules = users.users.${name}.modules or [];
other-modules = users.users.${name}.modules or [ ];
user-name = created-user.specialArgs.user;
in
args @ {
args@{
config,
options,
pkgs,
host ? "",
system ? pkgs.stdenv.hostPlatform.system,
...
}: let
host-matches =
(name == "${user-name}@${host}")
|| (name == "${user-name}@${system}");
}:
let
host-matches = (name == "${user-name}@${host}") || (name == "${user-name}@${system}");
# NOTE: To conform to the config structure of home-manager, we have to
# remap the options coming from `snowfallorg.user.<name>.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
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;
contents = builtins.map (
merge-entry: merge-entry.${user-name}.home.config or { }
) user-option.contents;
}
else
(builtins.trace ''
@@ -345,7 +371,8 @@ in {
user-option;
home-config = mkAliasAndWrapDefinitions wrap-user-options options.snowfallorg.users;
in {
in
{
_file = "virtual:snowfallorg/home/user/${name}";
config = mkIf host-matches {
@@ -358,18 +385,32 @@ in {
# NOTE: specialArgs are not propagated by Home-Manager without this.
# However, not all specialArgs values can be set when using `_module.args`.
_module.args = builtins.removeAttrs ((users.users.${name}.specialArgs or {})
_module.args =
builtins.removeAttrs
(
(users.users.${name}.specialArgs or { })
// {
namespace = snowfall-config.namespace;
})
["options" "config" "lib" "pkgs" "specialArgs" "host"];
}
)
[
"options"
"config"
"lib"
"pkgs"
"specialArgs"
"host"
];
};
home-manager = {
users.${user-name} = mkIf config.snowfallorg.users.${user-name}.home.enable ({pkgs, ...}: {
imports = (home-config.imports or []) ++ other-modules ++ [user-module];
config = builtins.removeAttrs home-config ["imports"];
});
users.${user-name} = mkIf config.snowfallorg.users.${user-name}.home.enable (
{ pkgs, ... }:
{
imports = (home-config.imports or [ ]) ++ other-modules ++ [ user-module ];
config = builtins.removeAttrs home-config [ "imports" ];
}
);
# NOTE: Without this home-manager will instead create its own package set which won't contain the same config and
# user-defined packages/overlays as the flake's nixpkgs channel.
@@ -377,8 +418,7 @@ in {
};
};
}
)
(builtins.attrNames created-users);
) (builtins.attrNames created-users);
in
[
extra-special-args-module

View File

@@ -6,7 +6,8 @@
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.

View File

@@ -3,8 +3,14 @@
user-inputs,
snowfall-lib,
snowfall-config,
}: let
inherit (core-inputs.nixpkgs.lib) fix filterAttrs callPackageWith isFunction;
}:
let
inherit (core-inputs.nixpkgs.lib)
fix
filterAttrs
callPackageWith
isFunction
;
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);
@@ -16,44 +22,45 @@
core-inputs-libs
user-inputs-libs
snowfall-top-level-lib
{snowfall = snowfall-lib;}
{ snowfall = snowfall-lib; }
];
user-lib-root = snowfall-lib.fs.get-snowfall-file "lib";
user-lib-modules = snowfall-lib.fs.get-default-nix-files-recursive user-lib-root;
user-lib = fix (
user-lib: let
user-lib:
let
attrs = {
inputs = snowfall-lib.flake.without-snowfall-inputs user-inputs;
snowfall-inputs = core-inputs;
namespace = snowfall-config.namespace;
lib = snowfall-lib.attrs.merge-shallow [
base-lib
{"${snowfall-config.namespace}" = user-lib;}
{ "${snowfall-config.namespace}" = user-lib; }
];
};
libs =
builtins.map
(
path: let
libs = builtins.map (
path:
let
imported-module = import path;
in
if isFunction imported-module
then callPackageWith attrs path {}
if isFunction imported-module then
callPackageWith attrs path { }
# the only difference is that there is no `override` and `overrideDerivation` on returned value
else imported-module
)
user-lib-modules;
else
imported-module
) user-lib-modules;
in
snowfall-lib.attrs.merge-deep libs
);
system-lib = snowfall-lib.attrs.merge-shallow [
base-lib
{"${snowfall-config.namespace}" = user-lib;}
{ "${snowfall-config.namespace}" = user-lib; }
];
in {
in
{
internal = {
inherit system-lib user-lib;
};

View File

@@ -3,12 +3,22 @@
user-inputs,
snowfall-lib,
snowfall-config,
}: let
}:
let
inherit (builtins) baseNameOf;
inherit (core-inputs.nixpkgs.lib) foldl mapAttrs hasPrefix hasSuffix isFunction splitString tail;
inherit (core-inputs.nixpkgs.lib)
foldl
mapAttrs
hasPrefix
hasSuffix
isFunction
splitString
tail
;
user-modules-root = snowfall-lib.fs.get-snowfall-file "modules";
in {
in
{
module = {
## Create flake output modules.
## Example Usage:
@@ -20,47 +30,56 @@ in {
## { another-module = ...; my-module = ...; default = ...; }
## ```
#@ Attrs -> Attrs
create-modules = {
create-modules =
{
src ? "${user-modules-root}/nixos",
overrides ? {},
alias ? {},
}: let
overrides ? { },
alias ? { },
}:
let
user-modules = snowfall-lib.fs.get-default-nix-files-recursive src;
create-module-metadata = module: {
name = let
path-name = builtins.replaceStrings [(builtins.toString src) "/default.nix"] ["" ""] (builtins.unsafeDiscardStringContext module);
name =
let
path-name = builtins.replaceStrings [ (builtins.toString 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;
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:
merge-modules =
modules: metadata:
modules
// {
# NOTE: 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
${metadata.name} =
args@{ pkgs, ... }:
let
system = args.system or args.pkgs.stdenv.hostPlatform.system;
target = args.target or system;
format = let
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";
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
// {
modified-args = args // {
inherit system target format;
virtual = args.virtual or (snowfall-lib.system.get-virtual-system-type target != "");
systems = args.systems or {};
systems = args.systems or { };
lib = snowfall-lib.internal.system-lib;
@@ -69,13 +88,14 @@ in {
};
imported-user-module = import metadata.path;
user-module =
if isFunction imported-user-module
then imported-user-module modified-args
else imported-user-module;
if isFunction imported-user-module then
imported-user-module modified-args
else
imported-user-module;
in
user-module // {_file = metadata.path;};
user-module // { _file = metadata.path; };
};
modules-without-aliases = foldl merge-modules {} modules-metadata;
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

View File

@@ -3,12 +3,14 @@
user-inputs,
snowfall-lib,
snowfall-config,
}: let
}:
let
inherit (core-inputs.nixpkgs.lib) assertMsg foldl concatStringsSep;
user-overlays-root = snowfall-lib.fs.get-snowfall-file "overlays";
user-packages-root = snowfall-lib.fs.get-snowfall-file "packages";
in {
in
{
overlay = {
## Create a flake-utils-plus overlays builder.
## Example Usage:
@@ -20,13 +22,17 @@ in {
## (channels: [ ... ])
## ```
#@ Attrs -> Attrs -> [(a -> b -> c)]
create-overlays-builder = {
create-overlays-builder =
{
src ? user-overlays-root,
namespace ? snowfall-config.namespace,
extra-overlays ? [],
}: channels: let
extra-overlays ? [ ],
}:
channels:
let
user-overlays = snowfall-lib.fs.get-default-nix-files-recursive src;
create-overlay = overlay:
create-overlay =
overlay:
import overlay (
# Deprecated: Use `inputs.*` instead of referencing the input name directly.
user-inputs
@@ -37,18 +43,22 @@ in {
lib = snowfall-lib.internal.system-lib;
}
);
user-packages-overlay = final: prev: let
user-packages-overlay =
final: prev:
let
user-packages = snowfall-lib.package.create-packages {
pkgs = final;
inherit channels namespace;
};
in {
${namespace} =
(prev.${namespace} or {})
// user-packages;
in
{
${namespace} = (prev.${namespace} or { }) // user-packages;
};
overlays =
[user-packages-overlay] ++ extra-overlays ++ (builtins.map create-overlay user-overlays);
overlays = [
user-packages-overlay
]
++ extra-overlays
++ (builtins.map create-overlay user-overlays);
in
overlays;
@@ -63,16 +73,18 @@ in {
## { default = final: prev: ...; some-overlay = final: prev: ...; }
## ```
#@ Attrs -> Attrs
create-overlays = {
create-overlays =
{
src ? user-overlays-root,
packages-src ? user-packages-root,
namespace ? snowfall-config.namespace,
extra-overlays ? {},
}: let
extra-overlays ? { },
}:
let
fake-pkgs = {
callPackage = x: x;
isFakePkgs = true;
lib = {};
lib = { };
system = "fake-system";
};
@@ -80,25 +92,29 @@ in {
channel-systems = user-inputs.self.pkgs;
user-packages-overlay = final: prev: let
user-packages-overlay =
final: prev:
let
user-packages = snowfall-lib.package.create-packages {
pkgs = final;
channels = channel-systems.${prev.system};
inherit namespace;
};
in
if namespace == null
then user-packages
else {
${namespace} =
(prev.${namespace} or {})
// user-packages;
if namespace == null then
user-packages
else
{
${namespace} = (prev.${namespace} or { }) // user-packages;
};
create-overlay = (
overlays: file: let
overlays: file:
let
name = builtins.unsafeDiscardStringContext (snowfall-lib.path.get-parent-directory file);
overlay = final: prev: let
overlay =
final: prev:
let
channels = channel-systems.${prev.system};
user-overlay = import file (
# Deprecated: Use `inputs.*` instead of referencing the input name directly.
@@ -111,29 +127,24 @@ in {
);
packages = user-packages-overlay final prev;
prev-with-packages =
if namespace == null
then prev // packages
if namespace == null then
prev // packages
else
prev
// {
${namespace} =
(prev.${namespace} or {})
// packages.${namespace};
${namespace} = (prev.${namespace} or { }) // packages.${namespace};
};
user-overlay-packages =
user-overlay
final
prev-with-packages;
outputs =
user-overlay-packages;
user-overlay-packages = user-overlay final prev-with-packages;
outputs = user-overlay-packages;
in
if user-overlay-packages.__dontExport or false == true
then outputs // {__dontExport = true;}
else outputs;
if user-overlay-packages.__dontExport or false == true then
outputs // { __dontExport = true; }
else
outputs;
fake-overlay-result = overlay fake-pkgs fake-pkgs;
in
if fake-overlay-result.__dontExport or false == true
then overlays
if fake-overlay-result.__dontExport or false == true then
overlays
else
overlays
// {
@@ -141,29 +152,30 @@ in {
}
);
overlays =
foldl
create-overlay
{}
user-overlays;
overlays = foldl create-overlay { } user-overlays;
user-packages = snowfall-lib.fs.get-default-nix-files-recursive packages-src;
create-package-overlay = package-overlays: file: let
create-package-overlay =
package-overlays: file:
let
name = builtins.unsafeDiscardStringContext (snowfall-lib.path.get-parent-directory file);
overlay = final: prev: let
overlay =
final: prev:
let
channels = channel-systems.${prev.system};
packages = snowfall-lib.package.create-packages {
inherit namespace;
channels = channel-systems.${prev.system};
};
in
if namespace == null
then {${name} = packages.${name};}
else {
${namespace} =
(prev.${namespace} or {})
// {${name} = packages.${name};};
if namespace == null then
{ ${name} = packages.${name}; }
else
{
${namespace} = (prev.${namespace} or { }) // {
${name} = packages.${name};
};
};
in
package-overlays
@@ -171,28 +183,23 @@ in {
"package/${name}" = overlay;
};
package-overlays =
foldl
create-package-overlay
{}
user-packages;
package-overlays = foldl create-package-overlay { } user-packages;
default-overlay = final: prev: let
default-overlay =
final: prev:
let
overlays-list = builtins.attrValues overlays;
package-overlays-list = builtins.attrValues package-overlays;
overlays-results = builtins.map (overlay: overlay final prev) overlays-list;
package-overlays-results = builtins.map (overlay: overlay final prev) package-overlays-list;
merged-results =
snowfall-lib.attrs.merge-shallow-packages
(package-overlays-results ++ overlays-results);
merged-results = snowfall-lib.attrs.merge-shallow-packages (
package-overlays-results ++ overlays-results
);
in
merged-results;
in
package-overlays
// overlays
// {default = default-overlay;}
// extra-overlays;
package-overlays // overlays // { default = default-overlay; } // extra-overlays;
};
}

View File

@@ -3,12 +3,20 @@
user-inputs,
snowfall-lib,
snowfall-config,
}: let
}:
let
inherit (core-inputs.flake-utils-plus.lib) filterPackages allSystems;
inherit (core-inputs.nixpkgs.lib) assertMsg foldl mapAttrs filterAttrs callPackageWith;
inherit (core-inputs.nixpkgs.lib)
assertMsg
foldl
mapAttrs
filterAttrs
callPackageWith
;
user-packages-root = snowfall-lib.fs.get-snowfall-file "packages";
in {
in
{
package = rec {
## Create flake output packages.
## Example Usage:
@@ -20,16 +28,20 @@ in {
## { another-package = ...; my-package = ...; default = ...; }
## ```
#@ Attrs -> Attrs
create-packages = {
create-packages =
{
channels,
src ? user-packages-root,
pkgs ? channels.nixpkgs,
overrides ? {},
alias ? {},
overrides ? { },
alias ? { },
namespace ? snowfall-config.namespace,
}: let
}:
let
user-packages = snowfall-lib.fs.get-default-nix-files-recursive src;
create-package-metadata = package: let
create-package-metadata =
package:
let
namespaced-packages = {
${namespace} = packages-without-aliases;
};
@@ -42,16 +54,16 @@ in {
pkgs = pkgs // namespaced-packages;
inputs = user-inputs;
};
in {
in
{
name = builtins.unsafeDiscardStringContext (snowfall-lib.path.get-parent-directory package);
drv = let
pkg = callPackageWith extra-inputs package {};
drv =
let
pkg = callPackageWith extra-inputs package { };
in
pkg
// {
meta =
(pkg.meta or {})
// {
meta = (pkg.meta or { }) // {
snowfall = {
path = package;
};
@@ -59,12 +71,13 @@ in {
};
};
packages-metadata = builtins.map create-package-metadata user-packages;
merge-packages = packages: metadata:
merge-packages =
packages: metadata:
packages
// {
${metadata.name} = metadata.drv;
};
packages-without-aliases = foldl merge-packages {} packages-metadata;
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

View File

@@ -3,12 +3,19 @@
user-inputs,
snowfall-lib,
snowfall-config,
}: let
inherit (builtins) toString baseNameOf dirOf concatStringsSep;
}:
let
inherit (builtins)
toString
baseNameOf
dirOf
concatStringsSep
;
inherit (core-inputs.nixpkgs.lib) assertMsg last init;
file-name-regex = "(.*)\\.(.*)$";
in {
in
{
path = rec {
## Split a file name and its extension.
## Example Usage:
@@ -20,10 +27,15 @@ in {
## [ "my-file" "md" ]
## ```
#@ String -> [String]
split-file-extension = file: let
split-file-extension =
file:
let
match = builtins.match file-name-regex file;
in
assert assertMsg (match != null) "lib.snowfall.split-file-extension: File must have an extension to split."; match;
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.
## Example Usage:
@@ -35,7 +47,9 @@ in {
## true
## ```
#@ String -> Bool
has-any-file-extension = file: let
has-any-file-extension =
file:
let
match = builtins.match file-name-regex (toString file);
in
match != null;
@@ -50,13 +64,15 @@ in {
## "txt"
## ```
#@ String -> String
get-file-extension = file:
if has-any-file-extension file
then let
get-file-extension =
file:
if has-any-file-extension file then
let
match = builtins.match file-name-regex (toString file);
in
last match
else "";
else
"";
## Check if a file name has a specific file extension.
## Example Usage:
@@ -68,10 +84,9 @@ in {
## true
## ```
#@ String -> String -> Bool
has-file-extension = extension: file:
if has-any-file-extension file
then extension == get-file-extension file
else false;
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.
## Example Usage:
@@ -95,11 +110,14 @@ in {
## "my-file"
## ```
#@ Path -> String
get-file-name-without-extension = path: let
get-file-name-without-extension =
path:
let
file-name = baseNameOf path;
in
if has-any-file-extension file-name
then concatStringsSep "" (init (split-file-extension file-name))
else file-name;
if has-any-file-extension file-name then
concatStringsSep "" (init (split-file-extension file-name))
else
file-name;
};
}

View File

@@ -3,12 +3,19 @@
user-inputs,
snowfall-lib,
snowfall-config,
}: let
}:
let
inherit (core-inputs.flake-utils-plus.lib) filterPackages;
inherit (core-inputs.nixpkgs.lib) assertMsg foldl mapAttrs callPackageWith;
inherit (core-inputs.nixpkgs.lib)
assertMsg
foldl
mapAttrs
callPackageWith
;
user-shells-root = snowfall-lib.fs.get-snowfall-file "shells";
in {
in
{
shell = {
## Create flake output packages.
## Example Usage:
@@ -20,34 +27,38 @@ in {
## { another-shell = ...; my-shell = ...; default = ...; }
## ```
#@ Attrs -> Attrs
create-shells = {
create-shells =
{
channels,
src ? user-shells-root,
pkgs ? channels.nixpkgs,
overrides ? {},
alias ? {},
}: let
overrides ? { },
alias ? { },
}:
let
user-shells = snowfall-lib.fs.get-default-nix-files-recursive src;
create-shell-metadata = shell: let
extra-inputs =
pkgs
// {
create-shell-metadata =
shell:
let
extra-inputs = pkgs // {
inherit channels;
lib = snowfall-lib.internal.system-lib;
inputs = snowfall-lib.flake.without-src user-inputs;
namespace = snowfall-config.namespace;
};
in {
in
{
name = builtins.unsafeDiscardStringContext (snowfall-lib.path.get-parent-directory shell);
drv = callPackageWith extra-inputs shell {};
drv = callPackageWith extra-inputs shell { };
};
shells-metadata = builtins.map create-shell-metadata user-shells;
merge-shells = shells: metadata:
merge-shells =
shells: metadata:
shells
// {
${metadata.name} = metadata.drv;
};
shells-without-aliases = foldl merge-shells {} shells-metadata;
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

View File

@@ -3,15 +3,25 @@
user-inputs,
snowfall-lib,
snowfall-config,
}: let
}:
let
inherit (builtins) dirOf baseNameOf;
inherit (core-inputs.nixpkgs.lib) assertMsg fix hasInfix concatMap foldl optionals singleton;
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";
in {
in
{
system = rec {
## Get the name of a system based on its file path.
## Example Usage:
@@ -23,10 +33,12 @@ in {
## "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;
get-inferred-system-name =
path:
if snowfall-lib.path.has-file-extension "nix" path then
snowfall-lib.path.get-parent-directory path
else
baseNameOf path;
## Check whether a named system is macOS.
## Example Usage:
@@ -62,8 +74,7 @@ in {
## true
## ```
#@ String -> Bool
is-virtual = target:
(get-virtual-system-type target) != "";
is-virtual = target: (get-virtual-system-type target) != "";
## Get the virtual system type of a system target.
## Example Usage:
@@ -75,16 +86,12 @@ in {
## "iso"
## ```
#@ String -> String
get-virtual-system-type = target:
foldl
(
get-virtual-system-type =
target:
foldl (
result: virtual-system:
if result == "" && hasInfix virtual-system target
then virtual-system
else result
)
""
virtual-systems;
if result == "" && hasInfix virtual-system target then virtual-system else result
) "" virtual-systems;
## Get structured data about all systems for a given target.
## Example Usage:
@@ -96,7 +103,9 @@ in {
## [ { target = "x86_64-linux"; name = "my-machine"; path = "/systems/x86_64-linux/my-machine"; } ]
## ```
#@ String -> [Attrs]
get-target-systems-metadata = target: let
get-target-systems-metadata =
target:
let
systems = snowfall-lib.fs.get-directories target;
existing-systems = builtins.filter (system: builtins.pathExists "${system}/default.nix") systems;
create-system-metadata = path: {
@@ -124,62 +133,66 @@ in {
## (args: <system>)
## ```
#@ String -> Function
get-system-builder = target: let
get-system-builder =
target:
let
virtual-system-type = get-virtual-system-type target;
virtual-system-builder = args:
assert assertMsg (user-inputs ? nixos-generators) "In order to create virtual systems, you must include `nixos-generators` as a flake input.";
user-inputs.nixos-generators.nixosGenerate
(args
virtual-system-builder =
args:
assert assertMsg (
user-inputs ? nixos-generators
) "In order to create virtual systems, you must include `nixos-generators` as a flake input.";
user-inputs.nixos-generators.nixosGenerate (
args
// {
format = virtual-system-type;
specialArgs =
args.specialArgs
// {
specialArgs = args.specialArgs // {
format = virtual-system-type;
};
modules =
args.modules
++ [
modules = args.modules ++ [
../../modules/nixos/user/default.nix
];
});
darwin-system-builder = args:
assert assertMsg (user-inputs ? darwin) "In order to create virtual systems, you must include `darwin` as a flake input.";
user-inputs.darwin.lib.darwinSystem
((builtins.removeAttrs args ["system" "modules"])
// {
specialArgs =
args.specialArgs
}
);
darwin-system-builder =
args:
assert assertMsg (
user-inputs ? darwin
) "In order to create virtual systems, you must include `darwin` as a flake input.";
user-inputs.darwin.lib.darwinSystem (
(builtins.removeAttrs args [
"system"
"modules"
])
// {
specialArgs = args.specialArgs // {
format = "darwin";
};
modules =
args.modules
++ [
modules = args.modules ++ [
../../modules/darwin/user/default.nix
];
});
linux-system-builder = args:
core-inputs.nixpkgs.lib.nixosSystem
(args
// {
specialArgs =
args.specialArgs
}
);
linux-system-builder =
args:
core-inputs.nixpkgs.lib.nixosSystem (
args
// {
specialArgs = args.specialArgs // {
format = "linux";
};
modules =
args.modules
++ [
modules = args.modules ++ [
../../modules/nixos/user/default.nix
];
});
}
);
in
if virtual-system-type != ""
then virtual-system-builder
else if is-darwin target
then darwin-system-builder
else linux-system-builder;
if virtual-system-type != "" then
virtual-system-builder
else if is-darwin target then
darwin-system-builder
else
linux-system-builder;
## Get the flake output attribute for a system target.
## Example Usage:
@@ -191,14 +204,17 @@ in {
## "darwinConfigurations"
## ```
#@ String -> String
get-system-output = target: let
get-system-output =
target:
let
virtual-system-type = get-virtual-system-type target;
in
if virtual-system-type != ""
then "${virtual-system-type}Configurations"
else if is-darwin target
then "darwinConfigurations"
else "nixosConfigurations";
if virtual-system-type != "" then
"${virtual-system-type}Configurations"
else if is-darwin target then
"darwinConfigurations"
else
"nixosConfigurations";
## Get the resolved (non-virtual) system target.
## Example Usage:
@@ -210,12 +226,15 @@ in {
## "x86_64-linux"
## ```
#@ String -> String
get-resolved-system-target = target: let
get-resolved-system-target =
target:
let
virtual-system-type = get-virtual-system-type target;
in
if virtual-system-type != ""
then builtins.replaceStrings [virtual-system-type] ["linux"] target
else target;
if virtual-system-type != "" then
builtins.replaceStrings [ virtual-system-type ] [ "linux" ] target
else
target;
## Create a system.
## Example Usage:
@@ -227,35 +246,47 @@ in {
## <flake-utils-plus-system-configuration>
## ```
#@ Attrs -> Attrs
create-system = {
create-system =
{
target ? "x86_64-linux",
system ? get-resolved-system-target target,
path,
name ? builtins.unsafeDiscardStringContext (get-inferred-system-name path),
modules ? [],
specialArgs ? {},
modules ? [ ],
specialArgs ? { },
channelName ? "nixpkgs",
builder ? get-system-builder target,
output ? get-system-output target,
systems ? {},
homes ? {},
}: let
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;
if is-darwin system then
user-inputs.home-manager.darwinModules.home-manager
else
user-inputs.home-manager.nixosModules.home-manager;
home-manager-modules = [ home-manager-module ] ++ home-system-modules;
in
{
inherit
channelName
system
builder
output
;
modules = [path] ++ modules ++ (optionals (user-inputs ? home-manager) home-manager-modules);
modules = [ path ] ++ modules ++ (optionals (user-inputs ? home-manager) home-manager-modules);
specialArgs =
specialArgs
// {
inherit target system systems lib;
specialArgs = specialArgs // {
inherit
target
system
systems
lib
;
host = name;
virtual = (get-virtual-system-type target) != "";
@@ -274,10 +305,12 @@ in {
## { my-host = <flake-utils-plus-system-configuration>; }
## ```
#@ Attrs -> Attrs
create-systems = {
systems ? {},
homes ? {},
}: let
create-systems =
{
systems ? { },
homes ? { },
}:
let
targets = snowfall-lib.fs.get-directories user-systems-root;
target-systems-metadata = concatMap get-target-systems-metadata targets;
user-nixos-modules = snowfall-lib.module.create-modules {
@@ -286,38 +319,33 @@ in {
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 [];
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;
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-modules = if is-darwin system-metadata.target then darwin-modules else nixos-modules;
in
{
${system-metadata.name} = create-system (
overrides
// system-metadata
// {
systems = created-systems;
modules = user-modules-list ++ (overrides.modules or []) ++ system-modules;
modules = user-modules-list ++ (overrides.modules or [ ]) ++ system-modules;
inherit homes;
});
}
);
};
created-systems = fix (
created-systems:
foldl
(
systems: system-metadata:
systems // (create-system' created-systems system-metadata)
)
{}
target-systems-metadata
foldl (
systems: system-metadata: systems // (create-system' created-systems system-metadata)
) { } target-systems-metadata
);
in
created-systems;

View File

@@ -3,12 +3,14 @@
user-inputs,
snowfall-lib,
snowfall-config,
}: let
}:
let
inherit (builtins) baseNameOf;
inherit (core-inputs.nixpkgs.lib) assertMsg foldl mapAttrs;
user-templates-root = snowfall-lib.fs.get-snowfall-file "templates";
in {
in
{
template = {
## Create flake templates.
##
@@ -22,41 +24,40 @@ in {
## { another-template = ...; my-template = ...; default = ...; }
## ```
#@ Attrs -> Attrs
create-templates = {
create-templates =
{
src ? user-templates-root,
overrides ? {},
alias ? {},
}: let
overrides ? { },
alias ? { },
}:
let
user-templates = snowfall-lib.fs.get-directories src;
create-template-metadata = template: let
create-template-metadata =
template:
let
flake-file = template + "/flake.nix";
has-flake = builtins.pathExists flake-file;
flake-attrs =
if has-flake
then import flake-file
else {};
flake-attrs = if has-flake then import flake-file else { };
description = flake-attrs.description or null;
in
{
name = builtins.unsafeDiscardStringContext (baseNameOf template);
path = template;
}
// (
if description != null
then {inherit description;}
else {}
);
// (if description != null then { inherit description; } else { });
templates-metadata = builtins.map create-template-metadata user-templates;
merge-templates = templates: metadata:
merge-templates =
templates: metadata:
templates
// {
${metadata.name} =
(overrides.${metadata.name} or {})
// (builtins.removeAttrs metadata ["name"]);
(overrides.${metadata.name} or { }) // (builtins.removeAttrs metadata [ "name" ]);
};
templates-without-aliases = foldl merge-templates {} templates-metadata;
templates-without-aliases = foldl merge-templates { } templates-metadata;
aliased-templates = mapAttrs (name: value: templates-without-aliases.${value}) alias;
unused-overrides = builtins.removeAttrs overrides (builtins.map (metadata: metadata.name) templates-metadata);
unused-overrides = builtins.removeAttrs overrides (
builtins.map (metadata: metadata.name) templates-metadata
);
templates = templates-without-aliases // aliased-templates // unused-overrides;
in
templates;