{ config, lib, pkgs, home-manager, ... }: let inherit (lib) filter attrNames ; in { imports = [ ]; options.me.install = { user = lib.mkOption { type = lib.types.attrsOf ( lib.types.submodule ( { username, config, ... }: { options = { enable = lib.mkOption { type = lib.types.bool; default = true; defaultText = "me.install.file.‹username›.enable"; example = false; 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 = { target_username = lib.mkDefault username; }; } ) ); 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 [ (lib.mkIf (config.me.install.file != { }) ( let cfg = config.me.install.file; install_file_targets = filter (target: config.me.install.file."${target}".enable) (attrNames cfg); in { home.activation = { installFiles = home-manager.lib.hm.dag.entryAfter [ "writeBoundary" ] ( let install_commands = builtins.map ( target: let target_config = config.me.install.file."${target}"; source = lib.strings.escapeShellArg "${target_config.source}"; destination = lib.strings.escapeShellArg target; mode = lib.strings.escapeShellArg "${target_config.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} '' ) install_file_targets; in (lib.strings.concatStringsSep "\n" install_commands) ); }; } )) ]; }