main
 1{inputs, ...}: let
 2in {
 3  den.quirks.persist.description = "Persistent directories/files collected from aspects (host)";
 4  den.quirks.cache.description = "Cache directories/files collected from aspects (host)";
 5  den.quirks.persistHome.description = "Persistent directories/files collected from aspects (hjem)";
 6  den.quirks.cacheHome.description = "Cache directories/files collected from aspects (hjem)";
 7
 8  den.aspects.disk.preservation.persist-collector = {
 9    nixos = {
10      persist,
11      cache,
12      lib,
13      config,
14      ...
15    }: let
16      mergePersist = entries: {
17        directories = lib.unique (lib.concatMap (e: e.directories or []) entries);
18        files = lib.unique (lib.concatMap (e: e.files or []) entries);
19      };
20
21      persistData = mergePersist persist;
22      cacheData = mergePersist cache;
23      persistFiles = persistData.files;
24      cacheFiles = cacheData.files;
25
26      # Merge per-user persistence collected from hjem scopes.
27      relayUsers = prefix: let
28        fromHjem = lib.filterAttrs (_: u: (u.environment.persistence or {}) ? ${prefix}) (config.hjem.users or {});
29        merge = userName: fromHjem.${userName}.environment.persistence.${prefix};
30      in
31        lib.mapAttrs (userName: _: merge userName) fromHjem;
32    in {
33      imports = [inputs.preservation.nixosModules.preservation];
34
35      preservation.enable = true;
36      preservation.preserveAt = {
37        "/persist" = {
38          commonMountOptions = ["x-gvfs-hide"];
39          directories = persistData.directories;
40          files = persistFiles;
41          users = relayUsers "persist";
42        };
43        "/cache" = {
44          commonMountOptions = ["x-gvfs-hide"];
45          directories = cacheData.directories;
46          files = cacheFiles;
47          users = relayUsers "cache";
48        };
49      };
50    };
51
52    provides.to-users = {
53      hjem = {
54        persistHome,
55        cacheHome,
56        lib,
57        config,
58        ...
59      }: let
60        _removeHomePrefix = path: lib.removePrefix config.directory path;
61        removeHomePrefix = path:
62          if lib.typeOf path == "string"
63          then _removeHomePrefix path
64          else path // {directory = _removeHomePrefix path.directory;};
65        removeHomePrefixes = paths: lib.map removeHomePrefix paths;
66        mergePersist = entries: {
67          directories = lib.unique (lib.concatMap (e: removeHomePrefixes (e.directories or [])) entries);
68          files = lib.unique (lib.concatMap (e: removeHomePrefixes (e.files or [])) entries);
69        };
70      in {
71        environment.persistence.persist = {
72          directories = (mergePersist persistHome).directories;
73          files = (mergePersist persistHome).files;
74        };
75        environment.persistence.cache = {
76          directories = (mergePersist cacheHome).directories;
77          files = (mergePersist cacheHome).files;
78        };
79      };
80    };
81  };
82}