diff --git a/nix/configuration/configuration.nix b/nix/configuration/configuration.nix index 35e5d7c..cfc094a 100644 --- a/nix/configuration/configuration.nix +++ b/nix/configuration/configuration.nix @@ -78,6 +78,11 @@ ./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-command" "flakes" diff --git a/nix/configuration/util/install_files/default.nix b/nix/configuration/util/install_files/default.nix index 239e79f..8f06105 100644 --- a/nix/configuration/util/install_files/default.nix +++ b/nix/configuration/util/install_files/default.nix @@ -7,10 +7,23 @@ }: let + cfg = config.me.install; inherit (lib) filter 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 { imports = [ ]; @@ -19,138 +32,121 @@ in user = lib.mkOption { type = lib.types.attrsOf ( lib.types.submodule ( - { username, config, ... }: + { name, config, ... }: + let + username = name; + in { options = { enable = lib.mkOption { type = lib.types.bool; default = true; - defaultText = "me.install.file.‹username›.enable"; - example = false; + defaultText = "enable"; + example = lib.literalExpression 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; + 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."; + }; + }; + + 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 [ - (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); - 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_config.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 - { - 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"; - }; - script = (lib.strings.concatStringsSep "\n" install_commands); - # preStop = '' - # rm -f /home/talexander/.docker/config.json - # ''; + 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; + install_commands = builtins.map install_user_file enabled_file_targets; + 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"; }; - } - )) - ]; + 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); + }; }