Initial commit
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
cfg = config.xdg;
|
||||
username = "someone";
|
||||
fileType = lib.types.submodule {
|
||||
options = {
|
||||
text = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.lines;
|
||||
default = null;
|
||||
};
|
||||
source = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
};
|
||||
mutable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "If true, copy the file instead of symlinking, allowing the application to modify it";
|
||||
};
|
||||
};
|
||||
};
|
||||
userOpts = _: {
|
||||
options = {
|
||||
configFiles = lib.mkOption {
|
||||
type = lib.types.attrsOf fileType;
|
||||
default = {};
|
||||
};
|
||||
cacheFiles = lib.mkOption {
|
||||
type = lib.types.attrsOf fileType;
|
||||
default = {};
|
||||
};
|
||||
dataFiles = lib.mkOption {
|
||||
type = lib.types.attrsOf fileType;
|
||||
default = {};
|
||||
};
|
||||
stateFiles = lib.mkOption {
|
||||
type = lib.types.attrsOf fileType;
|
||||
default = {};
|
||||
};
|
||||
homeFiles = lib.mkOption {
|
||||
type = lib.types.attrsOf fileType;
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mkLinkScript = baseDir: name: file: let
|
||||
target =
|
||||
if file.text != null
|
||||
then pkgs.writeText name file.text
|
||||
else file.source;
|
||||
fullPath = "${baseDir}/${name}";
|
||||
parentDir = builtins.dirOf fullPath;
|
||||
in
|
||||
if file.mutable
|
||||
then ''
|
||||
mkdir -p "${parentDir}"
|
||||
if [ -L "${fullPath}" ]; then
|
||||
# Replace symlink with a copy
|
||||
rm -f "${fullPath}"
|
||||
cp "${target}" "${fullPath}"
|
||||
chmod +w "${fullPath}"
|
||||
elif [ -e "${fullPath}" ]; then
|
||||
:
|
||||
else
|
||||
cp "${target}" "${fullPath}"
|
||||
chmod +w "${fullPath}"
|
||||
fi
|
||||
''
|
||||
else ''
|
||||
mkdir -p "${parentDir}"
|
||||
if [ -L "${fullPath}" ]; then
|
||||
current_target=$(readlink "${fullPath}")
|
||||
if [ "$current_target" != "${target}" ]; then
|
||||
rm -f "${fullPath}"
|
||||
ln -s "${target}" "${fullPath}"
|
||||
fi
|
||||
elif [ -e "${fullPath}" ]; then
|
||||
rm -f "${fullPath}"
|
||||
ln -s "${target}" "${fullPath}"
|
||||
else
|
||||
ln -s "${target}" "${fullPath}"
|
||||
fi
|
||||
'';
|
||||
in {
|
||||
options = {
|
||||
users.users = lib.mkOption {type = lib.types.attrsOf (lib.types.submodule userOpts);};
|
||||
home = {
|
||||
homeDirectory = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/home/${username}";
|
||||
};
|
||||
file = lib.mkOption {
|
||||
type = lib.types.attrsOf fileType;
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
xdg = {
|
||||
configHome = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/home/${username}/.config";
|
||||
};
|
||||
cacheHome = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/home/${username}/.cache";
|
||||
};
|
||||
dataHome = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/home/${username}/.local/share";
|
||||
};
|
||||
stateHome = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/home/${username}/.local/state";
|
||||
};
|
||||
runtimeDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/run/user/1000";
|
||||
};
|
||||
configFile = lib.mkOption {
|
||||
type = lib.types.attrsOf fileType;
|
||||
default = {};
|
||||
};
|
||||
cacheFile = lib.mkOption {
|
||||
type = lib.types.attrsOf fileType;
|
||||
default = {};
|
||||
};
|
||||
dataFile = lib.mkOption {
|
||||
type = lib.types.attrsOf fileType;
|
||||
default = {};
|
||||
};
|
||||
stateFile = lib.mkOption {
|
||||
type = lib.types.attrsOf fileType;
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
users.users.${username} = {
|
||||
configFiles = cfg.configFile;
|
||||
cacheFiles = cfg.cacheFile;
|
||||
dataFiles = cfg.dataFile;
|
||||
stateFiles = cfg.stateFile;
|
||||
homeFiles = config.home.file;
|
||||
};
|
||||
|
||||
environment.sessionVariables = {
|
||||
XDG_CONFIG_HOME = cfg.configHome;
|
||||
XDG_CACHE_HOME = cfg.cacheHome;
|
||||
XDG_DATA_HOME = cfg.dataHome;
|
||||
XDG_STATE_HOME = cfg.stateHome;
|
||||
};
|
||||
|
||||
system.activationScripts.xdgUserFiles = lib.stringAfter ["users"] ''
|
||||
${lib.concatStringsSep "\n" (
|
||||
lib.flatten (
|
||||
lib.mapAttrsToList (
|
||||
user: userCfg:
|
||||
(lib.mapAttrsToList (mkLinkScript cfg.configHome) userCfg.configFiles)
|
||||
++ (lib.mapAttrsToList (mkLinkScript cfg.cacheHome) userCfg.cacheFiles)
|
||||
++ (lib.mapAttrsToList (mkLinkScript cfg.dataHome) userCfg.dataFiles)
|
||||
++ (lib.mapAttrsToList (mkLinkScript cfg.stateHome) userCfg.stateFiles)
|
||||
++ (lib.mapAttrsToList (mkLinkScript config.home.homeDirectory) userCfg.homeFiles)
|
||||
)
|
||||
config.users.users
|
||||
)
|
||||
)}
|
||||
'';
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user