Skip to content

Instantly share code, notes, and snippets.

@abathur
Last active October 27, 2023 17:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save abathur/877a4fa25ec7047baeb3033a9153b269 to your computer and use it in GitHub Desktop.
Save abathur/877a4fa25ec7047baeb3033a9153b269 to your computer and use it in GitHub Desktop.
testing workaround for macOS updates overwriting zsh shell hook

I have a potential fix to the nagging issue of macOS updates overwriting zsh shell init files (causing command not found errors for nix commands). I don't use zsh, so I could use some zsh-using guinea pigs to help validate this approach in day-to-day use.

Get set up - from scratch

If you still have an intel/x86_64-darwin mac (test installers aren't generated for aarch64-darwin yet), the most-helpful test would be to install Nix from scratch using a test installer based on my WIP by running something like this:

sh <(curl -L https://abathur-nix-install-tests.cachix.org/serve/0xjd33idlj3ffm9wzw7jkzs9swxz6vyn/install) --tarball-url-prefix https://abathur-nix-install-tests.cachix.org/serve

This installer is generated in CI, so you can verify what's going on here before you install:

Get set up - existing install

If you have an existing Nix install that you aren't able to remove in order to test from scratch, you can still help test this approach by modifying your zsh init files.

  1. Remove the following from /etc/zshrc (and ~/.zshrc, if you added it there):

    # Nix
    if [ -e /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh ]; then
      . /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
    fi
    # End Nix

    Note: If you don't see this in /etc/zshrc, you may not be a good candidate for this test. Feel free to reach out to confirm.

  2. Create /etc/zshenv (if it doesn't exist) and include the following:

    # Nix
    if [ -e /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh ]; then
      . /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
      export __ETC_PROFILE_NIX_SOURCED=1
    fi
    
    # wrap path_helper to keep it from pushing nix rightwards
    /usr/libexec/path_helper() {
        case "$1" in
            "-c")
                # don't interfere if this gets invoked with -c
                command /usr/libexec/path_helper "$@"
                ;;
            *)
                (
                    # subshell to see what path_helper would do to PATH. inject a
                    # separator for splitting (saving previous PATH can duplicate
                    # entries, and people tend to see that as a smell)
                    eval "$(PATH="nixpathsep:$PATH" command /usr/libexec/path_helper "$@")"
                    local prefixed="${PATH%%:nixpathsep:*}" pushed_back="${PATH##*:nixpathsep:}"
    
                   # re-emit what path_helper would; remove function to avoid rerunning
                    echo "PATH=\"${pushed_back}:${prefixed}\"; export PATH; unset -f /usr/libexec/path_helper;"
                )
                ;;
        esac
    }
    # End Nix

    Note: If you diff this with the linked commits, you may notice that the code above there doesn't export __ETC_PROFILE_NIX_SOURCED. I'm adding it here to approximate some changes I'm making to nix-daemon.sh that aren't as easy for you to test in an ad-hoc manner.

Providing feedback

There are two main things we need to validate about this approach:

  1. Does it cause you any day-to-day usage problems:
    • Are Nix-installed utilities ahead of system utilities on your PATH? (type -a <utility> or which -a <utility> can help check)
    • Do you notice any problems in basic interactive shell sessions?
    • Do you notice any problems in other contexts such as launchd services or cron jobs, ssh sessions, IDE consoles, etc.
    • Does zsh work correctly as a script shebang/interpreter?
  2. Does it survive macOS updates.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment