1
0
Fork 0
mirror of https://github.com/nix-community/home-manager.git synced 2025-12-09 02:21:05 +01:00
home-manager/modules/programs/pimsync/default.nix
Andrew Jeffery 43173abcb4 pimsync: Make storage names unique
This includes the calendar/contacts prefix in the storage name as well
as the pair name to ensure that if the same name is used for contacts
and calendar then it is correctly referenced.
2025-12-03 13:46:21 +01:00

151 lines
4.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;
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 ];
xdg.configFile."pimsync/pimsync.conf".text = lib.hm.generators.toSCFG { } (
accountSettings ++ cfg.settings
);
};
}