{ homeDirectory, lib, pkgs }: with lib; { # Constructs a type suitable for a `home.file` like option. The # target path may be either absolute or relative, in which case it # is relative the `basePath` argument (which itself must be an # absolute path). # # Arguments: # - basePathDesc docbook compatible description of the base path # - basePath the file base path fileType = basePathDesc: basePath: types.attrsOf (types.submodule ( { name, config, ... }: { options = { target = mkOption { type = types.str; apply = p: let absPath = if hasPrefix "/" p then p else "${basePath}/${p}"; in removePrefix (homeDirectory + "/") absPath; defaultText = literalExpression ""; description = '' Path to target file relative to ${basePathDesc}. ''; }; text = mkOption { default = null; type = types.nullOr types.lines; description = '' Text of the file. If this option is null then home.file.<name?>.source must be set. ''; }; source = mkOption { type = types.path; description = '' Path of the source file or directory. If home.file.<name?>.text is non-null then this option will automatically point to a file containing that text. ''; }; executable = mkOption { type = types.nullOr types.bool; default = null; description = '' Set the execute bit. If null, defaults to the mode of the source file or to false for files created through the text option. ''; }; recursive = mkOption { type = types.bool; default = false; description = '' If the file source is a directory, then this option determines whether the directory should be recursively linked to the target location. This option has no effect if the source is a file. If false (the default) then the target will be a symbolic link to the source directory. If true then the target will be a directory structure matching the source's but whose leafs are symbolic links to the files of the source directory. ''; }; onChange = mkOption { type = types.lines; default = ""; description = '' Shell commands to run when file has changed between generations. The script will be run after the new files have been linked into place. Note, this code is always run when recursive is enabled. ''; }; force = mkOption { type = types.bool; default = false; visible = false; description = '' Whether the target path should be unconditionally replaced by the managed file source. Warning, this will silently delete the target regardless of whether it is a file or link. ''; }; }; config = { target = mkDefault name; source = mkIf (config.text != null) ( mkDefault (pkgs.writeTextFile { inherit (config) executable text; name = hm.strings.storeFileName name; }) ); }; } )); }