Merge pull request #19733 from Homebrew/improve_brew_bundle_env

Improve `brew bundle exec`/`env`/`sh` environment handling
This commit is contained in:
Mike McQuaid 2025-04-10 14:43:27 +00:00 committed by GitHub
commit 1fb3bf8a14
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 25 additions and 44 deletions

View File

@ -11,47 +11,9 @@ module Homebrew
module Bundle
module Commands
module Exec
# Homebrew's global environment variables that we don't want to leak into
# the `brew bundle exec` environment.
HOMEBREW_ENV_CLEANUP = %w[
HOMEBREW_HELP_MESSAGE
HOMEBREW_API_DEFAULT_DOMAIN
HOMEBREW_BOTTLE_DEFAULT_DOMAIN
HOMEBREW_BREW_DEFAULT_GIT_REMOTE
HOMEBREW_CORE_DEFAULT_GIT_REMOTE
HOMEBREW_DEFAULT_CACHE
HOMEBREW_DEFAULT_LOGS
HOMEBREW_DEFAULT_TEMP
HOMEBREW_REQUIRED_RUBY_VERSION
HOMEBREW_PRODUCT
HOMEBREW_SYSTEM
HOMEBREW_PROCESSOR
HOMEBREW_PHYSICAL_PROCESSOR
HOMEBREW_BREWED_CURL_PATH
HOMEBREW_USER_AGENT_CURL
HOMEBREW_USER_AGENT
HOMEBREW_GENERIC_DEFAULT_PREFIX
HOMEBREW_GENERIC_DEFAULT_REPOSITORY
HOMEBREW_DEFAULT_PREFIX
HOMEBREW_DEFAULT_REPOSITORY
HOMEBREW_AUTO_UPDATE_COMMAND
HOMEBREW_BREW_GIT_REMOTE
HOMEBREW_COMMAND_DEPTH
HOMEBREW_CORE_GIT_REMOTE
HOMEBREW_MACOS_VERSION_NUMERIC
HOMEBREW_MINIMUM_GIT_VERSION
HOMEBREW_MACOS_NEWEST_UNSUPPORTED
HOMEBREW_MACOS_OLDEST_SUPPORTED
HOMEBREW_MACOS_OLDEST_ALLOWED
HOMEBREW_GITHUB_PACKAGES_AUTH
].freeze
PATH_LIKE_ENV_REGEX = /.+#{File::PATH_SEPARATOR}/
def self.run(*args, global: false, file: nil, subcommand: "", services: false)
# Cleanup Homebrew's global environment
HOMEBREW_ENV_CLEANUP.each { |key| ENV.delete(key) }
# Store the old environment so we can check if things were already set
# before we start mutating it.
old_env = ENV.to_h
@ -149,16 +111,37 @@ module Homebrew
# For commands which aren't either absolute or relative
raise "command was not found in your PATH: #{command}" if command.exclude?("/") && which(command).nil?
# Don't need to export Homebrew internal variables that won't be used by other tools.
# Those Homebrew needs have already been set to global constants and/or are exported again later.
# Setting these globally can interfere with nested Homebrew invocations/environments.
ENV.delete_if { |key, _| key.start_with?("HOMEBREW_", "PORTABLE_RUBY_") }
if subcommand == "env"
ENV.sort.each do |key, value|
# No need to export empty values.
next if value.blank?
# Skip exporting non-Homebrew things that were already set in the old environment.
next if !key.start_with?("HOMEBREW_") && old_env.key?(key) && old_env[key] == value
# Skip exporting things that were the same in the old environment.
old_value = old_env[key]
next if old_value == value
# Look for PATH-like environment variables
if key.include?("PATH") && value.match?(PATH_LIKE_ENV_REGEX)
old_values = old_value.to_s.split(File::PATH_SEPARATOR)
path = PATH.new(value)
.reject do |path_value|
# Exclude Homebrew shims from the PATH as they don't work
# without all Homebrew environment variables.
# Exclude existing/old values as they've already been exported.
path_value.include?("/Homebrew/shims/") || old_values.include?(path_value)
end
next if path.blank?
puts "export #{key}=\"#{Utils::Shell.sh_quote(path.to_s)}:${#{key}:-}\""
else
puts "export #{key}=\"#{Utils::Shell.sh_quote(value)}\""
end
end
return
end

View File

@ -65,12 +65,10 @@ RSpec.describe Homebrew::Bundle::Commands::Exec do
context "with env command" do
it "outputs the environment variables" do
ENV["HOMEBREW_PREFIX"] = "/opt/homebrew"
ENV["HOMEBREW_PATH"] = "/usr/bin"
allow(OS).to receive(:linux?).and_return(true)
expect { described_class.run("env", subcommand: "env") }.to \
output(/HOMEBREW_PREFIX="#{ENV.fetch("HOMEBREW_PREFIX")}"/).to_stdout
output(/export PATH=".+:\${PATH:-}"/).to_stdout
end
end