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

View File

@ -39,32 +39,25 @@ module Homebrew
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?
safe_system(preferred_shell, "-c", args.cmd)
safe_system(preferred_path, "-c", args.cmd)
elsif args.named.present?
safe_system(preferred_shell, args.named.first)
safe_system(preferred_path, args.named.first)
else
shell_type = Utils::Shell.preferred
subshell = case shell_type
when :zsh
"PS1='brew %B%F{green}%~%f%b$ ' #{preferred_shell} -d -f"
when :bash
"PS1=\"brew \\[\\033[1;32m\\]\\w\\[\\033[0m\\]$ \" #{preferred_shell} --noprofile --norc"
else
"PS1=\"brew \\[\\033[1;32m\\]\\w\\[\\033[0m\\]$ \" #{preferred_shell}"
notice = unless Homebrew::EnvConfig.no_env_hints?
<<~EOS
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.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
When done, type `exit`.
EOS
end
puts <<~EOS
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
system Utils::Shell.shell_with_prompt("brew", preferred_path:, notice:)
end
end
end

View File

@ -105,4 +105,26 @@ RSpec.describe Utils::Shell do
.to eq("fish_add_path #{path}")
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

View File

@ -152,5 +152,21 @@ module Utils
str.gsub!("\n", "'\n'")
str
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

View File

@ -265,6 +265,16 @@ then
export HOMEBREW_GITHUB_HOSTED_RUNNER=1
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
PATH="/usr/bin:/bin:/usr/sbin:/sbin"