nix-darwin
nix-darwin copied to clipboard
applications are only linked for system packages, not user packages
When I do this:
{ users.users.brianhicks.packages = [ pkgs.emacsMacport ]; }
I expect Emacs.app
to be available somewhere—maybe in ~/Applications/Nix Apps
. But it's not! However, if I do this:
{ environment.systemPackages = [ pkgs.emacsMacport ]; }
Then ~/Applications/Nix Apps/Emacs.app
gets created.
This is important to me because I manage my packages through home-manager, where I create a big ol' bundle of emacs packages all together. I'd rather not have to move all that configuration out of home-manager just to use graphical Emacs!
According to @rvolosatovs in https://github.com/rycee/home-manager/pull/702#issuecomment-489431636, it's because these lines specifically (and only) include the system packages:
https://github.com/LnL7/nix-darwin/blob/3ba909eb2dd3ddd893604f83048fa76cc2e47e74/modules/system/applications.nix#L17-L21
@LnL7 I don't have a great idea of how hard this would be to fix. Do you think it would be something someone newish (read: me) could take on? Would a patch for this behavior be welcome?
The main problem is that there's no link between the user running darwin-rebuild and users entries. It's probably better to link per user applications instead and move system packages to /Applications
.
I'm having some trouble understanding what you're saying about the running user. Why does this matter? Shouldn't stuff end up in /$USER_HOME/Applications
regardless of who is running it?
Regardless, is that a change you're open to? I'm happy to look into it but I would rather not waste everyone's time by making something that would be doomed before I started 😁
OK, I've taken more time to think about it today, and just want to check my understanding. I think we'd need to:
- change https://github.com/LnL7/nix-darwin/blob/3ba909eb2dd3ddd893604f83048fa76cc2e47e74/modules/system/applications.nix to symlink into
/Applications/Nix Apps
instead of~/Applications
or~/Applications/Nix Apps
. - Figure out some way of removing the old symlinks in
~
. - add similar app linking logic in https://github.com/LnL7/nix-darwin/blob/3ba909eb2dd3ddd893604f83048fa76cc2e47e74/modules/users/default.nix somewhere. This would put applications in
users.<user?>.packages
in~/Applications
or~/Applications/Nix Apps
like the system packages are now.
The first seems pretty approachable; I'm sure I could handle it. But I'm not sure if the second or third even make sense. @LnL7, what do you think? Would that be a good way to move forward on this?
(to be clear, if it's "yes" I plan to make PRs to do this!)
Yeah that's what I was suggesting.
Great, thank you. Sorry for the noise; I wanted to make sure I understood you completely before I sent in a PR. :)
On Jul 18, 2019, at 2:59 PM, Daiderd Jordan [email protected] wrote:
Yeah that's what I was suggesting.
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/LnL7/nix-darwin/issues/139?email_source=notifications&email_token=AACWYSLJ54ZKV62VBADHAZTQADDS3A5CNFSM4HK37DL2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2JTTQQ#issuecomment-512965058, or mute the thread https://github.com/notifications/unsubscribe-auth/AACWYSO5ZD7T64654SUZBLTQADDS3ANCNFSM4HK37DLQ.
For future reference, you can override the applications link like:
system.build.applications = pkgs.lib.mkForce (pkgs.buildEnv {
name = "applications";
paths = config.environment.systemPackages ++ config.home-manager.users.myusername.home.packages;
pathsToLink = "/Applications";
});
It'd be nice if it was a config option though to avoid the mkForce.
@jsravn Nice, thanks for sharing that. It's a shame the larger change to place system-wide app links under /Applications
and per-user app links under ~/Applications
didn't end up getting seen through, because it feels like the ideal outcome.
Seems like spotlight struggles to index the links in ~/Applications however. I'm pretty sure it worked for me at one point but it's not working anymore. Any ideas?
I modified the activation script to create aliases which get picked up by spotlight.
system.activationScripts.applications.text = pkgs.lib.mkForce (''
echo "setting up ~/Applications/NixApps..."
mkdir -p ~/Applications
rm -rf ~/Applications/NixApps
mkdir -p ~/Applications/NixApps
chown myusername ~/Applications/NixApps
find ${config.system.build.applications}/Applications -maxdepth 1 -type l | while read f; do
echo "Linking $f"
src=$(/usr/bin/stat -f%Y $f)
osascript -e "tell app \"Finder\" to make alias file at POSIX file \"/Users/myusername/Applications/NixApps/\" to POSIX file \"$src\"";
done
'');
It can probably be made a bit nicer but it works.
@jsravn I found that some alias files were ending up with different names over time, e.g. with numeric suffixes. Making the name of the alias file explicit as follows seems to help:
system.activationScripts.applications.text = pkgs.lib.mkForce (''
echo "setting up ~/Applications/Nix..."
rm -rf ~/Applications/Nix
mkdir -p ~/Applications/Nix
chown ${me} ~/Applications/Nix
find ${config.system.build.applications}/Applications -maxdepth 1 -type l | while read f; do
src="$(/usr/bin/stat -f%Y $f)"
appname="$(basename $src)"
osascript -e "tell app \"Finder\" to make alias file at POSIX file \"/Users/${me}/Applications/Nix/\" to POSIX file \"$src\" with properties {name: \"$appname\"}";
done
'');
(Note that ${me}
is just a local attribute with my username.)
Nice one! @LnL7 would you accept a PR with this change?
Relying on applescript seems pretty undesirable to me, especially for headless usecases. But should be pretty easy to create an alias using CoreFoundation if there's no binary that create one on the system already.
Hello. I’ve encountered this issue today. At the moment I’ve applied a fix from above. I’d like to fix it permanently though. I’ll continue Brian’s PR unless you have time to fix it @LnL7. What are your thoughts?
So on Catalina, I tried the above suggestions of using aliases created through AppleScript instead of symlinks, but Spotlight still couldn't find the apps Nix installed into ~/Applications
. I even tried creating the symlinks and aliases in /Applications
, but still nothing. So now I'm just copying the entire app directory over! Wasteful but at least it shows up in Spotlight!
system.activationScripts.applications.text = pkgs.lib.mkForce (''
rm -rf ~/Applications/Nix\ Apps
mkdir -p ~/Applications/Nix\ Apps
for app in $(find ${config.system.build.applications}/Applications -maxdepth 1 -type l); do
src="$(/usr/bin/stat -f%Y "$app")"
cp -r "$src" ~/Applications/Nix\ Apps
done
'');
Copying (or moving?) the entire app to /Applications
is actually the approach taken by brew cask
. I suspect there's a good reason for that so I do the same as you do in my nix-darwin
config.
Copying the applications solved the issue for me too. I added the -L
flag to follow symlinks too (this helped copy the alacritty
app properly, for example).
So now I'm just copying the entire app directory over!
@andreykaipov @wangkev
If you comment out the program to uninstall, and run nix-collect-garbage
is the copied app directory will be removed or not?
I don't want leave garbage files/links/directories after uninstalling them.
@ihsanturk If I understand the question correctly - the copied apps aren't removed even when you uninstall Nix because Nix doesn't know what directories you create in your custom activation script, so you don't have to worry about commenting them out in your config before running garbage collection. As part of my uninstall script I have to manually remove the created directory.
Also I've since changed the above script to compare the hashes of <app>/Contents/MacOS
to prevent unnecessary copying. It makes for a rather large snippet, but you can view it here.
@ihsanturk Yes. the app will be removed. It's in the script.
system.activationScripts.applications.text = pkgs.lib.mkForce (''
rm -rf ~/Applications/Nix\ Apps
mkdir -p ~/Applications/Nix\ Apps
for app in $(find ${config.system.build.applications}/Applications -maxdepth 1 -type l); do
src="$(/usr/bin/stat -f%Y "$app")"
cp -r "$src" ~/Applications/Nix\ Apps
done
'');
The script starts with rm -rf ~/Applications/Nix\ Apps
which removes all previously copied apps. Then later in the script it copies new list of apps.
Thanks! Those were my two wishes:
... compare the hashes of
/Contents/MacOS to prevent unnecessary copying.
The script starts with
rm -rf ~/Applications/Nix\ Apps
which removes all previously copied apps.
Now I will integrate them. I hope these will be solved more generally by Nix itself.
I really don't understand why nix-darwin puts anything in the home directory. These are system packages, shouldn't they go to /Applications
? I would assume ~/Applications
would be used by home-manager, but apparently it can't (on mac) because of the conflict.
@akoppela Thank you!
↓ FYI I improved your snippet by resolving the symlinks in bulk, and using APFS's copy-on-write.
system.activationScripts.applications.text = let
env = pkgs.buildEnv {
name = "system-applications";
paths = config.environment.systemPackages;
pathsToLink = "/Applications";
};
in mkForce ''
# Set up applications.
echo "setting up ~/Applications..." >&2
rm -rf ~/Applications/Nix\ Apps
mkdir -p ~/Applications/Nix\ Apps
find ${env}/Applications -maxdepth 1 -type l -exec readlink '{}' + |
while read src; do
/bin/cp -cr "$src" ~/Applications/Nix\ Apps
done
'';
Folders symlinked to ~/Applications
do not show up in spotlight, and copying them seems like a waste of disk space. Not to mention that it can take a while too if you have a lot of packages. I found a workaround using APFS aliases, those show up in spotlight and barely take any disk space.
This is my activation script:
# Nix-darwin does not link installed applications to the user environment. This means apps will not show up
# in spotlight, and when launched through the dock they come with a terminal window. This is a workaround.
# Upstream issue: https://github.com/LnL7/nix-darwin/issues/214
system.activationScripts.applications.text = lib.mkForce ''
echo "setting up ~/Applications..." >&2
applications="$HOME/Applications"
nix_apps="$applications/Nix Apps"
# Needs to be writable by the user so that home-manager can symlink into it
if ! test -d "$applications"; then
mkdir -p "$applications"
chown ${username}: "$applications"
chmod u+w "$applications"
fi
# Delete the directory to remove old links
rm -rf "$nix_apps"
mkdir -p "$nix_apps"
find ${config.system.build.applications}/Applications -maxdepth 1 -type l -exec readlink '{}' + |
while read src; do
# Spotlight does not recognize symlinks, it will ignore directory we link to the applications folder.
# It does understand MacOS aliases though, a unique filesystem feature. Sadly they cannot be created
# from bash (as far as I know), so we use the oh-so-great Apple Script instead.
/usr/bin/osascript -e "
set fileToAlias to POSIX file \"$src\"
set applicationsFolder to POSIX file \"$nix_apps\"
tell application \"Finder\"
make alias file to fileToAlias at applicationsFolder
# This renames the alias; 'mpv.app alias' -> 'mpv.app'
set name of result to \"$(rev <<< "$src" | cut -d'/' -f1 | rev)\"
end tell
" 1>/dev/null
done
'';
I have done something similar for home-manager, which integrates with this just fine.
Commit from my dotfiles: https://github.com/IvarWithoutBones/dotfiles/commit/0b3faad8bd1d0e1af6103caf59b206666ab742f4