1
Fork 0
mirror of https://github.com/RGBCube/hjem synced 2025-10-31 21:52:44 +00:00
hjem/modules/nixos/default.nix
NotAShelf db6e3af3e5
modules: rename hjem.extraSpecialArgs to hjem.specialArgs
Okay they are just special, not *extra* special.
2025-01-21 16:09:16 +03:00

128 lines
3.9 KiB
Nix

{
config,
pkgs,
lib,
...
}: let
inherit (lib.modules) mkIf mkMerge;
inherit (lib.options) mkOption literalExpression;
inherit (lib.lists) filter map flatten concatLists;
inherit (lib.attrsets) filterAttrs mapAttrs' attrValues mapAttrsToList;
inherit (lib.trivial) flip;
inherit (lib.types) bool attrsOf submoduleWith listOf raw attrs;
cfg = config.hjem;
hjemModule = submoduleWith {
description = "Hjem NixOS module";
class = "hjem";
specialArgs = {inherit pkgs lib;} // cfg.specialArgs;
modules = concatLists [
[
({name, ...}: {
imports = [../common.nix];
config = {
user = config.users.users.${name}.name;
directory = config.users.users.${name}.home;
clobberFiles = cfg.clobberByDefault;
};
})
]
# Evaluate additional modules under 'hjem.users.<name>' so that
# module systems built on Hjem are more ergonomic.
cfg.extraModules
];
};
in {
imports = [
# This should be removed in the future, since 'homes' is a very vague
# namespace to occupy. Added 2024-12-27, remove 2025-01-27 to allow
# sufficient time to migrate.
(lib.mkRenamedOptionModule ["homes"] ["hjem" "users"])
# 'extraSpecialArgs' is confusing and obscure. 'hjem.specialArgs' better
# describes what the option is really for.
(lib.mkRenamedOptionModule ["hjem" "extraSpecialArgs"] ["hjem" "specialArgs"])
];
options.hjem = {
clobberByDefault = mkOption {
type = bool;
default = false;
description = ''
The default override behaviour for files managed by Hjem.
While `true`, existing files will be overriden with new files on rebuild.
The behaviour may be modified per-user by setting {option}`hjem.users.<name>.clobberFiles`
to the desired value.
'';
};
users = mkOption {
default = {};
type = attrsOf hjemModule;
description = "Home configurations to be managed";
};
extraModules = mkOption {
type = listOf raw;
default = [];
description = ''
Additional modules to be evaluated as a part of the users module
inside {option}`config.hjem.users.<name>`. This can be used to
extend each user configuration with additional options.
'';
};
specialArgs = mkOption {
type = attrs;
default = {};
example = literalExpression "{ inherit inputs; }";
description = ''
Additional `specialArgs` are passed to Hjem, allowing extra arguments
to be passed down to to all imported modules.
'';
};
};
config = mkMerge [
{
users.users = mapAttrs' (name: {packages, ...}: {
inherit name;
value.packages = packages;
}) (filterAttrs (_: u: (u.enable && u.packages != [])) cfg.users);
systemd.user.tmpfiles.users = mapAttrs' (name: {files, ...}: {
inherit name;
value.rules = map (
file: let
# L+ will recreate, i.e., clobber existing files.
mode =
if file.clobber
then "L+"
else "L";
in
# Constructed rule string that consists of the type, target, and source
# of a tmpfile. Files with 'null' sources are filtered before the rule
# is constructed.
"${mode} '${file.target}' - - - - ${file.source}"
) (filter (f: f.enable && f.source != null) (attrValues files));
}) (filterAttrs (_: u: (u.enable && u.files != {})) cfg.users);
}
(mkIf (cfg.users != {}) {
warnings = flatten (flip mapAttrsToList cfg.users (user: config:
flip map config.warnings (
warning: "${user} profile: ${warning}"
)));
assertions = flatten (flip mapAttrsToList cfg.users (user: config:
flip map config.assertions (assertion: {
inherit (assertion) assertion;
message = "${user} profile: ${assertion.message}";
})));
})
];
}