1
0
Fork 0
mirror of https://github.com/nix-community/home-manager synced 2024-11-26 21:19:45 +01:00

Apply nixfmt

This commit is contained in:
Robert Helgesson 2020-04-26 15:40:37 +02:00
parent b0df7d9919
commit a4a4774423
No known key found for this signature in database
GPG key ID: 36BDAA14C2797E89
7 changed files with 337 additions and 323 deletions

View file

@ -6,36 +6,37 @@ let
cfg = config.accounts.calendar; cfg = config.accounts.calendar;
localModule = name: types.submodule { localModule = name:
options = { types.submodule {
path = mkOption { options = {
type = types.str; path = mkOption {
default = "${cfg.basePath}/${name}"; type = types.str;
defaultText = "accounts.contact.basePath/name"; default = "${cfg.basePath}/${name}";
description = "The path of the storage."; defaultText = "accounts.contact.basePath/name";
}; description = "The path of the storage.";
};
type = mkOption { type = mkOption {
type = types.enum [ "filesystem" "singlefile" ]; type = types.enum [ "filesystem" "singlefile" ];
description = "The type of the storage."; description = "The type of the storage.";
}; };
fileExt = mkOption { fileExt = mkOption {
type = types.nullOr types.str; type = types.nullOr types.str;
default = null; default = null;
description = "The file extension to use."; description = "The file extension to use.";
}; };
encoding = mkOption { encoding = mkOption {
type = types.nullOr types.str; type = types.nullOr types.str;
default = null; default = null;
description = '' description = ''
File encoding for items, both content and file name. File encoding for items, both content and file name.
Defaults to UTF-8. Defaults to UTF-8.
''; '';
};
}; };
}; };
};
remoteModule = types.submodule { remoteModule = types.submodule {
options = { options = {
@ -121,21 +122,15 @@ let
}; };
}; };
config = { config = { name = name; };
name = name;
};
}; };
in in {
{
options.accounts.calendar = { options.accounts.calendar = {
basePath = mkOption { basePath = mkOption {
type = types.str; type = types.str;
apply = p: apply = p:
if hasPrefix "/" p if hasPrefix "/" p then p else "${config.home.homeDirectory}/${p}";
then p
else "${config.home.homeDirectory}/${p}";
description = '' description = ''
The base directory in which to save calendars. May be a The base directory in which to save calendars. May be a
relative path, in which case it is relative the home relative path, in which case it is relative the home
@ -150,25 +145,19 @@ in
(import ../programs/khal-accounts.nix) (import ../programs/khal-accounts.nix)
(import ../programs/khal-calendar-accounts.nix) (import ../programs/khal-calendar-accounts.nix)
]); ]);
default = {}; default = { };
description = "List of calendars."; description = "List of calendars.";
}; };
}; };
config = mkIf (cfg.accounts != {}) { config = mkIf (cfg.accounts != { }) {
assertions = assertions = let
let primaries =
primaries = catAttrs "name" (filter (a: a.primary) (attrValues cfg.accounts));
catAttrs "name" in [{
(filter (a: a.primary) assertion = length primaries <= 1;
(attrValues cfg.accounts)); message = "Must have at most one primary calendar account but found "
in + toString (length primaries) + ", namely "
[{ + concatStringsSep ", " primaries;
assertion = length primaries <= 1; }];
message =
"Must have at most one primary calendar account but found "
+ toString (length primaries)
+ ", namely "
+ concatStringsSep ", " primaries;
}];
}; };
} }

View file

