{ lib, config, ... }: let inherit (lib) attrValues concatStringsSep mapAttrsToList mkOption optionalString recursiveUpdate; inherit (lib.types) bool loaOf nullOr str submodule; dirOpts = { ... }: { options = { owner = mkOption { default = null; type = nullOr str; }; group = mkOption { default = null; type = nullOr str; }; permissions = mkOption { default = "0700"; type = str; }; activationScripts = mkOption { default = {}; type = loaOf str; }; }; }; applyDirConfig = user: dir: let owner = if dir.owner == null then user else config.users.users.${dir.owner}; group = if dir.group == null then owner.group else dir.group; in '' chmod ${dir.permissions} . chown ${owner.name}:${group} . ${concatStringsSep "\n" (attrValues dir.activationScripts)} ''; in { options = { home = mkOption { default = {}; type = loaOf (submodule (args: recursiveUpdate (dirOpts args) { options = { imperativeNix = mkOption { default = false; type = bool; }; dirs = mkOption { default = {}; type = loaOf (submodule dirOpts); }; }; })); }; }; config = { system.activationScripts.home = { deps = []; text = concatStringsSep "\n" (mapAttrsToList (key: home: let user = config.users.users.${key}; in '' ${optionalString (!home.imperativeNix) '' rm -rf ${user.home}/.nix-{defexpr,profile} ''} pushd ${user.home} >/dev/null ${applyDirConfig user home} ${concatStringsSep "\n" (mapAttrsToList (name: dir: '' mkdir -p ${name} pushd ${name} >/dev/null ${applyDirConfig user dir} popd >/dev/null '') home.dirs)} popd >/dev/null '' ) config.home); }; }; }