2025-04-11 17:45:47 -04:00
|
|
|
|
{
|
|
|
|
|
config,
|
|
|
|
|
lib,
|
|
|
|
|
pkgs,
|
|
|
|
|
home-manager,
|
|
|
|
|
...
|
|
|
|
|
}:
|
|
|
|
|
|
|
|
|
|
let
|
2025-08-09 14:37:25 -04:00
|
|
|
|
cfg = config.me.install;
|
2025-04-11 17:45:47 -04:00
|
|
|
|
inherit (lib)
|
|
|
|
|
filter
|
|
|
|
|
attrNames
|
|
|
|
|
;
|
2025-08-09 14:37:25 -04:00
|
|
|
|
|
|
|
|
|
install_user_file =
|
2025-08-09 19:57:09 -04:00
|
|
|
|
let
|
|
|
|
|
constructors = {
|
|
|
|
|
"overwrite" = install_user_file_overwrite;
|
|
|
|
|
"symlink" = install_user_file_symlink;
|
|
|
|
|
};
|
|
|
|
|
in
|
2025-08-09 20:27:27 -04:00
|
|
|
|
stage: target: (constructors."${target.method}"."${stage}" target);
|
|
|
|
|
old_install_user_file =
|
2025-08-09 19:57:09 -04:00
|
|
|
|
let
|
2025-08-09 20:27:27 -04:00
|
|
|
|
constructors = {
|
|
|
|
|
"overwrite" = install_user_file_overwrite;
|
|
|
|
|
"symlink" = install_user_file_symlink;
|
|
|
|
|
};
|
2025-08-09 19:57:09 -04:00
|
|
|
|
in
|
2025-08-09 20:27:27 -04:00
|
|
|
|
(target: (constructors."${target.method}" target));
|
|
|
|
|
install_user_file_overwrite = {
|
|
|
|
|
"check" = (target: "");
|
|
|
|
|
"install" = (
|
|
|
|
|
target:
|
|
|
|
|
let
|
|
|
|
|
source = lib.strings.escapeShellArg "${target.source}";
|
|
|
|
|
destination = lib.strings.escapeShellArg "${target.target}";
|
|
|
|
|
mode = lib.strings.escapeShellArg "${target.mode}";
|
|
|
|
|
in
|
|
|
|
|
''
|
|
|
|
|
$DRY_RUN_CMD install $VERBOSE_ARG -D --compare -m ${mode} ${source} ${destination}
|
|
|
|
|
''
|
|
|
|
|
);
|
|
|
|
|
"uninstall" = (target: "");
|
|
|
|
|
};
|
|
|
|
|
install_user_file_symlink = {
|
|
|
|
|
"check" = (target: "");
|
|
|
|
|
"install" = (
|
|
|
|
|
target:
|
|
|
|
|
let
|
|
|
|
|
source = lib.strings.escapeShellArg "${target.source}";
|
|
|
|
|
destination = lib.strings.escapeShellArg "${target.target}";
|
|
|
|
|
in
|
|
|
|
|
''
|
|
|
|
|
$DRY_RUN_CMD ln $VERBOSE_ARG -s ${source} ${destination}
|
|
|
|
|
''
|
|
|
|
|
);
|
|
|
|
|
"uninstall" = (target: "");
|
|
|
|
|
};
|
2025-04-11 17:45:47 -04:00
|
|
|
|
in
|
|
|
|
|
{
|
|
|
|
|
imports = [ ];
|
|
|
|
|
|
2025-04-11 18:00:36 -04:00
|
|
|
|
options.me.install = {
|
|
|
|
|
user = lib.mkOption {
|
|
|
|
|
type = lib.types.attrsOf (
|
|
|
|
|
lib.types.submodule (
|
2025-08-09 14:37:25 -04:00
|
|
|
|
{ name, config, ... }:
|
|
|
|
|
let
|
|
|
|
|
username = name;
|
|
|
|
|
in
|
2025-04-11 18:00:36 -04:00
|
|
|
|
{
|
|
|
|
|
options = {
|
|
|
|
|
enable = lib.mkOption {
|
|
|
|
|
type = lib.types.bool;
|
|
|
|
|
default = true;
|
2025-08-09 14:37:25 -04:00
|
|
|
|
defaultText = "enable";
|
|
|
|
|
example = lib.literalExpression false;
|
2025-04-11 18:00:36 -04:00
|
|
|
|
description = "Whether we want to install files in this user's home directory.";
|
|
|
|
|
};
|
|
|
|
|
|
2025-08-09 14:37:25 -04:00
|
|
|
|
file = lib.mkOption {
|
|
|
|
|
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.";
|
|
|
|
|
};
|
|
|
|
|
};
|
2025-04-11 18:00:36 -04:00
|
|
|
|
|
2025-08-09 14:37:25 -04:00
|
|
|
|
config = {
|
|
|
|
|
username = lib.mkDefault username;
|
|
|
|
|
target = lib.mkDefault path;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
);
|
2025-04-11 17:45:47 -04:00
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2025-08-09 14:37:25 -04:00
|
|
|
|
config =
|
|
|
|
|
let
|
|
|
|
|
all_users = builtins.map (username: cfg.user."${username}") (attrNames cfg.user);
|
|
|
|
|
enabled_users = filter (user: user.enable) all_users;
|
|
|
|
|
all_file_targets = lib.flatten (
|
|
|
|
|
builtins.map (user: (builtins.map (path: user.file."${path}") (attrNames user.file))) enabled_users
|
|
|
|
|
);
|
|
|
|
|
enabled_file_targets = filter (target: target.enable) all_file_targets;
|
2025-08-09 20:27:27 -04:00
|
|
|
|
check_commands = builtins.map (install_user_file "check") enabled_file_targets;
|
|
|
|
|
install_commands = builtins.map (install_user_file "install") enabled_file_targets;
|
|
|
|
|
uninstall_commands = builtins.map (install_user_file "uninstall") enabled_file_targets;
|
2025-08-09 14:37:25 -04:00
|
|
|
|
in
|
|
|
|
|
{
|
|
|
|
|
systemd.services.me-install-file = {
|
|
|
|
|
enable = true;
|
|
|
|
|
description = "me-install-file";
|
|
|
|
|
wantedBy = [ "multi-user.target" ];
|
|
|
|
|
wants = [ "multi-user.target" ];
|
|
|
|
|
after = [ "multi-user.target" ];
|
|
|
|
|
# path = with pkgs; [
|
|
|
|
|
# zfs
|
|
|
|
|
# ];
|
|
|
|
|
unitConfig.DefaultDependencies = "no";
|
|
|
|
|
serviceConfig = {
|
|
|
|
|
Type = "oneshot";
|
|
|
|
|
RemainAfterExit = "yes";
|
2025-04-11 17:45:47 -04:00
|
|
|
|
};
|
2025-08-09 20:27:27 -04:00
|
|
|
|
script = (lib.strings.concatStringsSep "\n" (check_commands ++ install_commands));
|
|
|
|
|
preStop = (lib.strings.concatStringsSep "\n" uninstall_commands);
|
2025-08-09 14:37:25 -04:00
|
|
|
|
};
|
|
|
|
|
|
2025-08-09 19:57:09 -04:00
|
|
|
|
environment.etc."install_out".text = config.systemd.services.me-install-file.script;
|
2025-08-09 14:37:25 -04:00
|
|
|
|
};
|
2025-04-11 17:45:47 -04:00
|
|
|
|
}
|