@ -6,36 +6,37 @@ let
cfg = config.accounts.contact; cfg = config.accounts.contact;
localModule = name: types.submodule { localModule = name:
options = { types.submodule {
path = mkOption { options = {
type = types.str; path = mkOption {
default = "${cfg.basePath}/${name}"; type = types.str;
defaultText = "accounts.contact.basePath/name"; default = "${cfg.basePath}/${name}";
description = "The path of the storage."; defaultText = "accounts.contact.basePath/name";
}; description = "The path of the storage.";
};
type = mkOption { type = mkOption {
type = types.enum [ "filesystem" "singlefile" ]; type = types.enum [ "filesystem" "singlefile" ];
description = "The type of the storage."; description = "The type of the storage.";
}; };
fileExt = mkOption { fileExt = mkOption {
type = types.nullOr types.str; type = types.nullOr types.str;
default = null; default = null;
description = "The file extension to use."; description = "The file extension to use.";
}; };
encoding = mkOption { encoding = mkOption {
type = types.nullOr types.str; type = types.nullOr types.str;
default = null; default = null;
description = '' description = ''
File encoding for items, both content and file name. File encoding for items, both content and file name.
Defaults to UTF-8. Defaults to UTF-8.
''; '';
};
}; };
}; };
};
remoteModule = types.submodule { remoteModule = types.submodule {
options = { options = {
@ -104,21 +105,15 @@ let
}; };
}; };
config = { config = { name = name; };
name = name;
};
}; };
in in {
{
options.accounts.contact = { options.accounts.contact = {
basePath = mkOption { basePath = mkOption {
type = types.str; type = types.str;
apply = p: apply = p:
if hasPrefix "/" p if hasPrefix "/" p then p else "${config.home.homeDirectory}/${p}";
then p
else "${config.home.homeDirectory}/${p}";
description = '' description = ''
The base directory in which to save contacts. May be a The base directory in which to save contacts. May be a
relative path, in which case it is relative the home relative path, in which case it is relative the home
@ -132,7 +127,7 @@ in
(import ../programs/vdirsyncer-accounts.nix) (import ../programs/vdirsyncer-accounts.nix)
(import ../programs/khal-accounts.nix) (import ../programs/khal-accounts.nix)
]); ]);
default = {}; default = { };
description = "List of contacts."; description = "List of contacts.";
}; };
}; };

View file

