launchd: initial support for LaunchAgents#2497
Conversation
|
|
||
| # NOTE: Launch Agent configurations can't be symlinked from the Nix store | ||
| # because it needs to be owned by the user running it. | ||
| home.activation.setupLaunchAgents = |
There was a problem hiding this comment.
The activation script takes care of starting/restarting/stopping the agents automatically.
| # NOTE: Launch Agent configurations can't be symlinked from the Nix store | ||
| # because it needs to be owned by the user running it. |
There was a problem hiding this comment.
LaunchAgent configuration files are copied into the home directory because Launchd refuses to work with files not owned by the user running it. For safety reasons, the activation script would check if any changes are made to configurations files previously deployed by Home Manager.
| # launchd option type from nix-darwin | ||
| # | ||
| # Original Source: | ||
| # https://github.com/LnL7/nix-darwin/blob/a34dea2/modules/launchd/launchd.nix | ||
|
|
||
| # Copyright 2017 Daiderd Jordan | ||
| # | ||
| # Permission is hereby granted, free of charge, to any person obtaining |
There was a problem hiding this comment.
This file contains the definition for the Launchd option type, the code responsible for translating Nix expressions into LaunchAgent configurations. Since this file comes from the nix-darwin project, I have included the license (MIT) and copyright headers here.
Other files aren't based on outside projects.
berbiche
left a comment
There was a problem hiding this comment.
Thanks for the contribution!
| assertions = [{ | ||
| assertion = agentPlists != { } -> pkgs.stdenv.isDarwin; | ||
| message = let names = lib.concatStringsSep ", " (attrNames agentPlists); | ||
| in "Must use Darwin for modules that require Launchd: " + names; | ||
| }]; |
There was a problem hiding this comment.
I know the systemd module has the opposite logic, but would it be possible to also add an enable option to check against (with a default value of isDarwin)?
| assertions = [{ | |
| assertion = agentPlists != { } -> pkgs.stdenv.isDarwin; | |
| message = let names = lib.concatStringsSep ", " (attrNames agentPlists); | |
| in "Must use Darwin for modules that require Launchd: " + names; | |
| }]; | |
| assertions = [{ | |
| assertion = (cfg.enable && agentPlists != { }) -> isDarwin; | |
| message = let names = lib.concatStringsSep ", " (attrNames agentPlists); | |
| in "Must use Darwin for modules that require Launchd: " + names; | |
| }]; |
This would make it easier to have services defining both systemd services and launchd agents (until a common backend can be created).
There was a problem hiding this comment.
I wonder if the same should be done for systemd as well, or otherwise each systemd service would need to be hidden behind an mkIf for services using both systemd and launchd.
There was a problem hiding this comment.
Yeah, we should do the same for systemd services (in a different PR).
berbiche
left a comment
There was a problem hiding this comment.
I missed two things in my initial review.
| let | ||
| inherit (pkgs.stdenv.hostPlatform) isDarwin; | ||
| inherit (lib.generators) toPlist; | ||
| inherit (hm.dag) entryAfter; |
There was a problem hiding this comment.
I've removed this line.
99d5483 to
edbec1f
Compare
|
I've rebased against |
| inherit (lib.generators) toPlist; | ||
|
|
||
| cfg = config.launchd; | ||
| labelPrefix = "org.nixos.home."; |
There was a problem hiding this comment.
Maybe something like
| labelPrefix = "org.nixos.home."; | |
| labelPrefix = "org.nix-community.home."; |
since we're not an official nixos.org project.
There was a problem hiding this comment.
I applied your suggestion and changed the tests accordingly. This made me realize there actually is a https://nix-community.org site.
| home.activation.setupLaunchAgents = | ||
| hm.dag.entryAfter [ "writeBoundary" ] '' | ||
| setupLaunchAgents() { | ||
| local oldDir="$(readlink -m "$oldGenPath/LaunchAgents")" |
There was a problem hiding this comment.
I'm wondering if this may cause problems on the first activation, when $oldGenPath is unset?
Btw, the general recommendation is to declare the variable and assign it in separate statements. I.e. something like
local oldDir
oldDir="$(readline …)"See SC2155 for rationale.
There was a problem hiding this comment.
I added more conditional statements to deal with an empty $oldGenPath and also separated variable declarations and assignments.
| ''; | ||
| } | ||
|
|
||
| { |
There was a problem hiding this comment.
I think this change is worth mentioning in the release notes as well!
There was a problem hiding this comment.
I added an entry in the 22.05 release note.
| continue | ||
| fi | ||
| if [[ -f "$dstPath" ]]; then | ||
| while true; do |
There was a problem hiding this comment.
Would it be possible to limit this to just a few loops and then, e.g., return with an error message? It makes me a bit nervous to have a potentially infinite loop in an activation script, however unlikely it is to happen 🙂
There was a problem hiding this comment.
I set the limit to 10 loops.
| continue | ||
| fi | ||
| if ! cmp --quiet "$srcPath" "$dstPath"; then | ||
| warnEcho "Skipping deletion of '$dstPath', since its contents have diverged" |
There was a problem hiding this comment.
Nice, I like the "diverged" wording 👍
|
Thanks for the contribution, looks pretty cool! I added a few comments to the best of my ability. |
edbec1f to
ab832d9
Compare
b892a57 to
c7a13f7
Compare
|
Squashed and merged to master now 🙂 |
Description
Add support for macOS LaunchAgents, the equivalent of systemd user services.
Here's a little example of how to use this module:
Checklist
Change is backwards compatible.
Code formatted with
./format.Code tested through
nix-shell --pure tests -A run.all.Test cases updated/added. See example.
Commit messages are formatted like
See CONTRIBUTING for more information and recent commit messages for examples.
If this PR adds a new module
Added myself as module maintainer. See example.
Added myself and the module files to
.github/CODEOWNERS.