fix(bash): use `eval` instead of a procsub for the POSIX mode (#5020)

fix(bash): use eval instead of a procsub for the POSIX mode
This commit is contained in:
Koichi Murase 2024-04-02 17:45:02 +09:00 committed by GitHub
parent 55e11a42e5
commit 0f859e8b61
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 26 additions and 24 deletions

View File

@ -9,11 +9,11 @@ use which::which;
shell. This command evaluates a more complicated script using `source` and
process substitution.
Directly using `eval` on a shell script causes it to be evaluated in
a single line, which sucks because things like comments will comment out the
rest of the script, and you have to spam semicolons everywhere. By using
source and process substitutions, we make it possible to comment and debug
the init scripts.
Directly using `eval` on a shell script without proper quoting causes it to be
evaluated in a single line, which sucks because things like comments will
comment out the rest of the script, and you have to spam semicolons
everywhere. By using source and process substitutions, we make it possible to
comment and debug the init scripts.
In the future, this may be changed to just directly evaluating the initscript
using whatever mechanism is available in the host shell--this two-phase solution
@ -106,8 +106,13 @@ pub fn init_stub(shell_name: &str) -> io::Result<()> {
match shell_basename {
"bash" => print!(
/*
* The standard bash bootstrap is:
/* We now use the following bootstrap:
* `eval -- "$(starship init bash --print-full-init)"`
* which works in any version of Bash from 3.2 to the latest
* version and also works in the POSIX mode.
*
* ----
* Historically, the standard bash bootstrap was:
* `source <(starship init bash --print-full-init)`
*
* Unfortunately there is an issue with bash 3.2 (the MacOS
@ -129,28 +134,25 @@ pub fn init_stub(shell_name: &str) -> io::Result<()> {
* with the standard bootstrap, whereas bash 4.1 appears to be
* consistently compatible.
*
* The upshot of all of this, is that we will use the standard
* bootstrap whenever the bash version is 4.1 or higher. Otherwise,
* we fall back to the `/dev/stdin` solution.
* We had been using the standard bootstrap whenever the bash
* version is 4.1 or higher. Otherwise, we fell back to the
* `/dev/stdin` solution.
*
* However, process substitutions <(...) are not supported in the
* POSIX mode of Bash <= 5.0, so we switch to the approach with
* `eval -- "$(...)"`. The reason for not using `eval` seems to be
* explained at the top of this file, i.e., the script will be
* evaluated as if it is a single line, but that is caused by an
* improper quoting.
*
* More background can be found in these pull requests:
* https://github.com/starship/starship/pull/241
* https://github.com/starship/starship/pull/278
* https://github.com/starship/starship/issues/1674
* https://github.com/starship/starship/pull/5020
* https://github.com/starship/starship/issues/5382
*/
r#"
__main() {{
local major="${{BASH_VERSINFO[0]}}"
local minor="${{BASH_VERSINFO[1]}}"
if ((major > 4)) || {{ ((major == 4)) && ((minor >= 1)); }}; then
source <({0} init bash --print-full-init)
else
source /dev/stdin <<<"$({0} init bash --print-full-init)"
fi
}}
__main
unset -f __main
"#,
r#"eval -- "$({0} init bash --print-full-init)""#,
starship.sprint_posix()?
),
"zsh" => print_script(ZSH_INIT, &starship.sprint_posix()?),