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

View File

@ -5,7 +5,7 @@ with lib;
{
options.khal = {
type = mkOption {
type = types.nullOr (types.enum [ "calendar" "discover"]);
type = types.nullOr (types.enum [ "calendar" "discover" ]);
default = null;
description = ''
There is no description of this option.
@ -23,9 +23,22 @@ with lib;
color = mkOption {
type = types.nullOr (types.enum [
"black" "white" "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"
"black"
"white"
"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;
description = ''

View File

@ -10,83 +10,82 @@ let
khalCalendarAccounts =
filterAttrs (_: a: a.khal.enable) config.accounts.calendar.accounts;
khalContactAccounts =
mapAttrs (_: v: v // { type = "birthdays"; })
khalContactAccounts = mapAttrs (_: v: v // { type = "birthdays"; })
(filterAttrs (_: a: a.khal.enable) config.accounts.contact.accounts);
khalAccounts = khalCalendarAccounts // khalContactAccounts;
primaryAccount =
findSingle (a: a.primary) null null
(mapAttrsToList (n: v: v // {name= n;}) khalAccounts);
primaryAccount = findSingle (a: a.primary) null null
(mapAttrsToList (n: v: v // { name = n; }) khalAccounts);
definedAttrs = filterAttrs (_: v: !isNull v);
toKeyValueIfDefined = attrs:
generators.toKeyValue {} (definedAttrs attrs);
toKeyValueIfDefined = attrs: generators.toKeyValue { } (definedAttrs attrs);
genCalendarStr = name: value:
concatStringsSep "\n" (
[
"[[${name}]]"
"path = ${value.local.path + "/" + (optionalString (value.khal.type == "discover") value.khal.glob)}"
]
++ optional (value.khal.readOnly) "readonly = True"
++ [ (toKeyValueIfDefined (getAttrs [ "type" "color" "priority" ] value.khal)) ]
++ ["\n"]
);
concatStringsSep "\n" ([
"[[${name}]]"
"path = ${
value.local.path + "/"
+ (optionalString (value.khal.type == "discover") value.khal.glob)
}"
] ++ optional (value.khal.readOnly) "readonly = True" ++ [
(toKeyValueIfDefined (getAttrs [ "type" "color" "priority" ] value.khal))
] ++ [ "\n" ]);
localeFormatOptions = let T = lib.types; in mapAttrs (n: v: v // {
description = v.description + ''
localeFormatOptions = let T = lib.types;
in mapAttrs (n: v:
v // {
description = v.description + ''
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.
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.
'';
};
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 = {
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).
'';
};
};
localeOptions = let T = lib.types; in localeFormatOptions // {
localeOptions = let T = lib.types;
in localeFormatOptions // {
unicode_symbols = {
type = T.bool;
default = true;
@ -136,9 +135,7 @@ let
};
};
in
{
in {
options.programs.khal = {
enable = mkEnableOption "khal, a CLI calendar application";
locale = mkOption {
@ -152,23 +149,20 @@ in
};
config = mkIf cfg.enable {
home.packages = [ pkgs.khal ];
home.packages = [ pkgs.khal ];
xdg.configFile."khal/config".text = concatStringsSep "\n" (
[
"[calendars]"
]
++ mapAttrsToList genCalendarStr khalAccounts
++
[
(generators.toINI {} {
xdg.configFile."khal/config".text = concatStringsSep "\n" ([ "[calendars]" ]
++ mapAttrsToList genCalendarStr khalAccounts ++ [
(generators.toINI { } {
locale = definedAttrs (cfg.locale // { _module = null; });
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);
in
{
in {
options.vdirsyncer = {
enable = mkEnableOption "synchronization using vdirsyncer";
@ -21,10 +19,8 @@ in
};
conflictResolution = mkOption {
type =
types.nullOr
(types.either
(types.enum ["remote wins" "local wins"])
type = types.nullOr
(types.either (types.enum [ "remote wins" "local wins" ])
(types.listOf types.str));
default = null;
description = ''
@ -52,7 +48,7 @@ in
metadata = mkOption {
type = types.listOf types.str;
default = [];
default = [ ];
example = [ "color" "displayname" ];
description = ''
Metadata keys that should be synchronized when vdirsyncer
@ -115,7 +111,7 @@ in
};
auth = mkOption {
type = types.nullOr (types.enum ["basic" "digest" "guess"]);
type = types.nullOr (types.enum [ "basic" "digest" "guess" ]);
default = null;
description = ''
Authentication settings. The default is <literal>basic</literal>.
@ -128,7 +124,7 @@ in
description = ''
Either a path to a certificate with a client certificate and
the key or a list of paths to the files with them.
'';
'';
};
userAgent = mkOption {

View File

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

View File

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