1
0
Fork 0
mirror of https://github.com/nix-community/home-manager.git synced 2025-11-08 19:46:05 +01:00
home-manager/modules/targets/darwin/user-defaults/default.nix
lignus 3ec1cd9a07
launchd+targets/darwin: Escape XML in plists (#7356)
This patch updates all usage of toPlist such that it escapes any strings
in the final output.

The motication for this change is to avoid confusion when end-users of
home-manager's APIs are not aware that the option values they set end up
being passed un-escaped to XML files.

BREAKING CHANGE: Consumers doing manual escaping will now be doubly escaped.

Co-authored-by: Linnnus <linnnus@users.noreply.github.com>
2025-08-09 11:22:08 -05:00

113 lines
3.4 KiB
Nix

{
config,
lib,
pkgs,
...
}:
let
cfg = config.targets.darwin;
mkActivationCmds =
isLocal: settings:
let
toDefaultsFile =
domain: attrs: pkgs.writeText "${domain}.plist" (lib.generators.toPlist { escape = true; } attrs);
cliFlags = lib.optionalString isLocal "-currentHost";
toActivationCmd =
domain: attrs:
"run /usr/bin/defaults ${cliFlags} import ${lib.escapeShellArg domain} ${toDefaultsFile domain attrs}";
nonNullDefaults = lib.mapAttrs (domain: attrs: (lib.filterAttrs (n: v: v != null) attrs)) settings;
writableDefaults = lib.filterAttrs (domain: attrs: attrs != { }) nonNullDefaults;
in
lib.mapAttrsToList toActivationCmd writableDefaults;
defaultsCmds = mkActivationCmds false cfg.defaults;
currentHostDefaultsCmds = mkActivationCmds true cfg.currentHostDefaults;
activationCmds = defaultsCmds ++ currentHostDefaultsCmds;
in
{
meta.maintainers = [ lib.maintainers.midchildan ];
options.targets.darwin.defaults = lib.mkOption {
type = lib.types.submodule ./opts-allhosts.nix;
default = { };
example = {
"com.apple.desktopservices" = {
DSDontWriteNetworkStores = true;
DSDontWriteUSBStores = true;
};
};
description = ''
Set macOS user defaults. Values set to `null` are
ignored.
::: {.warning}
Some settings might require a re-login to take effect.
:::
::: {.warning}
Some settings are only read from
{option}`targets.darwin.currentHostDefaults`.
:::
'';
};
options.targets.darwin.currentHostDefaults = lib.mkOption {
type = lib.types.submodule ./opts-currenthost.nix;
default = { };
example = {
"com.apple.controlcenter" = {
BatteryShowPercentage = true;
};
};
description = ''
Set macOS user defaults. Unlike {option}`targets.darwin.defaults`,
the preferences will only be applied to the currently logged-in host. This
distinction is important for networked accounts.
Values set to `null` are ignored.
::: {.warning}
Some settings might require a re-login to take effect.
:::
'';
};
config = lib.mkIf (activationCmds != [ ]) {
assertions = [
(lib.hm.assertions.assertPlatform "targets.darwin.defaults" pkgs lib.platforms.darwin)
];
warnings =
let
batteryOptionName = ''targets.darwin.currentHostDefaults."com.apple.controlcenter".BatteryShowPercentage'';
batteryPercentage = lib.attrByPath [
"com.apple.menuextra.battery"
"ShowPercent"
] null cfg.defaults;
webkitDevExtras = lib.attrByPath [
"com.apple.Safari"
"com.apple.Safari.ContentPageGroupIdentifier.WebKit2DeveloperExtrasEnabled"
] null cfg.defaults;
in
lib.optional (batteryPercentage != null) ''
The option 'com.apple.menuextra.battery.ShowPercent' no longer works on
macOS 11 and later. Instead, use '${batteryOptionName}'.
''
++ lib.optional (webkitDevExtras != null) ''
The option 'com.apple.Safari.com.apple.Safari.ContentPageGroupIdentifier.WebKit2DeveloperExtrasEnabled'
is no longer present in recent versions of Safari.
'';
home.activation.setDarwinDefaults = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
verboseEcho "Configuring macOS user defaults"
${lib.concatStringsSep "\n" activationCmds}
'';
};
}