NixOS / nix

Nix, the purely functional package manager
https://nixos.org/
GNU Lesser General Public License v2.1
11.96k stars 1.46k forks source link

Provide a convention for allowing MacOS Spotlight to index Applications without getting hacky #7055

Open erikkrieg opened 1 year ago

erikkrieg commented 1 year ago

Describe the bug

I am trying to use nix-env to install applications like Alacritty and others that come with a .app file, but Spotlight won't work without manual changes to configuration post-install of nix. To integrate this with MacOS, I am using stow to create a symlink for that .app file in my /Applications directory. This alias can be clicked directly or added to the dock without issue, but Spotlight will not index those symlinked files.

I am aware that there was a change to explicitly prevent indexing of the /nix directory, some documentation being added here: https://github.com/NixOS/nix/pull/5730. After a bit more digging I found that I could remove that nobrowse option and found that after dropping it and restarting my computer the applications were indexed. While I have a solution, I don't really like it. It is brittle and opaque. I think other people will also want to do something similar on MacOS, so have a conventional solution seems appropriate.

Steps To Reproduce

  1. On a Mac (I'm using Monterey 12.6 on arm64 arch, but I am thinking other darwin machines will be affected).
  2. Install Alacritty nix-env -iA nixpkgs.alacritty.
  3. GNU Stow: stow -d "$(nix-env -q --installed alacritty --out-path --no-name)" -t /Applications Applications.
  4. Looking for alacritty in the spotlight or mdfind alacritty does not find the executable app.
  5. sudo vifs and remove nobrowse for /nix.
  6. Now mdfind alacritty turns up results.

Expected behavior

Now, I'm very new to Nix and there is a lot to digest, so I might have missed this, but what I'd hope to have seen is something in the manual or other docs that gives instructions on a standard Nix solution for installing apps in MacOS that are properly integrated like traditionally installed applications, i.e. can be found in /Applications and searched for with Spotlight. It would also be ideal if the fix does not require manually modifying a file post-install of nix.

nix-env --version output nix-env (Nix) 2.11.1

Additional context I have being going on a deep dive of this tool for a couple days and am really excited about it. Awesome work and thanks so much <3

abathur commented 1 year ago

AIUI, we're between a rock and a hard place here.

First up are the things people tend to want:

  1. People generally don't want their system wasting resources indexing the Nix Store volume, which can be full of 10s or 100s of gigabytes of files.
  2. People find it annoying when they try to search for a file in one of their projects, say "README.md", and get hundreds of results from inside the Nix store.
  3. People do want to launch apps via Spotlight, but they generally don't want it to launch whatever arbitrary store copy of "alacritty" it decided to surface as the top result if their store happens to have 7 different versions in it...
  4. A smaller number of people don't want to see the Nix Store volume on their desktop. This doesn't bug me much personally since I leave all kinds of crap on my desktop anyways, so I suspect it's mostly a gripe for people who like a ~clean desktop?

And then there's what the Apple gives us:

I know some people in the macOS channel on Matrix have been experimenting with trying to find ways around, but (from the sidelines) it's sounded like they all have problems of their own. Barring discovery of good options that I don't yet know about, I suspect our best bets are:

  1. Someone with knowledge/time/energy pulling on the spotlight plugin thread to see if we could plausibly surface applications in an active profile or just based on the symlinks in /Applications and ~/Applications?
  2. Trying to nag Apple into a fix/improvement in future macOS versions.
erikkrieg commented 1 year ago

Really appreciate that thorough response. Part of my thinking in raising this issue was that it was fairly time consuming for me to collect enough info on this issue to find a way forward. Just by having this GitHub issue up with an option might alone be enough to provide some value to people who, like me, get stuck on this.

And what do you think about these other possible responses to this issue?

  1. Include in the manual an entry on these issues with some suggestions around it (with caveats)
  2. Introduce an option when installing a package where .app files are moved /Applications and create the symlink back into the nix store.

Option 1 doesn't fix the real problem, but will hopefully save people an 30+ minutes of digging. Option 2 feel like a bit of a long shot. I don't have the insight into Nix to know if it is a crazy suggestion or not (but at least if it is a new option then it would be a backwards compatible change).

abathur commented 1 year ago

I'm not really responding as a decider here, just as someone who had to wrestle with some of these details while doing some installer work. This might get more interesting with feedback from more of the people who've looked into this, so I've posted it in chat.

This (managing stateful non-Nix directories on the host system tends) also falls in a bit of a roll-off between what tends to get treated as Nix's responsibility and what tends to get left up to other tools.

I'm not sure if a true fix within Nix itself would be seen as in-scope, but in any case I suspect it won't make a ton of sense to try to address this at that level until the attempts to address it (I think just for ~/Applications?) within nix-darwin seem to have settled on a solid approach that satisfies everyone there. (Mostly just because it'll be cheaper to iterate and experiment there than it will be in Nix itself.)

sellout commented 1 year ago

There's a lot of discussion about this in the context of nix-community/home-manager#1341 and LnL7/nix-darwin#214. I think the home-manager thread arrives at a good solution, and I've got a not-too-hacky version in home.nix to tide me over until changes land:

    home.activation = {
      # This should be removed once
      # https://github.com/nix-community/home-manager/issues/1341 is closed.
      aliasApplications = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
        app_folder="$(echo ~/Applications)/Home Manager Apps"
        home_manager_app_folder="$genProfilePath/home-path/Applications"
        $DRY_RUN_CMD rm -rf "$app_folder"
        # NB: aliasing ".../home-path/Applications" to "~/Applications/Home Manager Apps" doesn't
        #     work (presumably because the individual apps are symlinked in that directory, not
        #     aliased). So this makes "Home Manager Apps" a normal directory and then aliases each
        #     application into there directly from its location in the nix store.
        $DRY_RUN_CMD mkdir "$app_folder"
        for app in $(find "$newGenPath/home-path/Applications" -type l -exec readlink -f {} \;)
        do
          $DRY_RUN_CMD osascript \
            -e "tell app \"Finder\"" \
            -e "make new alias file at POSIX file \"$app_folder\" to POSIX file \"$app\"" \
            -e "set name of result to \"$(basename $app)\"" \
            -e "end tell"
        done
      '';
    };
protex commented 3 months ago

FWIW, I've found that the cleanest way to do this is to just delete/copy the application in the activation script. It just takes 3 lines and has never caused problems for me.

Example (unsure if the chmod is still necessary, it was at some point):

  home.activation.kitty = lib.hm.dag.entryAfter ["writeBoundry"] ''
    $DRY_RUN_CMD [ -f ~/Applications/kitty.app ] && rm -rf ~/Applications/kitty.app
    $DRY_RUN_CMD cp -r ${pkgs.kitty}/Applications/kitty.app/ ~/Applications
    $DRY_RUN_CMD chmod -R 755 ~/Applications/kitty.app
  '';
elsbrock commented 2 months ago

If we were able to do that generically, eg via mainProgram, that’d be perfect.