dotfiles

My PC Dotfiles & Website

modules/system/user/_mutable.nix (2280B)


 1# https://gist.github.com/piousdeer/b29c272eaeba398b864da6abf6cb5daa
 2{
 3  config,
 4  lib,
 5  ...
 6}: let
 7  inherit
 8    (builtins)
 9    attrValues
10    concatLists
11    filter
12    foldl'
13    map
14    ;
15
16  inherit
17    (lib)
18    assertMsg
19    concatLines
20    escapeShellArg
21    getAttrFromPath
22    hm
23    mkOption
24    recursiveUpdate
25    setAttrByPath
26    types
27    ;
28
29  fileOptionAttrPaths = [
30    [
31      "home"
32      "file"
33    ]
34    [
35      "xdg"
36      "configFile"
37    ]
38    [
39      "xdg"
40      "dataFile"
41    ]
42  ];
43in {
44  options = let
45    mergeAttrsList = foldl' recursiveUpdate {};
46    fileAttrsType = types.attrsOf (
47      types.submodule (_: {
48        options.mutable = mkOption {
49          type = types.bool;
50          default = false;
51          description = ''
52            Whether to copy the file without the read-only attribute instead of symlinking.
53            If you set this to 'true', you must also set 'force' to 'true'.
54            Mutable files are not removed when you remove them from your configuration.
55            This option is useful for programs that don't have a very good support for read-only configurations.
56          '';
57        };
58      })
59    );
60  in
61    mergeAttrsList (
62      map (
63        attrPath:
64          setAttrByPath attrPath (mkOption {
65            type = fileAttrsType;
66          })
67      )
68      fileOptionAttrPaths
69    );
70
71  config = {
72    home.activation.mutableFileGeneration = let
73      allFiles = concatLists (
74        map (attrPath: attrValues (getAttrFromPath attrPath config)) fileOptionAttrPaths
75      );
76
77      filterMutableFiles = filter (
78        file:
79          (file.mutable or false)
80          && assertMsg file.force "if you specify 'mutable' to 'true' on a file, you must also set 'force' to 'true'"
81      );
82
83      mutableFiles = filterMutableFiles allFiles;
84
85      toCommand = file: let
86        source = escapeShellArg file.source;
87        target = escapeShellArg file.target;
88      in ''
89        $VERBOSE_ECHO "${source} -> ${target}"
90        $DRY_RUN_CMD cp --remove-destination --no-preserve=mode ${source} ${target}
91      '';
92
93      command =
94        ''echo "Copying mutable home files for $HOME"''
95        + concatLines (map toCommand mutableFiles);
96    in
97      hm.dag.entryAfter ["linkGeneration"] command;
98  };
99}