1
0
Fork 0
mirror of https://github.com/nix-community/home-manager.git synced 2025-11-08 19:46:05 +01:00

launchd: sync up with changes from nix-darwin (#6508)

We haven't updated to match changes done upstream in a while. Updating
to reflect changes for expanding support / proper types.
This commit is contained in:
Austin Horstman 2025-02-27 18:38:18 -05:00 committed by GitHub
parent 343646e092
commit b71edac7a3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 208 additions and 89 deletions

View file

@ -25,9 +25,11 @@
{ config, lib, ... }: { config, lib, ... }:
with lib; let
inherit (lib) types mkOption; # added by Home Manager
{ launchdTypes = import ./types.nix { inherit config lib; };
in {
freeformType = with types; attrsOf anything; # added by Home Manager freeformType = with types; attrsOf anything; # added by Home Manager
options = { options = {
@ -118,7 +120,7 @@ with lib;
}; };
LimitLoadToSessionType = mkOption { LimitLoadToSessionType = mkOption {
type = types.nullOr types.str; type = types.nullOr (types.oneOf [ types.str (types.listOf types.str) ]);
default = null; default = null;
description = '' description = ''
This configuration file only applies to sessions of the type specified. This key is used in concert This configuration file only applies to sessions of the type specified. This key is used in concert
@ -369,60 +371,26 @@ with lib;
StartCalendarInterval = mkOption { StartCalendarInterval = mkOption {
default = null; default = null;
example = { example = [{
Hour = 2; Hour = 2;
Minute = 30; Minute = 30;
}; }];
description = '' description = ''
This optional key causes the job to be started every calendar interval as specified. Missing arguments This optional key causes the job to be started every calendar interval as specified. The semantics are
are considered to be wildcard. The semantics are much like `crontab(5)`. Unlike cron which skips job much like {manpage}`crontab(5)`: Missing attributes are considered to be wildcard. Unlike cron which skips
invocations when the computer is asleep, launchd will start the job the next time the computer wakes job invocations when the computer is asleep, launchd will start the job the next time the computer wakes
up. If multiple intervals transpire before the computer is woken, those events will be coalesced into up. If multiple intervals transpire before the computer is woken, those events will be coalesced into
one event upon wake from sleep. one event upon waking from sleep.
'';
type = types.nullOr (types.listOf (types.submodule {
options = {
Minute = mkOption {
type = types.nullOr types.int;
default = null;
description = ''
The minute on which this job will be run.
'';
};
Hour = mkOption { ::: {.important}
type = types.nullOr types.int; The list must not be empty and must not contain duplicate entries (attrsets which compare equally).
default = null; :::
description = ''
The hour on which this job will be run.
'';
};
Day = mkOption { ::: {.caution}
type = types.nullOr types.int; Since missing attrs become wildcards, an empty attrset effectively means "every minute".
default = null; :::
description = ''
The day on which this job will be run.
''; '';
}; type = types.nullOr launchdTypes.StartCalendarInterval;
Weekday = mkOption {
type = types.nullOr types.int;
default = null;
description = ''
The weekday on which this job will be run (0 and 7 are Sunday).
'';
};
Month = mkOption {
type = types.nullOr types.int;
default = null;
description = ''
The month on which this job will be run.
'';
};
};
}));
}; };
StandardInPath = mkOption { StandardInPath = mkOption {
@ -679,7 +647,7 @@ with lib;
Adaptive Adaptive
: Adaptive jobs move between the Background and Interactive classifications based on activity over : Adaptive jobs move between the Background and Interactive classifications based on activity over
XPC connections. See {manpage}`xpc_transaction_begin(3)` for details. XPC connections. See `xpc_transaction_begin(3)` for details.
Interactive Interactive
: Interactive jobs run with the same resource limitations as apps, that is to say, none. Interactive : Interactive jobs run with the same resource limitations as apps, that is to say, none. Interactive
@ -706,6 +674,15 @@ with lib;
''; '';
}; };
LowPriorityBackgroundIO = mkOption {
type = types.nullOr types.bool;
default = null;
description = ''
This optional key specifies whether the kernel should consider this daemon to be low priority when
doing file system I/O when the process is throttled with the Darwin-background classification.
'';
};
LaunchOnlyOnce = mkOption { LaunchOnlyOnce = mkOption {
type = types.nullOr types.bool; type = types.nullOr types.bool;
default = null; default = null;
@ -717,7 +694,7 @@ with lib;
MachServices = mkOption { MachServices = mkOption {
default = null; default = null;
example = { ResetAtClose = true; }; example = { "org.nixos.service" = { ResetAtClose = true; }; };
description = '' description = ''
This optional key is used to specify Mach services to be registered with the Mach bootstrap sub-system. This optional key is used to specify Mach services to be registered with the Mach bootstrap sub-system.
Each key in this dictionary should be the name of service to be advertised. The value of the key must Each key in this dictionary should be the name of service to be advertised. The value of the key must
@ -726,7 +703,8 @@ with lib;
Finally, for the job itself, the values will be replaced with Mach ports at the time of check-in with Finally, for the job itself, the values will be replaced with Mach ports at the time of check-in with
launchd. launchd.
''; '';
type = types.nullOr (types.submodule { type = types.nullOr (types.attrsOf (types.either types.bool
(types.submodule {
options = { options = {
ResetAtClose = mkOption { ResetAtClose = mkOption {
type = types.nullOr types.bool; type = types.nullOr types.bool;
@ -750,7 +728,7 @@ with lib;
''; '';
}; };
}; };
}); })));
}; };
LaunchEvents = mkOption { LaunchEvents = mkOption {
@ -778,6 +756,26 @@ with lib;
}; };
}; };
ServiceIPC = mkOption {
type = types.nullOr types.bool;
default = null;
description = ''
This optional key specifies whether the job participates in advanced
communication with launchd. The default is false. This flag is
incompatible with the inetdCompatibility key.
'';
};
SessionCreate = mkOption {
type = types.nullOr types.bool;
default = null;
description = ''
This key specifies that the job should be spawned into a new security
audit session rather than the default session for the context is belongs
to. See auditon(2) for details.
'';
};
Sockets = mkOption { Sockets = mkOption {
default = null; default = null;
description = '' description = ''

121
modules/launchd/types.nix Normal file
View file

@ -0,0 +1,121 @@
# launchd option type from nix-darwin
#
# Original code from https://github.com/LnL7/nix-darwin/commit/861af0fc94df9454f4e92d6892f75588763164bb
{ lib, ... }:
let
inherit (lib) imap1 types mkOption showOption mergeDefinitions;
inherit (builtins) map filter length deepSeq throw toString concatLists;
inherit (lib.options) showDefs;
wildcardText = lib.literalMD "`*`";
/* *
A type of list which does not allow duplicate elements. The base/inner
list type to use (e.g. `types.listOf` or `types.nonEmptyListOf`) is passed
via argument `listType`, which must be the final type and not a function.
NOTE: The extra check for duplicates is quadratic and strict, so use this
type sparingly and only:
* when needed, and
* when the list is expected to be recursively short (e.g. < 10 elements)
and shallow (i.e. strict evaluation of the list won't take too long)
The implementation of this function is similar to that of
`types.nonEmptyListOf`.
*/
types'.uniqueList = listType:
listType // {
description = "unique ${
types.optionDescriptionPhrase (class: class == "noun") listType
}";
substSubModules = m: types'.uniqueList (listType.substSubModules m);
# This has been taken from the implementation of `types.listOf`, but has
# been modified to throw on duplicates. This check cannot be done in the
# `check` fn as this check is deep/strict, and because `check` runs
# prior to merging.
merge = loc: defs:
let
# Each element of `dupes` is a list. When there are duplicates,
# later lists will be duplicates of earlier lists, so just throw on
# the first set of duplicates found so that we don't have duplicate
# error msgs.
checked = filter (li:
if length li > 1 then
throw ''
The option `${
showOption loc
}' contains duplicate entries after merging:
${showDefs li}''
else
false) dupes;
dupes =
map (def: filter (def': def'.value == def.value) merged) merged;
merged = filter (x: x ? value) (concatLists (imap1 (n: def:
imap1 (m: el:
let
inherit (def) file;
loc' = loc
++ [ "[definition ${toString n}-entry ${toString m}]" ];
in (mergeDefinitions loc' listType.nestedTypes.elemType [{
inherit file;
value = el;
}]).optionalValue // {
inherit loc' file;
}) def.value) defs));
in deepSeq checked (map (x: x.value) merged);
};
in {
StartCalendarInterval = let
CalendarIntervalEntry = types.submodule {
options = {
Minute = mkOption {
type = types.nullOr (types.ints.between 0 59);
default = null;
defaultText = wildcardText;
description = ''
The minute on which this job will be run.
'';
};
Hour = mkOption {
type = types.nullOr (types.ints.between 0 23);
default = null;
defaultText = wildcardText;
description = ''
The hour on which this job will be run.
'';
};
Day = mkOption {
type = types.nullOr (types.ints.between 1 31);
default = null;
defaultText = wildcardText;
description = ''
The day on which this job will be run.
'';
};
Weekday = mkOption {
type = types.nullOr (types.ints.between 0 7);
default = null;
defaultText = wildcardText;
description = ''
The weekday on which this job will be run (0 and 7 are Sunday).
'';
};
Month = mkOption {
type = types.nullOr (types.ints.between 1 12);
default = null;
defaultText = wildcardText;
description = ''
The month on which this job will be run.
'';
};
};
};
in types.either CalendarIntervalEntry
(types'.uniqueList (types.nonEmptyListOf CalendarIntervalEntry));
}