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:
parent
343646e092
commit
b71edac7a3
2 changed files with 208 additions and 89 deletions
|
|
@ -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.
|
||||||
|
|
||||||
|
::: {.important}
|
||||||
|
The list must not be empty and must not contain duplicate entries (attrsets which compare equally).
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: {.caution}
|
||||||
|
Since missing attrs become wildcards, an empty attrset effectively means "every minute".
|
||||||
|
:::
|
||||||
'';
|
'';
|
||||||
type = types.nullOr (types.listOf (types.submodule {
|
type = types.nullOr launchdTypes.StartCalendarInterval;
|
||||||
options = {
|
|
||||||
Minute = mkOption {
|
|
||||||
type = types.nullOr types.int;
|
|
||||||
default = null;
|
|
||||||
description = ''
|
|
||||||
The minute on which this job will be run.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
Hour = mkOption {
|
|
||||||
type = types.nullOr types.int;
|
|
||||||
default = null;
|
|
||||||
description = ''
|
|
||||||
The hour on which this job will be run.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
Day = mkOption {
|
|
||||||
type = types.nullOr types.int;
|
|
||||||
default = null;
|
|
||||||
description = ''
|
|
||||||
The day on which this job will be run.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
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 {
|
||||||
|
|
@ -669,22 +637,22 @@ with lib;
|
||||||
resource limits based on what kind of job it is. If left unspecified, the system will apply light
|
resource limits based on what kind of job it is. If left unspecified, the system will apply light
|
||||||
resource limits to the job, throttling its CPU usage and I/O bandwidth. The following are valid values:
|
resource limits to the job, throttling its CPU usage and I/O bandwidth. The following are valid values:
|
||||||
|
|
||||||
Background
|
Background
|
||||||
: Background jobs are generally processes that do work that was not directly requested by the user.
|
: Background jobs are generally processes that do work that was not directly requested by the user.
|
||||||
The resource limits applied to Background jobs are intended to prevent them from disrupting the
|
The resource limits applied to Background jobs are intended to prevent them from disrupting the
|
||||||
user experience.
|
user experience.
|
||||||
|
|
||||||
Standard
|
Standard
|
||||||
: Standard jobs are equivalent to no ProcessType being set.
|
: Standard jobs are equivalent to no ProcessType being set.
|
||||||
|
|
||||||
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
|
||||||
jobs are critical to maintaining a responsive user experience, and this key should only be
|
jobs are critical to maintaining a responsive user experience, and this key should only be
|
||||||
used if an app's ability to be responsive depends on it, and cannot be made Adaptive.
|
used if an app's ability to be responsive depends on it, and cannot be made Adaptive.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -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,31 +703,32 @@ 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
|
||||||
options = {
|
(types.submodule {
|
||||||
ResetAtClose = mkOption {
|
options = {
|
||||||
type = types.nullOr types.bool;
|
ResetAtClose = mkOption {
|
||||||
default = null;
|
type = types.nullOr types.bool;
|
||||||
description = ''
|
default = null;
|
||||||
If this boolean is false, the port is recycled, thus leaving clients to remain oblivious to the
|
description = ''
|
||||||
demand nature of job. If the value is set to true, clients receive port death notifications when
|
If this boolean is false, the port is recycled, thus leaving clients to remain oblivious to the
|
||||||
the job lets go of the receive right. The port will be recreated atomically with respect to bootstrap_look_up()
|
demand nature of job. If the value is set to true, clients receive port death notifications when
|
||||||
calls, so that clients can trust that after receiving a port death notification,
|
the job lets go of the receive right. The port will be recreated atomically with respect to bootstrap_look_up()
|
||||||
the new port will have already been recreated. Setting the value to true should be done with
|
calls, so that clients can trust that after receiving a port death notification,
|
||||||
care. Not all clients may be able to handle this behavior. The default value is false.
|
the new port will have already been recreated. Setting the value to true should be done with
|
||||||
'';
|
care. Not all clients may be able to handle this behavior. The default value is false.
|
||||||
};
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
HideUntilCheckIn = mkOption {
|
HideUntilCheckIn = mkOption {
|
||||||
type = types.nullOr types.bool;
|
type = types.nullOr types.bool;
|
||||||
default = null;
|
default = null;
|
||||||
description = ''
|
description = ''
|
||||||
Reserve the name in the namespace, but cause bootstrap_look_up() to fail until the job has
|
Reserve the name in the namespace, but cause bootstrap_look_up() to fail until the job has
|
||||||
checked in with launchd.
|
checked in with launchd.
|
||||||
'';
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
})));
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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
121
modules/launchd/types.nix
Normal 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));
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue