2023-10-02 06:26:11 +00:00
|
|
|
{ config, lib, pkgs, ... }:
|
2023-03-13 15:45:17 +00:00
|
|
|
|
|
|
|
let
|
|
|
|
cfg = config.home.mutableFile;
|
|
|
|
|
2023-03-19 09:16:25 +00:00
|
|
|
fileType = baseDir: { name, config, options, ... }: {
|
2023-03-13 15:45:17 +00:00
|
|
|
options = {
|
|
|
|
url = lib.mkOption {
|
|
|
|
type = lib.types.str;
|
2023-07-27 03:13:39 +00:00
|
|
|
description = ''
|
2023-03-13 15:45:17 +00:00
|
|
|
The URL of the file to be fetched.
|
|
|
|
'';
|
|
|
|
example = "https://github.com/foo-dogsquared/dotfiles.git";
|
|
|
|
};
|
|
|
|
|
|
|
|
path = lib.mkOption {
|
|
|
|
type = lib.types.str;
|
2023-07-27 03:13:39 +00:00
|
|
|
description = ''
|
2023-03-13 15:45:17 +00:00
|
|
|
The path of the mutable file. By default, it will be relative to the
|
|
|
|
home directory.
|
|
|
|
'';
|
|
|
|
example = lib.literalExpression "\${config.xdg.userDirs.documents}/top-secret";
|
2023-03-19 09:16:25 +00:00
|
|
|
default = name;
|
2023-03-17 14:39:52 +00:00
|
|
|
apply = p:
|
2023-03-19 09:16:25 +00:00
|
|
|
if lib.hasPrefix "/" p then p else "${baseDir}/${p}";
|
2023-03-13 15:45:17 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
extractPath = lib.mkOption {
|
|
|
|
type = with lib.types; nullOr str;
|
2023-07-27 03:13:39 +00:00
|
|
|
description = ''
|
2023-03-13 15:45:17 +00:00
|
|
|
The path within the archive to be extracted. This is only used if the
|
|
|
|
type is `archive`. If the value is `null` then it will extract the
|
|
|
|
whole archive into the directory.
|
|
|
|
'';
|
|
|
|
default = null;
|
|
|
|
example = "path/inside/of/the/archive";
|
|
|
|
};
|
|
|
|
|
|
|
|
type = lib.mkOption {
|
2023-07-22 03:05:31 +00:00
|
|
|
type = lib.types.enum [ "git" "fetch" "archive" "gopass" "custom" ];
|
2023-07-27 03:13:39 +00:00
|
|
|
description = ''
|
2023-03-13 15:45:17 +00:00
|
|
|
Type that configures the behavior for fetching the URL.
|
|
|
|
|
|
|
|
This accept only certain keywords.
|
|
|
|
|
2023-09-18 06:39:34 +00:00
|
|
|
- For `fetch`, the file will be fetched with {command}`curl`.
|
|
|
|
- For `git`, it will be fetched with {command}`git clone`.
|
|
|
|
- For `archive`, the file will be fetched with {command}`curl` and
|
|
|
|
extracted before putting the file.
|
|
|
|
- For `gopass`, the file will be cloned with {command}`gopass`.
|
2023-07-22 03:05:31 +00:00
|
|
|
- For `custom`, the file will be passed with a user-given command.
|
|
|
|
The `extraArgs` option is now assumed to be a list of a command and
|
|
|
|
its arguments.
|
2023-03-13 15:45:17 +00:00
|
|
|
|
|
|
|
The default type is `fetch`.
|
|
|
|
'';
|
|
|
|
default = "fetch";
|
|
|
|
example = "git";
|
|
|
|
};
|
2023-03-17 14:39:03 +00:00
|
|
|
|
|
|
|
extraArgs = lib.mkOption {
|
|
|
|
type = with lib.types; listOf str;
|
2023-07-27 03:13:39 +00:00
|
|
|
description = ''
|
2023-03-17 14:39:03 +00:00
|
|
|
A list of extra arguments to be included with the fetch command. Take
|
|
|
|
note of the commands used for each type as documented from
|
2023-07-27 03:13:39 +00:00
|
|
|
{option}`config.home.mutableFile.<name>.type`.
|
2023-03-17 14:39:03 +00:00
|
|
|
'';
|
2023-06-08 13:19:17 +00:00
|
|
|
default = [ ];
|
2023-03-17 14:39:03 +00:00
|
|
|
example = [ "--depth" "1" ];
|
|
|
|
};
|
2023-09-18 06:36:30 +00:00
|
|
|
|
|
|
|
postScript = lib.mkOption {
|
|
|
|
type = lib.types.str;
|
|
|
|
description = ''
|
|
|
|
A shell script fragment to be executed after the download.
|
|
|
|
'';
|
|
|
|
default = "";
|
|
|
|
example = lib.literalExpression ''
|
|
|
|
$${config.xdg.configHome}/emacs/bin/doom install --no-config --no-fonts --install --force
|
|
|
|
'';
|
|
|
|
};
|
2023-03-13 15:45:17 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
in
|
|
|
|
{
|
|
|
|
options.home.mutableFile = lib.mkOption {
|
2023-03-19 09:16:25 +00:00
|
|
|
type = with lib.types; attrsOf (submodule (fileType config.home.homeDirectory));
|
2023-07-27 03:13:39 +00:00
|
|
|
description = ''
|
2023-03-13 15:45:17 +00:00
|
|
|
An attribute set of mutable files and directories to be declaratively put
|
|
|
|
into the home directory. Take note this is not exactly pure (or
|
|
|
|
idempotent) as it will only do its fetching when the designated file is
|
|
|
|
missing.
|
|
|
|
'';
|
|
|
|
default = { };
|
|
|
|
example = lib.literalExpression ''
|
|
|
|
{
|
|
|
|
"library/dotfiles" = {
|
|
|
|
url = "https://github.com/foo-dogsquared/dotfiles.git";
|
|
|
|
type = "git";
|
|
|
|
};
|
|
|
|
|
|
|
|
"library/projects/keys" = {
|
|
|
|
url = "https://example.com/file.zip";
|
|
|
|
type = "archive";
|
|
|
|
};
|
|
|
|
}
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
config = lib.mkIf (cfg != { }) {
|
2023-03-20 16:17:03 +00:00
|
|
|
systemd.user.services.fetch-mutable-files = {
|
2023-03-13 15:45:17 +00:00
|
|
|
Unit = {
|
2023-03-19 09:16:25 +00:00
|
|
|
Description = "Fetch mutable home-manager-managed files";
|
|
|
|
After = [ "default.target" "network-online.target" ];
|
|
|
|
Wants = [ "network-online.target" ];
|
2023-03-13 15:45:17 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
Service = {
|
|
|
|
# We'll assume this service will have lots of things to download so it
|
|
|
|
# is best to make the temp directory to only last with the service.
|
|
|
|
PrivateUsers = true;
|
|
|
|
PrivateTmp = true;
|
|
|
|
|
|
|
|
Type = "oneshot";
|
|
|
|
RemainAfterExit = true;
|
|
|
|
ExecStart =
|
|
|
|
let
|
|
|
|
mutableFilesCmds = lib.mapAttrsToList
|
|
|
|
(path: value:
|
|
|
|
let
|
|
|
|
url = lib.escapeShellArg value.url;
|
|
|
|
path = lib.escapeShellArg value.path;
|
2023-03-17 14:39:03 +00:00
|
|
|
extraArgs = lib.escapeShellArgs value.extraArgs;
|
2023-07-07 09:11:15 +00:00
|
|
|
isFetchType = type: lib.optionalString (value.type == type);
|
2023-03-13 15:45:17 +00:00
|
|
|
in
|
|
|
|
''
|
2023-07-07 09:11:15 +00:00
|
|
|
${isFetchType "git" "[ -d ${path} ] || git clone ${extraArgs} ${url} ${path}"}
|
|
|
|
${isFetchType "fetch" "[ -e ${path} ] || curl ${extraArgs} ${url} --output ${path}"}
|
|
|
|
${isFetchType "archive" ''
|
2023-03-17 14:39:03 +00:00
|
|
|
[ -e ${path} ] || {
|
|
|
|
filename=$(curl ${extraArgs} --output-dir /tmp --silent --show-error --write-out '%{filename_effective}' --remote-name --remote-header-name --location ${url})
|
2023-03-13 15:45:17 +00:00
|
|
|
${if (value.extractPath != null) then
|
|
|
|
''arc extract "/tmp/$filename" ${lib.escapeShellArg value.extractPath} ${path}''
|
|
|
|
else
|
|
|
|
''arc unarchive "/tmp/$filename" ${path}''
|
|
|
|
}
|
|
|
|
}
|
|
|
|
''}
|
2023-07-07 09:11:15 +00:00
|
|
|
${isFetchType "gopass" ''
|
|
|
|
[ -e ${path} ] || gopass clone ${extraArgs} ${url} --path ${path} ${extraArgs}
|
|
|
|
''}
|
2023-07-22 03:05:31 +00:00
|
|
|
${isFetchType "custom" "[ -e ${path} ] || ${extraArgs}"}
|
2023-09-18 06:36:30 +00:00
|
|
|
${value.postScript}
|
2023-03-13 15:45:17 +00:00
|
|
|
'')
|
|
|
|
cfg;
|
2023-03-23 00:06:44 +00:00
|
|
|
|
2023-08-21 04:15:23 +00:00
|
|
|
script = pkgs.writeShellApplication {
|
|
|
|
name = "fetch-mutable-files";
|
|
|
|
runtimeInputs = with pkgs; [ archiver curl git gopass ];
|
|
|
|
text = "${lib.concatStringsSep "\n" mutableFilesCmds}";
|
|
|
|
};
|
2023-06-08 13:19:17 +00:00
|
|
|
in
|
2023-09-05 22:50:17 +00:00
|
|
|
"${script}/bin/fetch-mutable-files";
|
2023-03-13 15:45:17 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
Install.WantedBy = [ "default.target" ];
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|