Switch to nested attrsets.

This commit is contained in:
Tom Alexander 2025-08-09 14:37:25 -04:00
parent f667c9daa6
commit 146dc5f79a
No known key found for this signature in database
GPG Key ID: D3A179C9A53C0EDE
2 changed files with 119 additions and 118 deletions

View File

@ -78,6 +78,11 @@
./util/unfree_polyfill ./util/unfree_polyfill
]; ];
# me.install.user.file.talexander.".local/nixcfg" = ./README.org;
me.install.user.talexander.file.".local/nixcfg" = {
source = ./flake.lock;
};
nix.settings.experimental-features = [ nix.settings.experimental-features = [
"nix-command" "nix-command"
"flakes" "flakes"

View File

@ -7,10 +7,23 @@
}: }:
let let
cfg = config.me.install;
inherit (lib) inherit (lib)
filter filter
attrNames attrNames
; ;
install_user_file =
target:
let
source = lib.strings.escapeShellArg "${target.source}";
destination = lib.strings.escapeShellArg "${target.target}";
mode = lib.strings.escapeShellArg "${target.mode}";
in
# $DRY_RUN_CMD ${pkgs.toyboy}/bin/install $VERBOSE_ARG -D -m ${mode} ${source} ${destination}
''
$DRY_RUN_CMD install $VERBOSE_ARG -D --compare -m ${mode} ${source} ${destination}
'';
in in
{ {
imports = [ ]; imports = [ ];
@ -19,138 +32,121 @@ in
user = lib.mkOption { user = lib.mkOption {
type = lib.types.attrsOf ( type = lib.types.attrsOf (
lib.types.submodule ( lib.types.submodule (
{ username, config, ... }: { name, config, ... }:
let
username = name;
in
{ {
options = { options = {
enable = lib.mkOption { enable = lib.mkOption {
type = lib.types.bool; type = lib.types.bool;
default = true; default = true;
defaultText = "me.install.file.username.enable"; defaultText = "enable";
example = false; example = lib.literalExpression false;
description = "Whether we want to install files in this user's home directory."; description = "Whether we want to install files in this user's home directory.";
}; };
target_username = lib.mkOption {
type = lib.types.str;
defaultText = "me.install.file.username.target_username";
example = "root";
description = "The username for the user whose home directory will contain the file.";
};
};
config = { file = lib.mkOption {
target_username = lib.mkDefault username; type = lib.types.attrsOf (
lib.types.submodule (
{ name, config, ... }:
let
path = name;
in
{
options = {
enable = lib.mkOption {
type = lib.types.bool;
default = true;
defaultText = "enable";
example = lib.literalExpression false;
description = "Whether we want to install this file in this user's home directory.";
};
username = lib.mkOption {
type = lib.types.str;
defaultText = "username";
example = "root";
description = "The username for the user whose home directory will contain the file.";
};
target = lib.mkOption {
type = lib.types.str;
defaultText = "target";
example = ".local/share/foo/bar.txt";
description = "The path where the file should be written.";
};
method = lib.mkOption {
type = lib.types.enum [
"symlink"
"overwrite"
# "bind_mount" TODO: for directories?
];
default = "symlink";
defaultText = "me.install.file.path.method";
example = "overwrite";
description = "The way in which the file should be installed.";
};
mode = lib.mkOption {
type = lib.types.str;
default = "0444";
defaultText = "me.install.file.path.mode";
example = "0750";
description = "The read, write, execute permission flags.";
};
source = lib.mkOption {
type = lib.types.path;
defaultText = "me.install.file.path.source";
example = ./files/foo.txt;
description = "The source file to install into the destination.";
};
};
config = {
username = lib.mkDefault username;
target = lib.mkDefault path;
};
}
)
);
};
}; };
} }
) )
); );
defaultText = "me.install.user.username";
default = { };
# TODO: example
};
file = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule (
{ path, config, ... }:
{
options = {
enable = lib.mkOption {
type = lib.types.bool;
default = true;
defaultText = "me.install.file.path.enable";
example = false;
description = "Whether we want to install this file.";
};
method = lib.mkOption {
type = lib.types.enum [
"symlink"
"overwrite"
# "bind_mount" TODO: for directories?
];
default = "symlink";
defaultText = "me.install.file.path.method";
example = "overwrite";
description = "The way in which the file should be installed.";
};
mode = lib.mkOption {
type = lib.types.str;
default = "0444";
defaultText = "me.install.file.path.mode";
example = "0750";
description = "The read, write, execute permission flags.";
};
source = lib.mkOption {
type = lib.types.path;
defaultText = "me.install.file.path.source";
example = ./files/foo.txt;
description = "The source file to install into the destination.";
};
target = lib.mkOption {
type = lib.types.str;
defaultText = "me.install.file.path.target";
example = ".local/share/foo/bar.txt";
description = "The path where the file should be written.";
};
};
config = {
target = lib.mkDefault path;
};
}
)
);
defaultText = "me.install.file.path";
default = { };
example = lib.literalExpression ''
{
".config/foo/bar.txt" = {
source = ./files/bar.txt
};
}
'';
}; };
}; };
config = lib.mkMerge [ config =
(lib.mkIf (config.me.install.file != { }) ( let
let all_users = builtins.map (username: cfg.user."${username}") (attrNames cfg.user);
cfg = config.me.install.file; enabled_users = filter (user: user.enable) all_users;
install_file_targets = filter (target: config.me.install.file."${target}".enable) (attrNames cfg); all_file_targets = lib.flatten (
install_commands = builtins.map ( builtins.map (user: (builtins.map (path: user.file."${path}") (attrNames user.file))) enabled_users
target: );
let enabled_file_targets = filter (target: target.enable) all_file_targets;
target_config = config.me.install.file."${target}"; install_commands = builtins.map install_user_file enabled_file_targets;
source = lib.strings.escapeShellArg "${target_config.source}"; in
destination = lib.strings.escapeShellArg "${target_config.target}"; {
mode = lib.strings.escapeShellArg "${target_config.mode}"; systemd.services.me-install-file = {
in enable = true;
# $DRY_RUN_CMD ${pkgs.toyboy}/bin/install $VERBOSE_ARG -D -m ${mode} ${source} ${destination} description = "me-install-file";
'' wantedBy = [ "multi-user.target" ];
$DRY_RUN_CMD install $VERBOSE_ARG -D --compare -m ${mode} ${source} ${destination} wants = [ "multi-user.target" ];
'' after = [ "multi-user.target" ];
) install_file_targets; # path = with pkgs; [
in # zfs
{ # ];
systemd.services.me-install-file = { unitConfig.DefaultDependencies = "no";
enable = true; serviceConfig = {
description = "me-install-file"; Type = "oneshot";
wantedBy = [ "multi-user.target" ]; RemainAfterExit = "yes";
wants = [ "multi-user.target" ];
after = [ "multi-user.target" ];
# path = with pkgs; [
# zfs
# ];
unitConfig.DefaultDependencies = "no";
serviceConfig = {
Type = "oneshot";
RemainAfterExit = "yes";
};
script = (lib.strings.concatStringsSep "\n" install_commands);
# preStop = ''
# rm -f /home/talexander/.docker/config.json
# '';
}; };
} script = (lib.strings.concatStringsSep "\n" install_commands);
)) # preStop = ''
]; # rm -f /home/talexander/.docker/config.json
# '';
};
# environment.etc."install_out".text = builtins.toJSON enabled_file_targets;
environment.etc."install_out".text = (lib.strings.concatStringsSep "\n" install_commands);
};
} }