fish's `set` doesn't modify the exit status when assigning a variable.
This means that `set -q VAR; or set VAR ...` will return an exit status
of 1 even if the variable is suceessfully set. By switching the commands
to `! set -q VAR; and set VAR ...`, this prevents the 1 from propogating
when running `eval (brew shellenv)`.
These were introduced by typos and an incorrect assumption on the last
update of #15358. The last commit had been tested with a parameter, but
had not been re-tested *without* parameter.
Apologies for the error.
Resolves#15358
With this change, `brew shellenv` will accept a shell name parameter to
override its default output (based on `/bin/ps`) for advanced use cases
such as with dotfile templating and caching with
[twpayne/chezmoi](https://github.com/twpayne/chezmoi/discussions/2971).
When running under `fish`, this is the output:
```console
$ brew shellenv pwsh
[System.Environment]::SetEnvironmentVariable('HOMEBREW_PREFIX','/opt/homebrew',[System.EnvironmentVariableTarget]::Process)
[System.Environment]::SetEnvironmentVariable('HOMEBREW_CELLAR','/opt/homebrew/Cellar',[System.EnvironmentVariableTarget]::Process)
[System.Environment]::SetEnvironmentVariable('HOMEBREW_REPOSITORY','/opt/homebrew',[System.EnvironmentVariableTarget]::Process)
[System.Environment]::SetEnvironmentVariable('PATH',$('/opt/homebrew/bin:/opt/homebrew/sbin:'+$ENV:PATH),[System.EnvironmentVariableTarget]::Process)
[System.Environment]::SetEnvironmentVariable('MANPATH',$('/opt/homebrew/share/man'+$(if(${ENV:MANPATH}){':'+${ENV:MANPATH}})+':'),[System.EnvironmentVariableTarget]::Process)
[System.Environment]::SetEnvironmentVariable('INFOPATH',$('/opt/homebrew/share/info'+$(if(${ENV:INFOPATH}){':'+${ENV:INFOPATH}})),[System.EnvironmentVariableTarget]::Process)
$ brew shellenv
set -gx HOMEBREW_PREFIX "/opt/homebrew";
set -gx HOMEBREW_CELLAR "/opt/homebrew/Cellar";
set -gx HOMEBREW_REPOSITORY "/opt/homebrew";
set -q PATH; or set PATH ''; set -gx PATH "/opt/homebrew/bin" "/opt/homebrew/sbin" $PATH;
set -q MANPATH; or set MANPATH ''; set -gx MANPATH "/opt/homebrew/share/man" $MANPATH;
set -q INFOPATH; or set INFOPATH ''; set -gx INFOPATH "/opt/homebrew/share/info" $INFOPATH;
```
The specific case presented in the mentioned discussion could be
mitigated by an additional level of indirection (`{{ output "fish" "-c"
"'brew shellenv'" | trim }}`), that requires that the running system
have the target shells installed, when they are not strictly necessary
with `brew shellenv`.
Some setups (e.g. a default `tmux` session) will result in a user
starting multiple nested login shells. This is a problem for the way we
currently handle `shellenv` because a login shell invokes
`/usr/libexec/path_helper` which will prepend the contents of
`/etc/paths` and `/etc/paths.d` to `PATH`. In particular, the second
login shell will place `brew` further down the `PATH` than desired in a
non-`/usr/local` prefix, since `brew shellenv` will no longer produce
output the second time around.
Let's fix this by replacing the check that `brew` is in `PATH` with a
check that `${HOMEBREW_PREFIX}/bin` precedes `/usr/bin` in `PATH`.
Fixes#11851, #11883, Homebrew/discussions#2547.
See also:
- Homebrew/discussions#2237
- https://superuser.com/questions/544989/does-tmux-sort-the-path-variable
It looks like #7738 removed the default unintentionally. This adds it back.
For scripts that `set -u`, this will fail if $INFOPATH is not already set (`INFOPATH: unbound variable`). This provides an empty default, but one that will still satisfy the trailing colon requirement.
It currently switches on `$SHELL`, which points to the user's login shell. However, `shellenv` may be used in contexts where the running shell isn't `$SHELL` (e.g. csh-based `cron` scripts), and Linux desktop environments may set up user sessions in ways that trip up the current algorithm (see #7965 for an example). To work correctly in all circumstances and environments, its output should be determined by the context (calling shell) instead.
Fixes#7965.
The behavior of some programs (e.g., emacs) differs depending on
whether INFOPATH is terminated in a colon or not. For example, the
info viewer built into emacs has a default list of places from which
it will draw info files, and it will only check this if either (a)
INFOPATH is unset, or (b) INFOPATH ends in a colon.
Currently brew shellenv prepends to the existing $INFOPATH and will
separate with a colon if $INFOPATH already exists, but if it does not
it will not terminate in a colon. As a result, info
pages (like emacs and elisp) are missing from the info viewer.
The existing brew shellenv logic used a parameter expansion trick to
include a colon only if it was prepending to an extant INFOPATH, but
because we want brew's contribution to the INFOPATH to always end in a
colon (whether there's an existing INFOPATH or not), we don't have to
use the parameter expansion trick
This commit only changes behavior for "other" shells (i.e., not fish,
csh, or tcsh) since I don't know how to append a colon to variables in
these shells.
$SHELL is set to only the binary name in some environments (e.g. fish, not /usr/bin/fish), causing detection of fish/csh/tsch to fail without this change.