@ -5,7 +5,7 @@ with lib;
{ {
options.khal = { options.khal = {
type = mkOption { type = mkOption {
type = types.nullOr (types.enum [ "calendar" "discover"]); type = types.nullOr (types.enum [ "calendar" "discover" ]);
default = null; default = null;
description = '' description = ''
There is no description of this option. There is no description of this option.
@ -23,9 +23,22 @@ with lib;
color = mkOption { color = mkOption {
type = types.nullOr (types.enum [ type = types.nullOr (types.enum [
"black" "white" "brown" "yellow" "dark gray" "dark green" "dark blue" "black"
"light gray" "light green" "light blue" "dark magenta" "dark cyan" "white"
"dark red" "light magenta" "light cyan" "light red" "brown"
"yellow"
"dark gray"
"dark green"
"dark blue"
"light gray"
"light green"
"light blue"
"dark magenta"
"dark cyan"
"dark red"
"light magenta"
"light cyan"
"light red"
]); ]);
default = null; default = null;
description = '' description = ''

View file

@ -10,83 +10,82 @@ let
khalCalendarAccounts = khalCalendarAccounts =
filterAttrs (_: a: a.khal.enable) config.accounts.calendar.accounts; filterAttrs (_: a: a.khal.enable) config.accounts.calendar.accounts;
khalContactAccounts = khalContactAccounts = mapAttrs (_: v: v // { type = "birthdays"; })
mapAttrs (_: v: v // { type = "birthdays"; })
(filterAttrs (_: a: a.khal.enable) config.accounts.contact.accounts); (filterAttrs (_: a: a.khal.enable) config.accounts.contact.accounts);
khalAccounts = khalCalendarAccounts // khalContactAccounts; khalAccounts = khalCalendarAccounts // khalContactAccounts;
primaryAccount = primaryAccount = findSingle (a: a.primary) null null
findSingle (a: a.primary) null null (mapAttrsToList (n: v: v // { name = n; }) khalAccounts);
(mapAttrsToList (n: v: v // {name= n;}) khalAccounts);
definedAttrs = filterAttrs (_: v: !isNull v); definedAttrs = filterAttrs (_: v: !isNull v);
toKeyValueIfDefined = attrs: toKeyValueIfDefined = attrs: generators.toKeyValue { } (definedAttrs attrs);
generators.toKeyValue {} (definedAttrs attrs);
genCalendarStr = name: value: genCalendarStr = name: value:
concatStringsSep "\n" ( concatStringsSep "\n" ([
[ "[[${name}]]"
"[[${name}]]" "path = ${
"path = ${value.local.path + "/" + (optionalString (value.khal.type == "discover") value.khal.glob)}" value.local.path + "/"
] + (optionalString (value.khal.type == "discover") value.khal.glob)
++ optional (value.khal.readOnly) "readonly = True" }"
++ [ (toKeyValueIfDefined (getAttrs [ "type" "color" "priority" ] value.khal)) ] ] ++ optional (value.khal.readOnly) "readonly = True" ++ [
++ ["\n"] (toKeyValueIfDefined (getAttrs [ "type" "color" "priority" ] value.khal))
); ] ++ [ "\n" ]);
localeFormatOptions = let T = lib.types; in mapAttrs (n: v: v // { localeFormatOptions = let T = lib.types;
description = v.description + '' in mapAttrs (n: v:
v // {
description = v.description + ''
Format strings are for python 'strftime', similarly to man 3 strftime. Format strings are for python 'strftime', similarly to man 3 strftime.
'';
}) {
dateformat = {
type = T.str;
default = "%x";
description = ''
khal will display and understand all dates in this format.
''; '';
}) {
dateformat = {
type = T.str;
default = "%x";
description = ''
khal will display and understand all dates in this format.
'';
};
timeformat = {
type = T.str;
default = "%X";
description = ''
khal will display and understand all times in this format.
'';
};
datetimeformat = {
type = T.str;
default = "%c";
description = ''
khal will display and understand all datetimes in this format.
'';
};
longdateformat = {
type = T.str;
default = "%x";
description = ''
khal will display and understand all dates in this format.
It should contain a year (e.g. %Y).
'';
};
longdatetimeformat = {
type = T.str;
default = "%c";
description = ''
khal will display and understand all datetimes in this format.
It should contain a year (e.g. %Y).
'';
};
}; };
timeformat = { localeOptions = let T = lib.types;
type = T.str; in localeFormatOptions // {
default = "%X";
description = ''
khal will display and understand all times in this format.
'';
};
datetimeformat = {
type = T.str;
default = "%c";
description = ''
khal will display and understand all datetimes in this format.
'';
};
longdateformat = {
type = T.str;
default = "%x";
description = ''
khal will display and understand all dates in this format.
It should contain a year (e.g. %Y).
'';
};
longdatetimeformat = {
type = T.str;
default = "%c";
description = ''
khal will display and understand all datetimes in this format.
It should contain a year (e.g. %Y).
'';
};
};
localeOptions = let T = lib.types; in localeFormatOptions // {
unicode_symbols = { unicode_symbols = {
type = T.bool; type = T.bool;
default = true; default = true;
@ -136,9 +135,7 @@ let
}; };
}; };
in in {
{
options.programs.khal = { options.programs.khal = {
enable = mkEnableOption "khal, a CLI calendar application"; enable = mkEnableOption "khal, a CLI calendar application";
locale = mkOption { locale = mkOption {
@ -152,23 +149,20 @@ in
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
home.packages = [ pkgs.khal ]; home.packages = [ pkgs.khal ];
xdg.configFile."khal/config".text = concatStringsSep "\n" ( xdg.configFile."khal/config".text = concatStringsSep "\n" ([ "[calendars]" ]
[ ++ mapAttrsToList genCalendarStr khalAccounts ++ [
"[calendars]" (generators.toINI { } {
]
++ mapAttrsToList genCalendarStr khalAccounts
++
[
(generators.toINI {} {
locale = definedAttrs (cfg.locale // { _module = null; }); locale = definedAttrs (cfg.locale // { _module = null; });
default = optionalAttrs (!isNull primaryAccount) { default = optionalAttrs (!isNull primaryAccount) {
default_calendar = if isNull primaryAccount.primaryCollection then primaryAccount.name else primaryAccount.primaryCollection; default_calendar = if isNull primaryAccount.primaryCollection then
primaryAccount.name
else
primaryAccount.primaryCollection;
}; };
}) })
] ]);
);
}; };
} }

View file

@ -6,9 +6,7 @@ let
collection = types.either types.str (types.listOf types.str); collection = types.either types.str (types.listOf types.str);
in in {
{
options.vdirsyncer = { options.vdirsyncer = {
enable = mkEnableOption "synchronization using vdirsyncer"; enable = mkEnableOption "synchronization using vdirsyncer";
@ -21,10 +19,8 @@ in
}; };
conflictResolution = mkOption { conflictResolution = mkOption {
type = type = types.nullOr
types.nullOr (types.either (types.enum [ "remote wins" "local wins" ])
(types.either
(types.enum ["remote wins" "local wins"])
(types.listOf types.str)); (types.listOf types.str));
default = null; default = null;
description = '' description = ''
@ -52,7 +48,7 @@ in
metadata = mkOption { metadata = mkOption {
type = types.listOf types.str; type = types.listOf types.str;
default = []; default = [ ];
example = [ "color" "displayname" ]; example = [ "color" "displayname" ];
description = '' description = ''
Metadata keys that should be synchronized when vdirsyncer Metadata keys that should be synchronized when vdirsyncer
@ -115,7 +111,7 @@ in
}; };
auth = mkOption { auth = mkOption {
type = types.nullOr (types.enum ["basic" "digest" "guess"]); type = types.nullOr (types.enum [ "basic" "digest" "guess" ]);
default = null; default = null;
description = '' description = ''
Authentication settings. The default is <literal>basic</literal>. Authentication settings. The default is <literal>basic</literal>.
@ -128,7 +124,7 @@ in
description = '' description = ''
Either a path to a certificate with a client certificate and Either a path to a certificate with a client certificate and
the key or a list of paths to the files with them. the key or a list of paths to the files with them.
''; '';
}; };
userAgent = mkOption { userAgent = mkOption {

View file

@ -6,116 +6,133 @@ let
cfg = config.programs.vdirsyncer; cfg = config.programs.vdirsyncer;
vdirsyncerCalendarAccounts = vdirsyncerCalendarAccounts = filterAttrs (_: v: v.vdirsyncer.enable)
filterAttrs (_: v: v.vdirsyncer.enable) (mapAttrs' (n: v: nameValuePair ("calendar_" + n) v)
(mapAttrs' (n: v: nameValuePair ("calendar_" + n) v) config.accounts.calendar.accounts); config.accounts.calendar.accounts);
vdirsyncerContactAccounts = vdirsyncerContactAccounts = filterAttrs (_: v: v.vdirsyncer.enable)
filterAttrs (_: v: v.vdirsyncer.enable) (mapAttrs' (n: v: nameValuePair ("contacts_" + n) v)
(mapAttrs' (n: v: nameValuePair ("contacts_" + n) v) config.accounts.contact.accounts); config.accounts.contact.accounts);
vdirsyncerAccounts = vdirsyncerCalendarAccounts // vdirsyncerContactAccounts; vdirsyncerAccounts = vdirsyncerCalendarAccounts // vdirsyncerContactAccounts;
wrap = s: ''"${s}"''; wrap = s: ''"${s}"'';
listString = l: ''[${concatStringsSep ", " l}]''; listString = l: "[${concatStringsSep ", " l}]";
boolString = b: if b then "true" else "false"; boolString = b: if b then "true" else "false";
localStorage = a: localStorage = a:
filterAttrs (_: v: v != null) filterAttrs (_: v: v != null)
((getAttrs [ "type" "fileExt" "encoding" ] a.local) // { ((getAttrs [ "type" "fileExt" "encoding" ] a.local) // {
path = a.local.path; path = a.local.path;
postHook = postHook = pkgs.writeShellScriptBin "post-hook" a.vdirsyncer.postHook
pkgs.writeShellScriptBin "post-hook" a.vdirsyncer.postHook + "/bin/post-hook";
+ "/bin/post-hook"; });
});
remoteStorage = a: remoteStorage = a:
filterAttrs (_: v: v != null) filterAttrs (_: v: v != null) ((getAttrs [
((getAttrs [ "type"
"type" "url"
"url" "userName"
"userName" #"userNameCommand"
#"userNameCommand" "passwordCommand"
"passwordCommand" ] a.remote) // (if a.vdirsyncer == null then
] a.remote) // { }
(if a.vdirsyncer == null else
then {} getAttrs [
else getAttrs [ "itemTypes"
"itemTypes" "verify"
"verify" "verifyFingerprint"
"verifyFingerprint" "auth"
"auth" "authCert"
"authCert" "userAgent"
"userAgent" "tokenFile"
"tokenFile" "clientIdCommand"
"clientIdCommand" "clientSecretCommand"
"clientSecretCommand" "timeRange"
"timeRange" ] a.vdirsyncer));
] a.vdirsyncer));
pair = a: pair = a:
with a.vdirsyncer; with a.vdirsyncer;
filterAttrs (k: v: k == "collections" || (v != null && v != [])) filterAttrs (k: v: k == "collections" || (v != null && v != [ ]))
(getAttrs [ "collections" "conflictResolution" "metadata" "partialSync" ] a.vdirsyncer); (getAttrs [ "collections" "conflictResolution" "metadata" "partialSync" ]
a.vdirsyncer);
pairs = mapAttrs (_: v: pair v) vdirsyncerAccounts; pairs = mapAttrs (_: v: pair v) vdirsyncerAccounts;
localStorages = mapAttrs (_: v: localStorage v) vdirsyncerAccounts; localStorages = mapAttrs (_: v: localStorage v) vdirsyncerAccounts;
remoteStorages = mapAttrs (_: v: remoteStorage v) vdirsyncerAccounts; remoteStorages = mapAttrs (_: v: remoteStorage v) vdirsyncerAccounts;
optionString = n: v: optionString = n: v:
if (n == "type") then ''type = "${v}"'' if (n == "type") then
else if (n == "path") then ''path = "${v}"'' ''type = "${v}"''
else if (n == "fileExt") then ''fileext = "${v}"'' else if (n == "path") then
else if (n == "encoding") then ''encoding = "${v}"'' ''path = "${v}"''
else if (n == "postHook") then ''post_hook = "${v}"'' else if (n == "fileExt") then
else if (n == "url") then ''url = "${v}"'' ''fileext = "${v}"''
else if (n == "timeRange") then '' else if (n == "encoding") then
start_date = "${v.start}" ''encoding = "${v}"''
end_date = "${v.end}"'' else if (n == "postHook") then
else if (n == "itemTypes") then '' ''post_hook = "${v}"''
item_types = ${listString (map wrap v)}'' else if (n == "url") then
else if (n == "userName") then ''username = "${v}"'' ''url = "${v}"''
else if (n == "userNameCommand") then '' else if (n == "timeRange") then ''
username.fetch = ${listString (map wrap (["command"] ++ v))}'' start_date = "${v.start}"
else if (n == "password") then ''password = "${v}"'' end_date = "${v.end}"'' else if (n == "itemTypes") then
else if (n == "passwordCommand") then '' "item_types = ${listString (map wrap v)}"
password.fetch = ${listString (map wrap (["command"] ++ v))}'' else if (n == "userName") then
else if (n == "passwordPrompt") then '' ''username = "${v}"''
password.fetch = ["prompt", "${v}"]'' else if (n == "userNameCommand") then
else if (n == "verify") then '' "username.fetch = ${listString (map wrap ([ "command" ] ++ v))}"
verify = ${if v then "true" else "false"}'' else if (n == "password") then
else if (n == "verifyFingerprint") then '' ''password = "${v}"''
verify_fingerprint = "${v}"'' else if (n == "passwordCommand") then
else if (n == "auth") then ''auth = "${v}"'' "password.fetch = ${listString (map wrap ([ "command" ] ++ v))}"
else if (n == "authCert" && isString(v)) then '' else if (n == "passwordPrompt") then
auth_cert = "${v}"'' ''password.fetch = ["prompt", "${v}"]''
else if (n == "authCert") then '' else if (n == "verify") then
auth_cert = ${listString (map wrap v)}'' "verify = ${if v then "true" else "false"}"
else if (n == "userAgent") then ''useragent = "${v}"'' else if (n == "verifyFingerprint") then
else if (n == "tokenFile") then ''token_file = "${v}"'' ''verify_fingerprint = "${v}"''
else if (n == "clientId") then ''client_id = "${v}"'' else if (n == "auth") then
else if (n == "clientIdCommand") then '' ''auth = "${v}"''
client_id.fetch = ${listString (map wrap (["command"] ++ v))}'' else if (n == "authCert" && isString (v)) then
else if (n == "clientSecret") then ''client_secret = "${v}"'' ''auth_cert = "${v}"''
else if (n == "clientSecretCommand") then '' else if (n == "authCert") then
client_secret.fetch = ${listString (map wrap (["command"] ++ v))}'' "auth_cert = ${listString (map wrap v)}"
else if (n == "metadata") then ''metadata = ${listString (map wrap v)}'' else if (n == "userAgent") then
else if (n == "partialSync") then ''partial_sync = "${v}"'' ''useragent = "${v}"''
else if (n == "collections") then else if (n == "tokenFile") then
let ''token_file = "${v}"''
contents = map (c: if (isString c) else if (n == "clientId") then
then ''"${c}"'' ''client_id = "${v}"''
else listString (map wrap c)) v; else if (n == "clientIdCommand") then
in ''collections = ${if ((isNull v) || v == []) then "null" else listString contents}'' "client_id.fetch = ${listString (map wrap ([ "command" ] ++ v))}"
else if (n == "conflictResolution") then else if (n == "clientSecret") then
if v == "remote wins" ''client_secret = "${v}"''
then ''conflict_resolution = "a wins"'' else if (n == "clientSecretCommand") then
else if v == "local wins" "client_secret.fetch = ${listString (map wrap ([ "command" ] ++ v))}"
then ''conflict_resolution = "b wins"'' else if (n == "metadata") then
else ''conflict_resolution = ${listString (map wrap (["command"] ++ v))}'' "metadata = ${listString (map wrap v)}"
else throw "Unrecognized option: ${n}"; else if (n == "partialSync") then
''partial_sync = "${v}"''
else if (n == "collections") then
let
contents =
map (c: if (isString c) then ''"${c}"'' else listString (map wrap c))
v;
in "collections = ${
if ((isNull v) || v == [ ]) then "null" else listString contents
}"
else if (n == "conflictResolution") then
if v == "remote wins" then
''conflict_resolution = "a wins"''
else if v == "local wins" then
''conflict_resolution = "b wins"''
else
"conflict_resolution = ${listString (map wrap ([ "command" ] ++ v))}"
else
throw "Unrecognized option: ${n}";
attrsString = a: concatStringsSep "\n" (mapAttrsToList optionString a); attrsString = a: concatStringsSep "\n" (mapAttrsToList optionString a);
@ -136,15 +153,18 @@ let
### Local storages ### Local storages
${concatStringsSep "\n\n" (mapAttrsToList (n: v: "[storage ${n}_local]" + "\n" + attrsString v) localStorages)} ${concatStringsSep "\n\n"
(mapAttrsToList (n: v: "[storage ${n}_local]" + "\n" + attrsString v)
localStorages)}
### Remote storages ### Remote storages
${concatStringsSep "\n\n" (mapAttrsToList (n: v: "[storage ${n}_remote]" + "\n" + attrsString v) remoteStorages)} ${concatStringsSep "\n\n"
(mapAttrsToList (n: v: "[storage ${n}_remote]" + "\n" + attrsString v)
remoteStorages)}
''; '';
in
{ in {
options = { options = {
programs.vdirsyncer = { programs.vdirsyncer = {
enable = mkEnableOption "vdirsyncer"; enable = mkEnableOption "vdirsyncer";
@ -177,12 +197,19 @@ in
assertions = let assertions = let
requiredOptions = t: requiredOptions = t:
if (t == "caldav" || t == "carddav" || t == "http") then [ "url" ] if (t == "caldav" || t == "carddav" || t == "http") then
else if (t == "filesystem") then [ "path" "fileExt" ] [ "url" ]
else if (t == "singlefile") then [ "path" ] else if (t == "filesystem") then [
else if (t == "google_calendar" || t == "google_contacts") then "path"
[ "tokenFile" "clientId" "clientSecret"] "fileExt"
else throw "Unrecognized storage type: ${t}"; ] else if (t == "singlefile") then
[ "path" ]
else if (t == "google_calendar" || t == "google_contacts") then [
"tokenFile"
"clientId"
"clientSecret"
] else
throw "Unrecognized storage type: ${t}";
allowedOptions = let allowedOptions = let
remoteOptions = [ remoteOptions = [
@ -198,46 +225,49 @@ in
"userAgent" "userAgent"
]; ];
in t: in t:
if (t == "caldav") if (t == "caldav") then
then [ "timeRange" "itemTypes" ] ++ remoteOptions [ "timeRange" "itemTypes" ] ++ remoteOptions
else if (t == "carddav" || t == "http") else if (t == "carddav" || t == "http") then
then remoteOptions remoteOptions
else if (t == "filesystem") else if (t == "filesystem") then [
then [ "fileExt" "encoding" "postHook" ] "fileExt"
else if (t == "singlefile") "encoding"
then [ "encoding" ] "postHook"
else if (t == "google_calendar") then ] else if (t == "singlefile") then
[ "timeRange" "itemTypes" "clientIdCommand" "clientSecretCommand" ] [ "encoding" ]
else if (t == "google_contacts") then [ "clientIdCommand" "clientSecretCommand" ] else if (t == "google_calendar") then [
else throw "Unrecognized storage type: ${t}"; "timeRange"
"itemTypes"
"clientIdCommand"
"clientSecretCommand"
] else if (t == "google_contacts") then [
"clientIdCommand"
"clientSecretCommand"
] else
throw "Unrecognized storage type: ${t}";
assertStorage = n: v: assertStorage = n: v:
let let allowed = allowedOptions v.type ++ (requiredOptions v.type);
allowed = allowedOptions v.type ++ (requiredOptions v.type); in mapAttrsToList (a: v':
in [{
mapAttrsToList (
a: v': [
{
assertion = (elem a allowed); assertion = (elem a allowed);
message = '' message = ''
Storage ${n} is of type ${v.type}. Option Storage ${n} is of type ${v.type}. Option
${a} is not allowed for this type. ${a} is not allowed for this type.
''; '';
} }] ++ (let
] ++ required =
(let required = filter (a: !hasAttr "${a}Command" v) (requiredOptions v.type); filter (a: !hasAttr "${a}Command" v) (requiredOptions v.type);
in map (a: [{ in map (a: [{
assertion = hasAttr a v; assertion = hasAttr a v;
message = '' message = ''
Storage ${n} is of type ${v.type}, but required Storage ${n} is of type ${v.type}, but required
option ${a} is not set. option ${a} is not set.
''; '';
}]) required) }]) required)) (removeAttrs v [ "type" "_module" ]);
) (removeAttrs v ["type" "_module"]);
storageAssertions = flatten (mapAttrsToList assertStorage localStorages) storageAssertions = flatten (mapAttrsToList assertStorage localStorages)
++ flatten (mapAttrsToList assertStorage remoteStorages); ++ flatten (mapAttrsToList assertStorage remoteStorages);
in storageAssertions; in storageAssertions;
home.packages = [ cfg.package ]; home.packages = [ cfg.package ];

View file

@ -6,13 +6,11 @@ let
cfg = config.services.vdirsyncer; cfg = config.services.vdirsyncer;
vdirsyncerOptions = vdirsyncerOptions = [ ]
[ ] ++ optional (cfg.verbosity != null) "--verbosity ${cfg.verbosity}" ++ optional (cfg.verbosity != null) "--verbosity ${cfg.verbosity}"
++ optional (cfg.configFile != null) "--config ${cfg.configFile}"; ++ optional (cfg.configFile != null) "--config ${cfg.configFile}";
in in {
{
meta.maintainers = [ maintainers.pjones ]; meta.maintainers = [ maintainers.pjones ];
options.services.vdirsyncer = { options.services.vdirsyncer = {
@ -41,7 +39,8 @@ in
}; };
verbosity = mkOption { verbosity = mkOption {
type = types.nullOr (types.enum [ "CRITICAL" "ERROR" "WARNING" "INFO" "DEBUG"]); type = types.nullOr
(types.enum [ "CRITICAL" "ERROR" "WARNING" "INFO" "DEBUG" ]);
default = null; default = null;
description = '' description = ''
Whether vdirsyncer should produce verbose output. Whether vdirsyncer should produce verbose output.
@ -68,23 +67,21 @@ in
Service = { Service = {
Type = "oneshot"; Type = "oneshot";
# TODO `vdirsyncer discover` # TODO `vdirsyncer discover`
ExecStart = "${cfg.package}/bin/vdirsyncer sync ${concatStringsSep " " vdirsyncerOptions}"; ExecStart = "${cfg.package}/bin/vdirsyncer sync ${
concatStringsSep " " vdirsyncerOptions
}";
}; };
}; };
systemd.user.timers.vdirsyncer = { systemd.user.timers.vdirsyncer = {
Unit = { Unit = { Description = "vdirsyncer calendar&contacts synchronization"; };
Description = "vdirsyncer calendar&contacts synchronization";
};
Timer = { Timer = {
OnCalendar = cfg.frequency; OnCalendar = cfg.frequency;
Unit = "vdirsyncer.service"; Unit = "vdirsyncer.service";
}; };
Install = { Install = { WantedBy = [ "timers.target" ]; };
WantedBy = [ "timers.target" ];
};
}; };
}; };
} }