2.home-manager/modules/programs/pimsync/default.nix
Austin Horstman 4e235a8746 treewide: nix fmt
nix fmt updated in nixpkgs with string handling changes

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-13 22:51:16 -06:00

172 lines
5.5 KiB
Nix

{
config,
lib,
pkgs,
...
}:
{
options = {
programs.pimsync = {
enable = lib.mkEnableOption "pimsync";
package = lib.mkPackageOption pkgs "pimsync" { };
settings = lib.mkOption {
description = ''
Settings to be added to pimsync.conf.
See {manpage}`pimsync.conf(5)`.
'';
type = lib.hm.types.SCFGDirectives;
default = [
{
name = "status_path";
params = [ "${config.xdg.dataHome}/pimsync/status" ];
}
];
defaultText = lib.literalExpression ''
[
{
name = "status_path";
params = [ "''${config.xdg.dataHome}/pimsync/status" ];
}
]
'';
};
};
};
config =
let
cfg = config.programs.pimsync;
calendarAccounts = lib.filterAttrs (_: v: v.pimsync.enable) config.accounts.calendar.accounts;
contactAccounts = lib.filterAttrs (_: v: v.pimsync.enable) config.accounts.contact.accounts;
# Provides a very naïve translation of an (non-nested) attribute set to a SCFGDirective
attrsToDirectives = lib.mapAttrsToList (
name: value: {
inherit name;
params = lib.toList value;
}
);
localStorage = calendar: name: acc: {
name = "storage";
params = [ "${if calendar then "calendar" else "contacts"}-${name}-local" ];
children =
(attrsToDirectives {
inherit (acc.local) path;
fileext = acc.local.fileExt;
type = if calendar then "vdir/icalendar" else "vdir/vcard";
})
++ acc.pimsync.extraLocalStorageDirectives;
};
remoteStorage = calendar: name: acc: {
name = "storage";
params = [ "${if calendar then "calendar" else "contacts"}-${name}-remote" ];
children =
(attrsToDirectives {
inherit (acc.remote) url;
username = acc.remote.userName;
type =
if !calendar then
"carddav"
else if acc.remote.type == "caldav" then
acc.remote.type
else
"webcal";
})
++ lib.optional (acc.remote.passwordCommand != null) {
name = "password";
children = lib.singleton {
name = "cmd";
params = acc.remote.passwordCommand;
};
}
++ acc.pimsync.extraRemoteStorageDirectives;
};
pair = calendar: name: acc: {
name = "pair";
params = lib.singleton "${if calendar then "calendar" else "contacts"}-${name}";
children =
(attrsToDirectives {
storage_a = "${if calendar then "calendar" else "contacts"}-${name}-local";
storage_b = "${if calendar then "calendar" else "contacts"}-${name}-remote";
})
++ acc.pimsync.extraPairDirectives;
};
multiMapAttrsToList = calendar: attrs: lib.concatMap (f: lib.mapAttrsToList (f calendar) attrs);
calendarConfig = multiMapAttrsToList true calendarAccounts [
localStorage
remoteStorage
pair
];
contactConfig = multiMapAttrsToList false contactAccounts [
localStorage
remoteStorage
pair
];
accountSettings = calendarConfig ++ contactConfig;
localStorageDir = name: acc: lib.attrsets.getAttrFromPath [ "local" "path" ] acc;
calendarLocalStorageDirs = lib.mapAttrsToList localStorageDir calendarAccounts;
contactLocalStorageDirs = lib.mapAttrsToList localStorageDir contactAccounts;
localStorageDirs = calendarLocalStorageDirs ++ contactLocalStorageDirs;
mkTmpFileRule = (dir: "d ${dir} 0755 ${config.home.username} ${config.home.username} - -");
tmpFileRules = map mkTmpFileRule localStorageDirs;
in
lib.mkIf cfg.enable {
meta.maintainers = [ lib.maintainers.antonmosich ];
assertions =
let
contactRemotes = lib.mapAttrsToList (_: acc: {
assertion = acc.remote.type == "carddav";
message = "pimsync can only handle contact remotes of type carddav";
}) contactAccounts;
calendarRemotes = lib.mapAttrsToList (_: acc: {
assertion = acc.remote.type == "caldav" || acc.remote.type == "http";
message = "pimsync can only handle calendar remotes of types http or caldav";
}) calendarAccounts;
sharedAsserts = lib.mapAttrsToList (
_: acc: [
{
assertion = acc.local.type == "filesystem";
message = "pimsync only supports type filesystem for local";
}
]
);
in
lib.flatten [
contactRemotes
calendarRemotes
(sharedAsserts contactAccounts)
(sharedAsserts calendarAccounts)
];
home.packages = [ cfg.package ];
systemd.user.tmpfiles.rules = lib.optionals pkgs.stdenv.hostPlatform.isLinux tmpFileRules;
home.activation.createDavDirectories = lib.mkIf (!pkgs.stdenv.hostPlatform.isLinux) (
let
directoriesList = localStorageDirs;
mkdir = (dir: ''[[ -L "${dir}" ]] || run mkdir -p $VERBOSE_ARG "${dir}"'');
in
lib.hm.dag.entryAfter [ "linkGeneration" ] (
lib.strings.concatMapStringsSep "\n" mkdir directoriesList
)
);
xdg.configFile."pimsync/pimsync.conf".text = lib.hm.generators.toSCFG { } (
accountSettings ++ cfg.settings
);
};
}