Don't filter the environment for brew bundle (exec|env|sh)

It's both unexpected and undesirable for `brew bundle (exec|env|sh)` to
filter the environment and makes these tools less useful.

Not filtering the environment, though, causes issues with the
`brew bundle sh` shell. Fix this up and, while we're here, also improve
the formatting for both `zsh` and `bash` (the default) to use nicer and
more consistent prompts and colours.

To simplify this, consolidate some logic in a new
`Utils::Shell.shell_with_prompt` method and add tests for it and a
similar notice for `brew bundle sh`.

Finally, avoid printing out the notice when `HOMEBREW_NO_ENV_HINTS` is
set.
This commit is contained in:
Mike McQuaid 2025-03-24 13:37:25 +00:00
parent f104184214
commit 6e20cedb67
No known key found for this signature in database
5 changed files with 71 additions and 31 deletions

View File

@ -210,18 +210,17 @@ module Homebrew
_subcommand, *named_args = args.named _subcommand, *named_args = args.named
named_args named_args
when "sh" when "sh"
preferred_shell = Utils::Shell.preferred_path(default: "/bin/bash") preferred_path = Utils::Shell.preferred_path(default: "/bin/bash")
subshell = case Utils::Shell.preferred notice = unless Homebrew::EnvConfig.no_env_hints?
when :zsh <<~EOS
"PS1='brew bundle %B%F{green}%~%f%b$ ' #{preferred_shell} -d -f" Your shell has been configured to use a build environment from your `Brewfile`.
when :bash This should help you build stuff.
"PS1=\"brew bundle \\[\\033[1;32m\\]\\w\\[\\033[0m\\]$ \" #{preferred_shell} --noprofile --norc" Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
else When done, type `exit`.
"PS1=\"brew bundle \\[\\033[1;32m\\]\\w\\[\\033[0m\\]$ \" #{preferred_shell}" EOS
end end
$stdout.flush
ENV["HOMEBREW_FORCE_API_AUTO_UPDATE"] = nil ENV["HOMEBREW_FORCE_API_AUTO_UPDATE"] = nil
[subshell] [Utils::Shell.shell_with_prompt("brew bundle", preferred_path:, notice:)]
when "env" when "env"
["env"] ["env"]
end end

View File

@ -39,32 +39,25 @@ module Homebrew
ENV["VERBOSE"] = "1" if args.verbose? ENV["VERBOSE"] = "1" if args.verbose?
preferred_shell = Utils::Shell.preferred_path(default: "/bin/bash") preferred_path = Utils::Shell.preferred_path(default: "/bin/bash")
if args.cmd.present? if args.cmd.present?
safe_system(preferred_shell, "-c", args.cmd) safe_system(preferred_path, "-c", args.cmd)
elsif args.named.present? elsif args.named.present?
safe_system(preferred_shell, args.named.first) safe_system(preferred_path, args.named.first)
else else
shell_type = Utils::Shell.preferred notice = unless Homebrew::EnvConfig.no_env_hints?
subshell = case shell_type <<~EOS
when :zsh Your shell has been configured to use Homebrew's build environment;
"PS1='brew %B%F{green}%~%f%b$ ' #{preferred_shell} -d -f" this should help you build stuff. Notably though, the system versions of
when :bash gem and pip will ignore our configuration and insist on using the
"PS1=\"brew \\[\\033[1;32m\\]\\w\\[\\033[0m\\]$ \" #{preferred_shell} --noprofile --norc" environment they were built under (mostly). Sadly, scons will also
else ignore our configuration.
"PS1=\"brew \\[\\033[1;32m\\]\\w\\[\\033[0m\\]$ \" #{preferred_shell}" Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
When done, type `exit`.
EOS
end end
puts <<~EOS system Utils::Shell.shell_with_prompt("brew", preferred_path:, notice:)
Your shell has been configured to use Homebrew's build environment;
this should help you build stuff. Notably though, the system versions of
gem and pip will ignore our configuration and insist on using the
environment they were built under (mostly). Sadly, scons will also
ignore our configuration.
When done, type `exit`.
EOS
$stdout.flush
safe_system subshell
end end
end end
end end

View File

@ -105,4 +105,26 @@ RSpec.describe Utils::Shell do
.to eq("fish_add_path #{path}") .to eq("fish_add_path #{path}")
end end
end end
describe "::shell_with_prompt" do
it "returns zsh-specific prompt configuration" do
ENV["SHELL"] = "/bin/zsh"
expect(described_class.shell_with_prompt("test", preferred_path: "/bin/zsh", notice: "")).to eq(
"PROMPT='%B%F{green}test%f %F{blue}$%f%b ' RPROMPT='[%B%F{red}%~%f%b]' /bin/zsh -f",
)
end
it "returns generic shell prompt configuration" do
ENV["SHELL"] = "/bin/bash"
expect(described_class.shell_with_prompt("test", preferred_path: "/bin/bash", notice: "")).to eq(
"PS1=\"\\[\\033[1;32m\\]brew \\[\\033[1;31m\\]\\w \\[\\033[1;34m\\]$\\[\\033[0m\\] \" /bin/bash",
)
end
it "outputs notice when provided" do
notice = "Test Notice"
expect { described_class.shell_with_prompt("test", preferred_path: "/bin/bash", notice: notice) }
.to output("#{notice}\n").to_stdout
end
end
end end

View File

@ -152,5 +152,21 @@ module Utils
str.gsub!("\n", "'\n'") str.gsub!("\n", "'\n'")
str str
end end
sig { params(type: String, preferred_path: String, notice: T.nilable(String)).returns(String) }
def shell_with_prompt(type, preferred_path:, notice:)
preferred = from_path(preferred_path)
subshell = case preferred
when :zsh
"PROMPT='%B%F{green}#{type}%f %F{blue}$%f%b ' RPROMPT='[%B%F{red}%~%f%b]' #{preferred_path} -f"
else
"PS1=\"\\[\\033[1;32m\\]brew \\[\\033[1;31m\\]\\w \\[\\033[1;34m\\]$\\[\\033[0m\\] \" #{preferred_path}"
end
puts notice if notice.present?
$stdout.flush
subshell
end
end end
end end

View File

@ -265,6 +265,16 @@ then
export HOMEBREW_GITHUB_HOSTED_RUNNER=1 export HOMEBREW_GITHUB_HOSTED_RUNNER=1
fi fi
# don't filter the environment for `brew bundle (exec|env|sh)`
if [[ "${1:-}" == "bundle" ]]
then
if [[ "${2:-}" == "exec" || "${2:-}" == "env" || "${2:-}" == "sh" ]]
then
exec /bin/bash -p "${HOMEBREW_LIBRARY}/Homebrew/brew.sh" "$@"
exit $?
fi
fi
# filter the user environment # filter the user environment
PATH="/usr/bin:/bin:/usr/sbin:/sbin" PATH="/usr/bin:/bin:/usr/sbin:/sbin"