Emulate path_helper more faithfully when constructing paths on macOS

Previously, elements already existing in the path variable would keep their position when the path was being constructed from the config files. This caused issues given that $PATH typically already contains "/usr/bin:/bin" when fish initializes within a macOS terminal app. In this case, these would keep their position at the front of the $PATH, even though the system path_helper configs explicitly place them _after_ other paths, like "/usr/local/bin". This would render binaries in "/usr/local/bin" as effectively "invisible" if they also happen to live in "/usr/bin" as well. This is not the intended

This change makes the __fish_macos_set_env config function emulate the macOS standard path_helper behavior more faithfully, with:

1. The path list being constructed *from scratch* based on the paths specified in the config files
2. Any distinct entries in the exist path environment variable being appended to this list
3. And then this list being used to *replace* the existing path environment variable

The result, for a vanilla fish shell on macOS, is that the $PATH is now set to:

    /usr/local/bin /usr/local/sbin /usr/bin /bin /usr/sbin /sbin

Where previously it was set to:

    /usr/bin /bin /usr/local/bin /usr/sbin /sbin

This new $PATH exactly matches the order of paths specified in `/etc/paths`.
This commit is contained in:
Tim Riley 2019-06-24 09:09:10 +10:00 committed by Fabian Homborg
parent d263093a5a
commit d1be300ac7

View file

@ -173,10 +173,9 @@ if status --is-login
# executable for fish; see # executable for fish; see
# https://opensource.apple.com/source/shell_cmds/shell_cmds-203/path_helper/path_helper.c.auto.html . # https://opensource.apple.com/source/shell_cmds/shell_cmds-203/path_helper/path_helper.c.auto.html .
function __fish_macos_set_env -d "set an environment variable like path_helper does (macOS only)" function __fish_macos_set_env -d "set an environment variable like path_helper does (macOS only)"
# The first argument is the variable name, the others are the files. set -l result
# Keep the components already there so we don't change the order
set -l result $$argv[1]
# Populate path according to config files
for path_file in $argv[2] $argv[3]/* for path_file in $argv[2] $argv[3]/*
if [ -f $path_file ] if [ -f $path_file ]
while read -l entry while read -l entry
@ -188,6 +187,13 @@ if status --is-login
end end
end end
# Merge in any existing path elements
for existing_entry in $$argv[1]
if not contains -- $existing_entry $result
set -a result $existing_entry
end
end
set -xg $argv[1] $result set -xg $argv[1] $result
end end