fish_git_prompt: be careful about invoking git on macOS

git on macOS has two hazards:

1. It comes "preinstalled" as a stub which pops a dialog to install
   command line developer tools.

2. It may populate the xcrun cache when run for the first time, which
   may take several seconds.

We fix these as follows, both fixes limited to Darwin:

1. If git is `/usr/bin/git` and `xcode-select --print-path` fails,
   then do not run git automatically.

2. Second, if there is no file at `xcrun --show-cache-path`, we take it
   as an indication that the cache is not yet populated. In this case we
   run `git` in the background to populate the cache.

Credit to @floam for the idea.

Fixes #9343. Fixes #6625.
This commit is contained in:
ridiculousfish 2022-12-26 13:17:53 -08:00 committed by Peter Ammon
parent 2e01b0038d
commit a77bc70def

View File

@ -168,12 +168,39 @@ function __fish_git_prompt_show_upstream --description "Helper function for fish
test "$count" = "0 0"
end
# Decide if git is safe to run.
# On Darwin, git is pre-installed as a stub, which will pop a dialog if you run it.
if string match -q Darwin -- "$(uname)" && type -q xcode-select && type -q xcrun
if string match -q /usr/bin/git -- "$(command -s git)" && not xcode-select --print-path &>/dev/null
# Only the stub git is installed.
# Do not try to run it.
function __fish_git_prompt_ready
return 1
end
else
# 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.
command git --version &>/dev/null &
disown
function __fish_git_prompt_ready
path is "$(xcrun --show-cache-path)" || return 1
# git is ready, erase the function.
functions -e __fish_git_prompt_ready
return 0
end
end
end
function fish_git_prompt --description "Prompt function for Git"
# If git isn't installed, there's nothing we can do
# Return 1 so the calling prompt can deal with it
if not command -sq git
return 1
end
# Fail if __fish_git_prompt_ready is defined and fails.
if functions -q __fish_git_prompt_ready && not __fish_git_prompt_ready
return 1
end
set -l repo_info (command git rev-parse --git-dir --is-inside-git-dir --is-bare-repository --is-inside-work-tree HEAD 2>/dev/null)
test -n "$repo_info"
or return