From 6e20cedb671c3d03c4060fabf82920cf36b87e4f Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Mon, 24 Mar 2025 13:37:25 +0000 Subject: [PATCH] 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. --- Library/Homebrew/cmd/bundle.rb | 19 ++++++------ Library/Homebrew/dev-cmd/sh.rb | 35 +++++++++-------------- Library/Homebrew/test/utils/shell_spec.rb | 22 ++++++++++++++ Library/Homebrew/utils/shell.rb | 16 +++++++++++ bin/brew | 10 +++++++ 5 files changed, 71 insertions(+), 31 deletions(-) diff --git a/Library/Homebrew/cmd/bundle.rb b/Library/Homebrew/cmd/bundle.rb index c7b8394dff..9e7e4bc714 100755 --- a/Library/Homebrew/cmd/bundle.rb +++ b/Library/Homebrew/cmd/bundle.rb @@ -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 diff --git a/Library/Homebrew/dev-cmd/sh.rb b/Library/Homebrew/dev-cmd/sh.rb index d7dbc389f5..c6161dd1ad 100644 --- a/Library/Homebrew/dev-cmd/sh.rb +++ b/Library/Homebrew/dev-cmd/sh.rb @@ -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 diff --git a/Library/Homebrew/test/utils/shell_spec.rb b/Library/Homebrew/test/utils/shell_spec.rb index 3855f08131..66cf8edfd8 100644 --- a/Library/Homebrew/test/utils/shell_spec.rb +++ b/Library/Homebrew/test/utils/shell_spec.rb @@ -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 diff --git a/Library/Homebrew/utils/shell.rb b/Library/Homebrew/utils/shell.rb index 1e88d881dd..4582542438 100644 --- a/Library/Homebrew/utils/shell.rb +++ b/Library/Homebrew/utils/shell.rb @@ -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 diff --git a/bin/brew b/bin/brew index f8f86335fe..3ccf7f68a2 100755 --- a/bin/brew +++ b/bin/brew @@ -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"