dotfiles

My PC Dotfiles & Website

_mutable.nix (2280B)


# https://gist.github.com/piousdeer/b29c272eaeba398b864da6abf6cb5daa
{
  config,
  lib,
  ...
}: let
  inherit
    (builtins)
    attrValues
    concatLists
    filter
    foldl'
    map
    ;

  inherit
    (lib)
    assertMsg
    concatLines
    escapeShellArg
    getAttrFromPath
    hm
    mkOption
    recursiveUpdate
    setAttrByPath
    types
    ;

  fileOptionAttrPaths = [
    [
      "home"
      "file"
    ]
    [
      "xdg"
      "configFile"
    ]
    [
      "xdg"
      "dataFile"
    ]
  ];
in {
  options = let
    mergeAttrsList = foldl' recursiveUpdate {};
    fileAttrsType = types.attrsOf (
      types.submodule (_: {
        options.mutable = mkOption {
          type = types.bool;
          default = false;
          description = ''
            Whether to copy the file without the read-only attribute instead of symlinking.
            If you set this to 'true', you must also set 'force' to 'true'.
            Mutable files are not removed when you remove them from your configuration.
            This option is useful for programs that don't have a very good support for read-only configurations.
          '';
        };
      })
    );
  in
    mergeAttrsList (
      map (
        attrPath:
          setAttrByPath attrPath (mkOption {
            type = fileAttrsType;
          })
      )
      fileOptionAttrPaths
    );

  config = {
    home.activation.mutableFileGeneration = let
      allFiles = concatLists (
        map (attrPath: attrValues (getAttrFromPath attrPath config)) fileOptionAttrPaths
      );

      filterMutableFiles = filter (
        file:
          (file.mutable or false)
          && assertMsg file.force "if you specify 'mutable' to 'true' on a file, you must also set 'force' to 'true'"
      );

      mutableFiles = filterMutableFiles allFiles;

      toCommand = file: let
        source = escapeShellArg file.source;
        target = escapeShellArg file.target;
      in ''
        $VERBOSE_ECHO "${source} -> ${target}"
        $DRY_RUN_CMD cp --remove-destination --no-preserve=mode ${source} ${target}
      '';

      command =
        ''echo "Copying mutable home files for $HOME"''
        + concatLines (map toCommand mutableFiles);
    in
      hm.dag.entryAfter ["linkGeneration"] command;
  };
}