Rework git detection for macOS

fish by default shows a git-aware prompt. Recall that on macOS, there are
two hazards we must avoid:

1. The command `/usr/bin/git` is installed by default. This command is not
actually git; instead it's a stub which pops open a dialog proposing to
install Xcode command line tools. Not a good experience.
2. Even after installing these tools, the first run of any `git` or other
command may be quite slow, because it's now a stub which invokes `xcrun`
which needs to populate a cache on a fresh boot. Another bad experience.

We previously attempted to fix this by having `xcrun` print out its cache
path and check if there's a file there. This worked because `xcrun` only
lazily created that file. However, this no longer works: `xcrun` now
eagerly creates the file, and only lazily populates it. Thus we think git
is ready, when it is not.

(This can be reproduced by running `xcrun --kill-cache` and then running
the default fish shell prompt - it will be slow).

Change the fix in the following way: using sh, run `/usr/bin/git --version;
touch /tmp/__fish_git_ready` in the background. Then detect the presence of
/tmp/__fish_git_ready as a mark that git is ready.

Fixes #10535
This commit is contained in:
Peter Ammon 2024-11-09 12:08:41 -08:00
parent 2543b8198d
commit dff454b1c7
No known key found for this signature in database

View File

@ -180,10 +180,10 @@ if string match -q Darwin -- (uname) && string match -q /usr/bin/git -- (command
else else
# git is installed, but on the first run it may be very slow as xcrun needs to populate the cache. # git is installed, but on the first run it may be very slow as xcrun needs to populate the cache.
# Kick it off in the background to populate the cache. # Kick it off in the background to populate the cache.
command git --version &>/dev/null & /bin/sh -c '/usr/bin/git --version; touch /tmp/__fish_git_ready' &>/dev/null &
disown $last_pid &>/dev/null disown $last_pid &>/dev/null
function __fish_git_prompt_ready function __fish_git_prompt_ready
path is (xcrun --show-cache-path 2>/dev/null) || return 1 path is /tmp/__fish_git_ready || return 1
# git is ready, erase the function. # git is ready, erase the function.
functions -e __fish_git_prompt_ready functions -e __fish_git_prompt_ready
return 0 return 0