mirror of
https://github.com/Homebrew/brew.git
synced 2026-10-28 09:34:42 +08:00
Deprecate Homebrew wrapper configuration
- Classify third-party wrappers as Tier 3 and centralise their support guidance in `Support-Tiers.md`. - Retire required wrappers, custom help and the opt-out together. - Check Bash-only environment deprecations before Ruby commands, reusing the per-process warning cache in `EnvConfig`. - Leave Ruby-backed environment deprecations to their accessors. - Remove shell validation, conflict errors and custom help output. - Invoke internal commands through Homebrew, not the wrapper, and remove private parent-process inspection and executable overrides. - Prepend Homebrew's `bin` and `sbin` without reading custom path files. - Warn when another `brew` shadows this installation, sharing the existing PATH diagnostics and shell-specific remediation.
This commit is contained in:
27 files changed
+458
-268
No files matched your search
@@ -122,6 +122,10 @@ begin
|
||||
# `Homebrew::Help.help` never returns, except for unknown and deferred commands.
|
||||
end
|
||||
|
||||
if !help_flag && (internal_cmd || external_ruby_v2_cmd || external_ruby_cmd_path || external_cmd_path)
|
||||
Homebrew::EnvConfig.check_deprecated_bash_variables
|
||||
end
|
||||
|
||||
if cmd.nil?
|
||||
raise UsageError, "Unknown command: brew #{ARGV.join(" ")}"
|
||||
elsif internal_cmd || external_ruby_v2_cmd
|
||||
|
||||
@@ -133,14 +133,6 @@ case "$@" in
|
||||
;;
|
||||
esac
|
||||
|
||||
# Check `HOMEBREW_FORCE_BREW_WRAPPER` for all non-trivial commands
|
||||
# (i.e. not defined above this line e.g. formulae or --cellar).
|
||||
if [[ -n "${HOMEBREW_FORCE_BREW_WRAPPER:-}" ]]
|
||||
then
|
||||
source "${HOMEBREW_LIBRARY}/Homebrew/utils/wrapper.sh"
|
||||
check-brew-wrapper "$1"
|
||||
fi
|
||||
|
||||
# commands that take a single or no arguments and need to write to HOMEBREW_PREFIX.
|
||||
# HOMEBREW_LIBRARY set by bin/brew
|
||||
# shellcheck disable=SC2154
|
||||
|
||||
@@ -28,23 +28,6 @@ homebrew-shellenv() {
|
||||
HOMEBREW_SHELL_NAME="${SHELL##*/}"
|
||||
fi
|
||||
|
||||
if [[ -n "${HOMEBREW_MACOS}" ]] &&
|
||||
[[ "${HOMEBREW_MACOS_VERSION_NUMERIC}" -ge "140000" ]] &&
|
||||
[[ -x /usr/libexec/path_helper ]]
|
||||
then
|
||||
HOMEBREW_PATHS_FILE="${HOMEBREW_PREFIX}/etc/paths"
|
||||
|
||||
if [[ ! -f "${HOMEBREW_PATHS_FILE}" ]]
|
||||
then
|
||||
printf '%s/bin\n%s/sbin\n' "${HOMEBREW_PREFIX}" "${HOMEBREW_PREFIX}" 2>/dev/null >"${HOMEBREW_PATHS_FILE}"
|
||||
fi
|
||||
|
||||
if [[ -r "${HOMEBREW_PATHS_FILE}" ]]
|
||||
then
|
||||
PATH_HELPER_ROOT="${HOMEBREW_PREFIX}"
|
||||
fi
|
||||
fi
|
||||
|
||||
case "${HOMEBREW_SHELL_NAME}" in
|
||||
fish | -fish)
|
||||
echo "set --global --export HOMEBREW_PREFIX \"${HOMEBREW_PREFIX}\";"
|
||||
@@ -58,12 +41,7 @@ homebrew-shellenv() {
|
||||
echo "setenv HOMEBREW_PREFIX ${HOMEBREW_PREFIX};"
|
||||
echo "setenv HOMEBREW_CELLAR ${HOMEBREW_CELLAR};"
|
||||
echo "setenv HOMEBREW_REPOSITORY ${HOMEBREW_REPOSITORY};"
|
||||
if [[ -n "${PATH_HELPER_ROOT}" ]]
|
||||
then
|
||||
echo "eval \`/usr/bin/env PATH_HELPER_ROOT=\"${PATH_HELPER_ROOT}\" /usr/libexec/path_helper -c\`;"
|
||||
else
|
||||
echo "setenv PATH \"${HOMEBREW_PREFIX}/bin:${HOMEBREW_PREFIX}/sbin:\$PATH\";"
|
||||
fi
|
||||
echo "setenv PATH \"${HOMEBREW_PREFIX}/bin:${HOMEBREW_PREFIX}/sbin:\$PATH\";"
|
||||
echo "test \${?MANPATH} -eq 1 && test -n \"\${MANPATH}\" && setenv MANPATH :\`printf '%s' \"\${MANPATH}\" | /usr/bin/sed -e 's/^:*//' -e 's/:*\$//'\`;"
|
||||
echo "test \${?INFOPATH} -eq 1 || setenv INFOPATH '';"
|
||||
echo "setenv INFOPATH \"${HOMEBREW_PREFIX}/share/info:\${INFOPATH}\";"
|
||||
@@ -85,12 +63,7 @@ homebrew-shellenv() {
|
||||
echo "fpath[1,0]=\"${HOMEBREW_PREFIX}/share/zsh/site-functions\";"
|
||||
echo "export FPATH;"
|
||||
fi
|
||||
if [[ -n "${PATH_HELPER_ROOT}" ]]
|
||||
then
|
||||
echo "eval \"\$(/usr/bin/env PATH_HELPER_ROOT=\"${PATH_HELPER_ROOT}\" /usr/libexec/path_helper -s)\""
|
||||
else
|
||||
echo "export PATH=\"${HOMEBREW_PREFIX}/bin:${HOMEBREW_PREFIX}/sbin\${PATH+:\$PATH}\";"
|
||||
fi
|
||||
echo "export PATH=\"${HOMEBREW_PREFIX}/bin:${HOMEBREW_PREFIX}/sbin\${PATH+:\$PATH}\";"
|
||||
echo "[ -z \"\${MANPATH-}\" ] || { export MANPATH=\"\${MANPATH%\"\${MANPATH##*[!:]}\"}\"; export MANPATH=\":\${MANPATH#\"\${MANPATH%%[!:]*}\"}\"; };"
|
||||
echo "export INFOPATH=\"${HOMEBREW_PREFIX}/share/info:\${INFOPATH:-}\";"
|
||||
;;
|
||||
|
||||
@@ -519,13 +519,28 @@ module Homebrew
|
||||
)
|
||||
end
|
||||
|
||||
sig { returns(T.nilable(Finding)) }
|
||||
def check_brew_path
|
||||
brew = which("brew", paths)
|
||||
return if brew.nil? || File.identical?(brew, HOMEBREW_BREW_FILE)
|
||||
|
||||
Finding.new(
|
||||
<<~EOS,
|
||||
Another `brew` shadows this Homebrew installation in your PATH:
|
||||
#{brew}
|
||||
|
||||
This may be a helper, wrapper or another Homebrew installation.
|
||||
EOS
|
||||
remediation: path_remediation,
|
||||
)
|
||||
end
|
||||
|
||||
sig { returns(T.nilable(Finding)) }
|
||||
def check_user_path_1
|
||||
@seen_prefix_bin = false
|
||||
@seen_prefix_sbin = false
|
||||
|
||||
message = ""
|
||||
remediation = T.let(nil, T.nilable(Finding::Remediation))
|
||||
|
||||
paths.each do |p|
|
||||
case p
|
||||
@@ -545,15 +560,6 @@ module Homebrew
|
||||
|
||||
The following tools exist at both paths:
|
||||
EOS
|
||||
prepend_path = Utils::Shell.prepend_path_in_profile("#{HOMEBREW_PREFIX}/bin")
|
||||
remediation = Finding::Remediation.new(
|
||||
text: <<~EOS,
|
||||
Consider setting your PATH so that
|
||||
#{HOMEBREW_PREFIX}/bin occurs before /usr/bin. Here is a one-liner:
|
||||
#{prepend_path}
|
||||
EOS
|
||||
commands: [prepend_path].compact,
|
||||
)
|
||||
end
|
||||
end
|
||||
when "#{HOMEBREW_PREFIX}/bin"
|
||||
@@ -564,7 +570,7 @@ module Homebrew
|
||||
end
|
||||
|
||||
@user_path_1_done = true
|
||||
Finding.new(message, remediation:) if message.present?
|
||||
Finding.new(message, remediation: path_remediation) if message.present?
|
||||
end
|
||||
|
||||
sig { returns(T.nilable(Finding)) }
|
||||
@@ -572,18 +578,11 @@ module Homebrew
|
||||
check_user_path_1 unless @user_path_1_done
|
||||
return if @seen_prefix_bin
|
||||
|
||||
prepend_path = Utils::Shell.prepend_path_in_profile("#{HOMEBREW_PREFIX}/bin")
|
||||
Finding.new(
|
||||
<<~EOS,
|
||||
Homebrew's "bin" was not found in your PATH.
|
||||
EOS
|
||||
remediation: Finding::Remediation.new(
|
||||
text: <<~EOS,
|
||||
Consider setting your PATH for example like so:
|
||||
#{prepend_path}
|
||||
EOS
|
||||
commands: [prepend_path].compact,
|
||||
),
|
||||
remediation: path_remediation,
|
||||
)
|
||||
end
|
||||
|
||||
@@ -598,19 +597,12 @@ module Homebrew
|
||||
return if sbin.children.empty?
|
||||
return if sbin.children.one? && sbin.children.first.basename.to_s == ".keepme"
|
||||
|
||||
prepend_path = Utils::Shell.prepend_path_in_profile("#{HOMEBREW_PREFIX}/sbin")
|
||||
Finding.new(
|
||||
<<~EOS,
|
||||
Homebrew's "sbin" was not found in your PATH but you have installed
|
||||
formulae that put executables in #{HOMEBREW_PREFIX}/sbin.
|
||||
EOS
|
||||
remediation: Finding::Remediation.new(
|
||||
text: <<~EOS,
|
||||
Consider setting your PATH for example like so:
|
||||
#{prepend_path}
|
||||
EOS
|
||||
commands: [prepend_path].compact,
|
||||
),
|
||||
remediation: path_remediation(sbin.to_s),
|
||||
)
|
||||
end
|
||||
|
||||
@@ -1643,6 +1635,18 @@ module Homebrew
|
||||
|
||||
private
|
||||
|
||||
sig { params(path: String).returns(Finding::Remediation) }
|
||||
def path_remediation(path = "#{HOMEBREW_PREFIX}/bin")
|
||||
prepend_path = Utils::Shell.prepend_path_in_profile(path)
|
||||
Finding::Remediation.new(
|
||||
text: <<~EOS,
|
||||
Consider setting your PATH for example like so:
|
||||
#{prepend_path}
|
||||
EOS
|
||||
commands: [prepend_path].compact,
|
||||
)
|
||||
end
|
||||
|
||||
sig { returns(T::Array[String]) }
|
||||
def paths
|
||||
@paths ||= T.let(ORIGINAL_PATHS.uniq.map(&:to_s), T.nilable(T::Array[String]))
|
||||
|
||||
@@ -431,12 +431,14 @@ module Homebrew
|
||||
boolean: :set,
|
||||
},
|
||||
HOMEBREW_FORCE_BREW_WRAPPER: {
|
||||
description: "If set, require `brew` to be invoked by the value of " \
|
||||
"`$HOMEBREW_FORCE_BREW_WRAPPER` for non-trivial `brew` commands.",
|
||||
description: "No longer used.",
|
||||
replacement: "your wrapper directly",
|
||||
odeprecated: true,
|
||||
},
|
||||
HOMEBREW_FORCE_BREW_WRAPPER_HELP_MESSAGE: {
|
||||
description: "If set, appended to the `$HOMEBREW_FORCE_BREW_WRAPPER` error message to provide " \
|
||||
"additional help or context to the user.",
|
||||
description: "No longer used.",
|
||||
replacement: "custom help in your wrapper",
|
||||
odeprecated: true,
|
||||
},
|
||||
HOMEBREW_FORCE_VENDOR_RUBY: {
|
||||
description: "If set, always use Homebrew's vendored, relocatable Ruby version even if the system version " \
|
||||
@@ -577,8 +579,10 @@ module Homebrew
|
||||
odisabled: true,
|
||||
},
|
||||
HOMEBREW_NO_FORCE_BREW_WRAPPER: {
|
||||
description: "`Deprecated:` If set, disables `$HOMEBREW_FORCE_BREW_WRAPPER` behaviour, even if set.",
|
||||
description: "No longer used.",
|
||||
boolean: :set,
|
||||
replacement: "an environment without $HOMEBREW_NO_FORCE_BREW_WRAPPER",
|
||||
odeprecated: true,
|
||||
},
|
||||
HOMEBREW_NO_GITHUB_API: {
|
||||
description: "If set, do not use the GitHub API, e.g. for searches or fetching relevant issues " \
|
||||
@@ -931,6 +935,15 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def self.check_deprecated_bash_variables
|
||||
force_brew_wrapper
|
||||
force_brew_wrapper_help_message
|
||||
no_force_brew_wrapper?
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
sig { params(env: T.any(String, Symbol), hash: T::Hash[Symbol, T.untyped]).returns(T.nilable(String)) }
|
||||
def env_value(env, hash)
|
||||
env = env.to_s
|
||||
|
||||
@@ -828,7 +828,7 @@ class Formula
|
||||
sig { params(path: Pathname).returns(T.nilable(T.any(String, Symbol))) }
|
||||
def link_overwrite_keg_name(path)
|
||||
# Don't overwrite files not created by Homebrew.
|
||||
return if path.stat.uid != HOMEBREW_ORIGINAL_BREW_FILE.stat.uid
|
||||
return if path.stat.uid != HOMEBREW_BREW_FILE.stat.uid
|
||||
|
||||
keg = Keg.for(path)
|
||||
# This keg doesn't belong to any current core/tap formula, most likely coming from a DIY install.
|
||||
|
||||
@@ -114,7 +114,7 @@ module Homebrew
|
||||
|
||||
sig { returns(Integer) }
|
||||
def owner_uid
|
||||
@owner_uid ||= T.let(HOMEBREW_ORIGINAL_BREW_FILE.stat.uid, T.nilable(Integer))
|
||||
@owner_uid ||= T.let(HOMEBREW_BREW_FILE.stat.uid, T.nilable(Integer))
|
||||
end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
|
||||
@@ -119,8 +119,8 @@ class Mktemp
|
||||
# Reference from `man 2 open`
|
||||
# > When a new file is created, it is given the group of the directory which
|
||||
# contains it.
|
||||
group_id = if HOMEBREW_ORIGINAL_BREW_FILE.grpowned?
|
||||
HOMEBREW_ORIGINAL_BREW_FILE.stat.gid
|
||||
group_id = if HOMEBREW_BREW_FILE.grpowned?
|
||||
HOMEBREW_BREW_FILE.stat.gid
|
||||
else
|
||||
Process.gid
|
||||
end
|
||||
|
||||
@@ -237,7 +237,7 @@ class Sandbox
|
||||
executable_path = Pathname.new(executable_name)
|
||||
return PATH.new(executable_path.dirname) if executable_path.absolute?
|
||||
|
||||
PATH.new(ORIGINAL_PATHS, ENV.fetch("PATH"), HOMEBREW_ORIGINAL_BREW_FILE.dirname)
|
||||
PATH.new(ORIGINAL_PATHS, ENV.fetch("PATH"), HOMEBREW_BREW_FILE.dirname)
|
||||
end
|
||||
|
||||
sig { returns(T.nilable(Pathname)) }
|
||||
@@ -541,7 +541,7 @@ class Sandbox
|
||||
|
||||
sig { void }
|
||||
def deny_write_homebrew_repository
|
||||
deny_write path: HOMEBREW_ORIGINAL_BREW_FILE
|
||||
deny_write path: HOMEBREW_BREW_FILE
|
||||
if HOMEBREW_PREFIX.to_s == HOMEBREW_REPOSITORY.to_s
|
||||
deny_write_path HOMEBREW_LIBRARY
|
||||
deny_write_path HOMEBREW_REPOSITORY/".git"
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
raise "HOMEBREW_BREW_FILE was not exported! Please call bin/brew directly!" unless ENV["HOMEBREW_BREW_FILE"]
|
||||
|
||||
# The path to the executable that should be used to run `brew`.
|
||||
# This may be HOMEBREW_ORIGINAL_BREW_FILE depending on the system configuration.
|
||||
# Favour this instead of running `brew` and expecting it to be in the `PATH`.
|
||||
# @api public
|
||||
HOMEBREW_BREW_FILE = Pathname(ENV.fetch("HOMEBREW_BREW_FILE")).freeze
|
||||
@@ -31,10 +30,6 @@ HOMEBREW_TEMP = Pathname(ENV.fetch("HOMEBREW_TEMP")).then do |tmp|
|
||||
tmp.realpath
|
||||
end.freeze
|
||||
|
||||
# Path to `bin/brew` main executable in `HOMEBREW_PREFIX`
|
||||
# Used for e.g. permissions checks.
|
||||
HOMEBREW_ORIGINAL_BREW_FILE = Pathname(ENV.fetch("HOMEBREW_ORIGINAL_BREW_FILE")).freeze
|
||||
|
||||
# Where `.git` is found
|
||||
HOMEBREW_REPOSITORY = Pathname(ENV.fetch("HOMEBREW_REPOSITORY")).freeze
|
||||
|
||||
|
||||
@@ -505,7 +505,7 @@ module Homebrew
|
||||
sig { returns(T::Array[Pathname]) }
|
||||
def self.shell_scripts
|
||||
[
|
||||
HOMEBREW_ORIGINAL_BREW_FILE.realpath,
|
||||
HOMEBREW_BREW_FILE.realpath,
|
||||
HOMEBREW_REPOSITORY/"completions/bash/brew",
|
||||
HOMEBREW_REPOSITORY/"Dockerfile",
|
||||
*HOMEBREW_REPOSITORY.glob(".devcontainer/**/*.sh"),
|
||||
|
||||
@@ -18,20 +18,44 @@ RSpec.describe Homebrew::Cmd::Exec do
|
||||
let(:env_executable) { shell_cellar/"#{env_formula_name}/1.0/bin/#{env_executable_name}" }
|
||||
let(:installable_formula_name) { "test-installable" }
|
||||
let(:installable_executable_name) { "test-installable-tool" }
|
||||
let(:brew_wrapper) { HOMEBREW_TEMP/"brew-exec-wrapper/brew" }
|
||||
let(:inline_script) { HOMEBREW_TEMP/"brew-exec-wrapper/script.sh" }
|
||||
let(:fake_brew) { HOMEBREW_TEMP/"brew-exec-test/brew" }
|
||||
let(:inline_script) { HOMEBREW_TEMP/"brew-exec-test/script.sh" }
|
||||
let(:brew_sh_env) do
|
||||
{
|
||||
"HOMEBREW_BREW_SH" => (HOMEBREW_PREFIX/"bin/brew").to_s,
|
||||
"HOMEBREW_FORCE_BREW_WRAPPER" => brew_wrapper.to_s,
|
||||
"HOMEBREW_NO_FORCE_BREW_WRAPPER" => "1",
|
||||
"HOMEBREW_TEMP" => HOMEBREW_TEMP.to_s,
|
||||
"HOMEBREW_COLOR" => nil,
|
||||
"GITHUB_ACTIONS" => nil,
|
||||
"HOMEBREW_BREW_SH" => (HOMEBREW_PREFIX/"bin/brew").to_s,
|
||||
"HOMEBREW_TEMP" => HOMEBREW_TEMP.to_s,
|
||||
"HOMEBREW_COLOR" => nil,
|
||||
"GITHUB_ACTIONS" => nil,
|
||||
}
|
||||
end
|
||||
|
||||
sig { params(args: String).returns(SystemCommand::Result) }
|
||||
def exec_command(*args)
|
||||
result = SystemCommand.run("/bin/bash", args: [
|
||||
"-c", <<~SH,
|
||||
source "$HOMEBREW_LIBRARY/Homebrew/utils/os.sh"
|
||||
source "$HOMEBREW_LIBRARY/Homebrew/utils.sh"
|
||||
source "$1"
|
||||
shift
|
||||
homebrew-exec "$@"
|
||||
SH
|
||||
"bash", HOMEBREW_LIBRARY_PATH/"cmd/exec.sh", *args
|
||||
], print_stderr: false)
|
||||
$stdout.print result.stdout
|
||||
$stderr.print result.stderr
|
||||
result
|
||||
end
|
||||
|
||||
before do
|
||||
ENV["HOMEBREW_BREW_FILE"] = fake_brew.to_s
|
||||
ENV["HOMEBREW_LIBRARY"] = HOMEBREW_LIBRARY_PATH.parent.to_s
|
||||
ENV["HOMEBREW_PREFIX"] = HOMEBREW_PREFIX.to_s
|
||||
ENV["HOMEBREW_CELLAR"] = shell_cellar.to_s
|
||||
ENV["HOMEBREW_CACHE"] = HOMEBREW_CACHE.to_s
|
||||
ENV["HOMEBREW_TEMP"] = HOMEBREW_TEMP.to_s
|
||||
ENV.delete("HOMEBREW_COLOR")
|
||||
ENV.delete("GITHUB_ACTIONS")
|
||||
(HOMEBREW_PREFIX/"bin").mkpath
|
||||
FileUtils.ln_sf HOMEBREW_LIBRARY_PATH.parent.parent/"bin/brew", HOMEBREW_PREFIX/"bin/brew"
|
||||
|
||||
db.dirname.mkpath
|
||||
@@ -62,7 +86,7 @@ RSpec.describe Homebrew::Cmd::Exec do
|
||||
linked_executable.write("#!/bin/sh\necho linked-provider\n")
|
||||
FileUtils.chmod 0755, linked_executable
|
||||
|
||||
brew_wrapper.dirname.mkpath
|
||||
fake_brew.dirname.mkpath
|
||||
inline_script.write(<<~SH)
|
||||
#!/bin/sh
|
||||
#{executable_name} "$@"
|
||||
@@ -70,7 +94,7 @@ RSpec.describe Homebrew::Cmd::Exec do
|
||||
SH
|
||||
FileUtils.chmod 0755, inline_script
|
||||
|
||||
brew_wrapper.write(<<~SH)
|
||||
fake_brew.write(<<~SH)
|
||||
#!/bin/sh
|
||||
case "$1" in
|
||||
deps)
|
||||
@@ -88,12 +112,12 @@ RSpec.describe Homebrew::Cmd::Exec do
|
||||
ln -sfn "#{shell_cellar}/#{installable_formula_name}/1.0.0" "#{HOMEBREW_PREFIX}/opt/#{installable_formula_name}"
|
||||
;;
|
||||
*)
|
||||
echo "unexpected brew wrapper call: $*" >&2
|
||||
echo "unexpected brew call: $*" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
SH
|
||||
FileUtils.chmod 0755, brew_wrapper
|
||||
FileUtils.chmod 0755, fake_brew
|
||||
end
|
||||
|
||||
after do
|
||||
@@ -104,49 +128,52 @@ RSpec.describe Homebrew::Cmd::Exec do
|
||||
FileUtils.rm_rf HOMEBREW_PREFIX/"opt/#{env_formula_name}"
|
||||
FileUtils.rm_rf HOMEBREW_PREFIX/"opt/#{installable_formula_name}"
|
||||
FileUtils.rm_f HOMEBREW_PREFIX/"bin/#{executable_name}"
|
||||
FileUtils.rm_rf brew_wrapper.dirname
|
||||
FileUtils.rm_rf fake_brew.dirname
|
||||
end
|
||||
|
||||
it "runs commands in formula environments and supports the x alias", :aggregate_failures, :integration_test do
|
||||
expect do
|
||||
expect(brew_sh("exec", executable_name, "arg", brew_sh_env)).to be_a_success
|
||||
expect(brew_sh("exec", executable_name, "arg", brew_sh_env))
|
||||
.to be_a_success
|
||||
end.to(
|
||||
output("active-version arg\n").to_stdout
|
||||
.and(output("").to_stderr),
|
||||
)
|
||||
|
||||
expect do
|
||||
expect(brew_sh("x", executable_name, brew_sh_env)).to be_a_success
|
||||
expect(brew_sh("x", executable_name, brew_sh_env))
|
||||
.to be_a_success
|
||||
end.to(
|
||||
output("active-version\n").to_stdout
|
||||
.and(output("").to_stderr),
|
||||
)
|
||||
end
|
||||
|
||||
it "runs commands with explicit formulae and installs missing providers", :aggregate_failures do
|
||||
expect do
|
||||
expect(brew_sh("exec", "--formulae=#{formula_name}, #{env_formula_name}", "--", inline_script.to_s, "arg",
|
||||
brew_sh_env)).to be_a_success
|
||||
expect(exec_command("--formulae=#{formula_name}, #{env_formula_name}", "--", inline_script.to_s, "arg"))
|
||||
.to be_a_success
|
||||
end.to(
|
||||
output("active-version arg\nenv-version arg\n").to_stdout
|
||||
.and(output("").to_stderr),
|
||||
)
|
||||
|
||||
expect do
|
||||
expect(brew_sh("exec", "--formulae=", executable_name, brew_sh_env)).to be_a_failure
|
||||
expect(exec_command("--formulae=", executable_name)).to be_a_failure
|
||||
end.to(
|
||||
output("").to_stdout
|
||||
.and(output("Error: `--formulae` requires a comma-separated formula list.\n").to_stderr),
|
||||
)
|
||||
|
||||
expect do
|
||||
expect(brew_sh("exec", "--sandbox=", executable_name, brew_sh_env)).to be_a_failure
|
||||
expect(exec_command("--sandbox=", executable_name)).to be_a_failure
|
||||
end.to(
|
||||
output("").to_stdout
|
||||
.and(output("Error: `--sandbox` requires a writable path.\n").to_stderr),
|
||||
)
|
||||
|
||||
expect do
|
||||
expect(brew_sh("exec", installable_executable_name, "arg",
|
||||
brew_sh_env)).to be_a_success
|
||||
expect(exec_command(installable_executable_name, "arg")).to be_a_success
|
||||
end.to(
|
||||
output("installable-version arg\n").to_stdout
|
||||
.and(
|
||||
|
||||
@@ -37,6 +37,7 @@ RSpec.describe "brew shellenv", type: :system do
|
||||
sig { params(shell: String, shell_args: T::Array[String]).returns(T::Hash[String, String]) }
|
||||
def shellenv_environment(shell, shell_args)
|
||||
stdout, stderr, status = Open3.capture3(
|
||||
{ "HOMEBREW_PREFIX" => nil, "HOMEBREW_CELLAR" => nil, "HOMEBREW_REPOSITORY" => nil },
|
||||
(which(shell, ORIGINAL_PATHS) || skip("#{shell} is not installed")).to_s, *shell_args,
|
||||
"#{shellenv(shell)}\n/usr/bin/env"
|
||||
)
|
||||
@@ -92,6 +93,20 @@ RSpec.describe "brew shellenv", type: :system do
|
||||
.and end_with("/custom path:/usr/bin:/bin")
|
||||
end
|
||||
|
||||
it "ignores customised path_helper configuration in #{shell}" do
|
||||
ENV["HOMEBREW_MACOS"] = "1"
|
||||
ENV["HOMEBREW_MACOS_VERSION_NUMERIC"] = "140000"
|
||||
ENV["PATH_HELPER_ROOT"] = HOMEBREW_PREFIX.to_s
|
||||
ENV["PATH"] = "/usr/bin:/bin:/wrapper/bin"
|
||||
expected_path = shellenv_environment(shell, shell_args).fetch("PATH")
|
||||
(HOMEBREW_PREFIX/"etc/paths.d").mkpath
|
||||
(HOMEBREW_PREFIX/"etc/paths").write("/wrapper/bin\n#{HOMEBREW_PREFIX}/bin\n#{HOMEBREW_PREFIX}/sbin\n")
|
||||
(HOMEBREW_PREFIX/"etc/paths.d/wrapper").write("/another/wrapper/bin\n")
|
||||
|
||||
expect(shellenv_environment(shell, shell_args).fetch("PATH"))
|
||||
.to eq(expected_path)
|
||||
end
|
||||
|
||||
it "preserves existing FPATH entries and adds completions for #{shell}" do
|
||||
expect(shellenv_environment(shell, shell_args).fetch("FPATH").split(":"))
|
||||
.to eq([("#{HOMEBREW_PREFIX}/share/zsh/site-functions" if shell == "zsh"), "/custom/functions"].compact)
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "diagnostic"
|
||||
|
||||
RSpec.describe Homebrew::Diagnostic::Checks do
|
||||
describe "#check_brew_path" do
|
||||
sig { returns(Homebrew::Diagnostic::Checks) }
|
||||
subject(:checks) { described_class.new }
|
||||
|
||||
sig { returns(Pathname) }
|
||||
def brew
|
||||
HOMEBREW_PREFIX/"bin/brew"
|
||||
end
|
||||
|
||||
sig { returns(Pathname) }
|
||||
def other_brew
|
||||
HOMEBREW_TEMP/"wrapper/bin/brew"
|
||||
end
|
||||
|
||||
before do
|
||||
brew.dirname.mkpath
|
||||
brew.write("#!/bin/sh\n")
|
||||
brew.chmod 0755
|
||||
other_brew.dirname.mkpath
|
||||
other_brew.write("#!/bin/sh\nexit 1\n")
|
||||
other_brew.chmod 0755
|
||||
stub_const("HOMEBREW_BREW_FILE", brew)
|
||||
stub_const("ORIGINAL_PATHS", [other_brew.dirname, brew.dirname])
|
||||
end
|
||||
|
||||
it "warns when another brew shadows this installation" do
|
||||
expect(checks.check_brew_path&.to_s)
|
||||
.to include("Another `brew` shadows this Homebrew installation in your PATH:",
|
||||
other_brew.to_s, "#{HOMEBREW_PREFIX}/bin")
|
||||
end
|
||||
|
||||
it "checks the original PATH, not Homebrew's modified PATH" do
|
||||
ENV["PATH"] = brew.dirname.to_s
|
||||
|
||||
expect(checks.check_brew_path).not_to be_nil
|
||||
end
|
||||
|
||||
it "uses the same PATH guidance as the missing-bin warning" do
|
||||
stub_const("ORIGINAL_PATHS", [other_brew.dirname])
|
||||
|
||||
expect(checks.check_brew_path&.remediation&.to_h)
|
||||
.to eq(checks.check_user_path_2&.remediation&.to_h)
|
||||
end
|
||||
|
||||
it "does not warn when this installation takes precedence" do
|
||||
stub_const("ORIGINAL_PATHS", [brew.dirname, other_brew.dirname])
|
||||
|
||||
expect(checks.check_brew_path).to be_nil
|
||||
end
|
||||
|
||||
it "does not warn about symlinks to the same brew" do
|
||||
other_brew.unlink
|
||||
FileUtils.ln_s brew, other_brew
|
||||
|
||||
expect(checks.check_brew_path).to be_nil
|
||||
end
|
||||
|
||||
it "ignores non-executable files" do
|
||||
other_brew.chmod 0644
|
||||
|
||||
expect(checks.check_brew_path).to be_nil
|
||||
end
|
||||
|
||||
it "ignores directories named brew" do
|
||||
other_brew.unlink
|
||||
other_brew.mkpath
|
||||
|
||||
expect(checks.check_brew_path).to be_nil
|
||||
end
|
||||
|
||||
it "does not duplicate the missing PATH warning" do
|
||||
stub_const("ORIGINAL_PATHS", [])
|
||||
|
||||
expect(checks.check_brew_path).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -70,6 +70,63 @@ RSpec.describe Homebrew::EnvConfig do
|
||||
end
|
||||
end
|
||||
|
||||
describe ".check_deprecated_bash_variables" do
|
||||
before do
|
||||
ENV.delete("HOMEBREW_FORCE_BREW_WRAPPER")
|
||||
ENV.delete("HOMEBREW_FORCE_BREW_WRAPPER_HELP_MESSAGE")
|
||||
ENV.delete("HOMEBREW_NO_FORCE_BREW_WRAPPER")
|
||||
end
|
||||
|
||||
test_each(%w[
|
||||
HOMEBREW_FORCE_BREW_WRAPPER
|
||||
HOMEBREW_FORCE_BREW_WRAPPER_HELP_MESSAGE
|
||||
HOMEBREW_NO_FORCE_BREW_WRAPPER
|
||||
]) do |variable|
|
||||
it "deprecates the obsolete Bash setting #{variable}" do
|
||||
ENV[variable] = "1"
|
||||
|
||||
expect { env_config.check_deprecated_bash_variables }
|
||||
.to raise_error(MethodDeprecatedError, /#{variable}.*deprecated/)
|
||||
end
|
||||
end
|
||||
|
||||
it "leaves Ruby settings to their accessors" do
|
||||
ENV["HOMEBREW_BAT_THEME"] = "GitHub"
|
||||
ENV["HOMEBREW_PRY"] = "1"
|
||||
ENV["HOMEBREW_REQUIRE_TAP_TRUST"] = "1"
|
||||
|
||||
expect { env_config.check_deprecated_bash_variables }.not_to raise_error
|
||||
end
|
||||
|
||||
it "ignores blank values" do
|
||||
ENV["HOMEBREW_FORCE_BREW_WRAPPER"] = ""
|
||||
|
||||
expect { env_config.check_deprecated_bash_variables }.not_to raise_error
|
||||
end
|
||||
|
||||
it "warns once per variable even when checked or read again" do
|
||||
ENV["HOMEBREW_FORCE_BREW_WRAPPER"] = "/wrapper/brew"
|
||||
ENV["HOMEBREW_NO_FORCE_BREW_WRAPPER"] = "0"
|
||||
ENV.delete("HOMEBREW_TESTS")
|
||||
ENV.delete("HOMEBREW_DEVELOPER")
|
||||
ENV.delete("GITHUB_ACTIONS")
|
||||
Homebrew.raise_deprecation_exceptions = false
|
||||
allow(Homebrew).to receive(:auditing?).and_return(false)
|
||||
stub_const("Homebrew::EnvConfig::WARNED_DEPRECATED_ENVS", Set.new)
|
||||
|
||||
expect do
|
||||
env_config.check_deprecated_bash_variables
|
||||
env_config.check_deprecated_bash_variables
|
||||
env_config.force_brew_wrapper
|
||||
env_config.no_force_brew_wrapper?
|
||||
end.to output(
|
||||
"Warning: Calling HOMEBREW_FORCE_BREW_WRAPPER is deprecated! Use your wrapper directly instead.\n" \
|
||||
"Warning: Calling HOMEBREW_NO_FORCE_BREW_WRAPPER is deprecated! " \
|
||||
"Use an environment without $HOMEBREW_NO_FORCE_BREW_WRAPPER instead.\n",
|
||||
).to_stderr
|
||||
end
|
||||
end
|
||||
|
||||
describe ".allowed_taps" do
|
||||
it "deprecates the tap allowlist" do
|
||||
ENV["HOMEBREW_ALLOWED_TAPS"] = "user/repo"
|
||||
@@ -97,6 +154,33 @@ RSpec.describe Homebrew::EnvConfig do
|
||||
end
|
||||
end
|
||||
|
||||
describe ".force_brew_wrapper" do
|
||||
it "deprecates requiring a wrapper" do
|
||||
ENV["HOMEBREW_FORCE_BREW_WRAPPER"] = "/wrapper/brew"
|
||||
|
||||
expect { env_config.force_brew_wrapper }
|
||||
.to raise_error(MethodDeprecatedError, /HOMEBREW_FORCE_BREW_WRAPPER.*deprecated/)
|
||||
end
|
||||
end
|
||||
|
||||
describe ".force_brew_wrapper_help_message" do
|
||||
it "deprecates custom wrapper help" do
|
||||
ENV["HOMEBREW_FORCE_BREW_WRAPPER_HELP_MESSAGE"] = "Contact support."
|
||||
|
||||
expect { env_config.force_brew_wrapper_help_message }
|
||||
.to raise_error(MethodDeprecatedError, /HOMEBREW_FORCE_BREW_WRAPPER_HELP_MESSAGE.*deprecated/)
|
||||
end
|
||||
end
|
||||
|
||||
describe ".no_force_brew_wrapper?" do
|
||||
it "deprecates the wrapper opt-out" do
|
||||
ENV["HOMEBREW_NO_FORCE_BREW_WRAPPER"] = "1"
|
||||
|
||||
expect { env_config.no_force_brew_wrapper? }
|
||||
.to raise_error(MethodDeprecatedError, /HOMEBREW_NO_FORCE_BREW_WRAPPER.*deprecated/)
|
||||
end
|
||||
end
|
||||
|
||||
describe ".arch" do
|
||||
it "deprecates overriding the compiler architecture" do
|
||||
ENV["HOMEBREW_ARCH"] = "haswell"
|
||||
|
||||
@@ -289,7 +289,7 @@ RSpec.describe Sandbox do
|
||||
before do
|
||||
sandbox_class.test_executable_name = executable_name
|
||||
sandbox_class.unsuitable_executables = []
|
||||
stub_const("HOMEBREW_ORIGINAL_BREW_FILE", homebrew_bin/"brew")
|
||||
stub_const("HOMEBREW_BREW_FILE", homebrew_bin/"brew")
|
||||
end
|
||||
|
||||
it "uses the first suitable executable candidate" do
|
||||
|
||||
@@ -142,7 +142,7 @@ module Test
|
||||
test_prefix_library.mkpath
|
||||
FileUtils.ln_sf HOMEBREW_LIBRARY_PATH, test_prefix_library/"Homebrew"
|
||||
# `cp` would keep the touched file's non-executable mode.
|
||||
FileUtils.install HOMEBREW_ORIGINAL_BREW_FILE, HOMEBREW_PREFIX/"bin/brew", mode: 0755
|
||||
FileUtils.install HOMEBREW_BREW_FILE, HOMEBREW_PREFIX/"bin/brew", mode: 0755
|
||||
(HOMEBREW_PREFIX/"bin/brew").to_s
|
||||
end
|
||||
|
||||
|
||||
@@ -14,7 +14,15 @@ RSpec.describe Test::Helper::IntegrationTest do
|
||||
(HOMEBREW_PREFIX/"bin").mkpath
|
||||
example.run
|
||||
ensure
|
||||
FileUtils.rm_rf HOMEBREW_PREFIX/"bin"
|
||||
FileUtils.rm_rf [HOMEBREW_PREFIX/"bin", HOMEBREW_PREFIX/"Library/Homebrew"]
|
||||
end
|
||||
|
||||
it "copies an executable Homebrew entry point into the test prefix" do
|
||||
FileUtils.touch HOMEBREW_PREFIX/"bin/brew"
|
||||
brew_sh_path = Pathname(helper.test_prefix_brew_sh)
|
||||
|
||||
expect([brew_sh_path.symlink?, brew_sh_path.executable?, brew_sh_path.read])
|
||||
.to eq([false, true, HOMEBREW_BREW_FILE.read])
|
||||
end
|
||||
|
||||
it "disables Sorbet checking in Ruby integration commands" do
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
raise "HOMEBREW_BREW_FILE was not exported! Please call bin/brew directly!" unless ENV["HOMEBREW_BREW_FILE"]
|
||||
|
||||
HOMEBREW_ORIGINAL_BREW_FILE = Pathname.new(ENV.fetch("HOMEBREW_ORIGINAL_BREW_FILE")).freeze
|
||||
HOMEBREW_BREW_FILE = Pathname.new(ENV.fetch("HOMEBREW_BREW_FILE")).freeze
|
||||
|
||||
TEST_TMPDIR = ENV.fetch("HOMEBREW_TEST_TMPDIR") do |k|
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe "brew wrapper", type: :system do
|
||||
sig { returns(SystemCommand::Result) }
|
||||
subject(:result) { SystemCommand.run(HOMEBREW_BREW_FILE, args: ["commands", "--quiet"]) }
|
||||
|
||||
before do
|
||||
ENV["HOMEBREW_FORCE_BREW_WRAPPER"] = "/wrapper/brew"
|
||||
ENV["HOMEBREW_BREW_WRAPPER"] = "/wrapper/brew"
|
||||
ENV.delete("HOMEBREW_NO_FORCE_BREW_WRAPPER")
|
||||
ENV["HOMEBREW_NO_INSTALL_FROM_API"] = "1"
|
||||
ENV.delete("HOMEBREW_FORCE_BREW_WRAPPER_HELP_MESSAGE")
|
||||
ENV.delete("HOMEBREW_DEVELOPER")
|
||||
ENV["HOMEBREW_NO_COLOR"] = "1"
|
||||
end
|
||||
|
||||
it "warns about obsolete wrapper configuration" do
|
||||
expect([result.status.exitstatus, result.stderr]).to eq([
|
||||
0,
|
||||
"Warning: Calling HOMEBREW_FORCE_BREW_WRAPPER is deprecated! " \
|
||||
"Use your wrapper directly instead.\n",
|
||||
])
|
||||
end
|
||||
|
||||
test_each([nil, "0"]) do |opt_out|
|
||||
it "keeps the Homebrew executable through a wrapper with opt-out #{opt_out.inspect}" do
|
||||
wrapper = HOMEBREW_TEMP/"brew-wrapper"
|
||||
wrapper.write(<<~SH)
|
||||
#!/bin/bash
|
||||
export HOMEBREW_BREW_WRAPPER="$0"
|
||||
exec "#{HOMEBREW_BREW_FILE}" "$@"
|
||||
SH
|
||||
FileUtils.chmod 0755, wrapper
|
||||
ENV["HOMEBREW_FORCE_BREW_WRAPPER"] = wrapper.to_s
|
||||
ENV["HOMEBREW_NO_FORCE_BREW_WRAPPER"] = opt_out
|
||||
result = SystemCommand.run(wrapper, args: ["ruby", "-e", "puts HOMEBREW_BREW_FILE"])
|
||||
|
||||
expect([result.status.exitstatus, result.stdout]).to eq([0, "#{HOMEBREW_BREW_FILE}\n"])
|
||||
end
|
||||
end
|
||||
|
||||
it "turns deprecations into errors for developers" do
|
||||
ENV["HOMEBREW_DEVELOPER"] = "1"
|
||||
|
||||
expect([result.status.exitstatus, result.stderr.lines.first]).to eq([
|
||||
1,
|
||||
"Error: Calling HOMEBREW_FORCE_BREW_WRAPPER is deprecated! Use your wrapper directly instead.\n",
|
||||
])
|
||||
end
|
||||
|
||||
test_each([nil, "/another/brew"]) do |wrapper|
|
||||
it "does not require a matching wrapper when the marker is #{wrapper.inspect}" do
|
||||
ENV["HOMEBREW_BREW_WRAPPER"] = wrapper
|
||||
|
||||
expect(result).to be_a_success
|
||||
end
|
||||
end
|
||||
|
||||
it "warns about obsolete custom help without printing it" do
|
||||
ENV.delete("HOMEBREW_FORCE_BREW_WRAPPER")
|
||||
ENV["HOMEBREW_FORCE_BREW_WRAPPER_HELP_MESSAGE"] = "-n"
|
||||
|
||||
expect([result.status.exitstatus, result.stderr]).to eq([
|
||||
0,
|
||||
"Warning: Calling HOMEBREW_FORCE_BREW_WRAPPER_HELP_MESSAGE is deprecated! " \
|
||||
"Use custom help in your wrapper instead.\n",
|
||||
])
|
||||
end
|
||||
|
||||
it "warns about the obsolete opt-out without requiring a wrapper" do
|
||||
ENV.delete("HOMEBREW_FORCE_BREW_WRAPPER")
|
||||
ENV["HOMEBREW_NO_FORCE_BREW_WRAPPER"] = "0"
|
||||
|
||||
expect([result.status.exitstatus, result.stderr]).to eq([
|
||||
0,
|
||||
"Warning: Calling HOMEBREW_NO_FORCE_BREW_WRAPPER is deprecated! " \
|
||||
"Use an environment without $HOMEBREW_NO_FORCE_BREW_WRAPPER instead.\n",
|
||||
])
|
||||
end
|
||||
|
||||
it "does nothing when no wrapper is required" do
|
||||
ENV.delete("HOMEBREW_FORCE_BREW_WRAPPER")
|
||||
|
||||
expect([result.status.exitstatus, result.stderr]).to eq([0, ""])
|
||||
end
|
||||
|
||||
it "does not check deprecated Ruby settings that the command does not read" do
|
||||
ENV.delete("HOMEBREW_FORCE_BREW_WRAPPER")
|
||||
ENV["HOMEBREW_BAT_THEME"] = "GitHub"
|
||||
|
||||
expect([result.status.exitstatus, result.stderr]).to eq([0, ""])
|
||||
end
|
||||
|
||||
it "does not check deprecated settings when displaying help" do
|
||||
ENV["HOMEBREW_DEVELOPER"] = "1"
|
||||
result = SystemCommand.run(HOMEBREW_BREW_FILE, args: ["commands", "--help"])
|
||||
|
||||
expect([result.status.exitstatus, result.stderr]).to eq([0, ""])
|
||||
end
|
||||
|
||||
it "does not check deprecated settings when an external command displays its own help" do
|
||||
command = HOMEBREW_TEMP/"brew-wrapper-test"
|
||||
command.write(<<~SH)
|
||||
#!/bin/bash
|
||||
printf '%s\\n' "$@"
|
||||
SH
|
||||
command.chmod(0755)
|
||||
ENV["HOMEBREW_PATH"] = PATH.new(ENV.fetch("PATH")).prepend(HOMEBREW_TEMP).to_s
|
||||
ENV["HOMEBREW_DEVELOPER"] = "1"
|
||||
result = SystemCommand.run(HOMEBREW_BREW_FILE, args: ["help", "wrapper-test"])
|
||||
|
||||
expect([result.status.exitstatus, result.stdout, result.stderr]).to eq([0, "--help\n", ""])
|
||||
end
|
||||
|
||||
it "reports unknown commands before checking deprecated settings" do
|
||||
ENV["HOMEBREW_DEVELOPER"] = "1"
|
||||
result = SystemCommand.run(HOMEBREW_BREW_FILE, args: ["wrapper-test-unknown"])
|
||||
|
||||
expect([result.status.exitstatus, result.stderr.lines.grep(/Error:|Warning:/)]).to eq([
|
||||
1,
|
||||
["Error: Invalid usage: Unknown command: brew wrapper-test-unknown\n"],
|
||||
])
|
||||
end
|
||||
|
||||
it "does not warn or enforce wrapper settings in shell-only commands" do
|
||||
ENV.delete("HOMEBREW_BREW_WRAPPER")
|
||||
result = SystemCommand.run(HOMEBREW_BREW_FILE, args: ["--version"])
|
||||
|
||||
expect([result.status.exitstatus, result.stderr]).to eq([0, ""])
|
||||
end
|
||||
end
|
||||
@@ -1,36 +0,0 @@
|
||||
#!/usr/bin/env ruby
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
pid = ARGV[0]&.to_i
|
||||
raise "Missing `pid` argument!" unless pid
|
||||
|
||||
require "fiddle"
|
||||
|
||||
# Canonically, this is a part of libproc.dylib. libproc is however just a symlink to libSystem
|
||||
# and some security tools seem to not support aliases from the dyld shared cache and incorrectly flag this.
|
||||
libproc = Fiddle.dlopen("/usr/lib/libSystem.B.dylib")
|
||||
|
||||
libproc_proc_pidpath_function = Fiddle::Function.new(
|
||||
libproc["proc_pidpath"],
|
||||
[Fiddle::TYPE_INT, Fiddle::TYPE_VOIDP, Fiddle::TYPE_UINT32_T],
|
||||
Fiddle::TYPE_INT,
|
||||
)
|
||||
|
||||
# We have to allocate a (char) buffer of exactly `PROC_PIDPATHINFO_MAXSIZE` to use `proc_pidpath`
|
||||
# From `include/sys/proc_info.h`, PROC_PIDPATHINFO_MAXSIZE = 4 * MAXPATHLEN
|
||||
# From `include/sys/param.h`, MAXPATHLEN = PATH_MAX
|
||||
# From `include/sys/syslimits.h`, PATH_MAX = 1024
|
||||
# https://github.com/apple-oss-distributions/xnu/blob/e3723e1f17661b24996789d8afc084c0c3303b26/libsyscall/wrappers/libproc/libproc.c#L268-L275
|
||||
buffer_size = 4 * 1024 # PROC_PIDPATHINFO_MAXSIZE = 4 * MAXPATHLEN
|
||||
buffer = "\0" * buffer_size
|
||||
pointer_to_buffer = Fiddle::Pointer.to_ptr(buffer)
|
||||
|
||||
# `proc_pidpath` returns a positive value on success. See:
|
||||
# https://stackoverflow.com/a/8149198
|
||||
# https://github.com/chromium/chromium/blob/86df41504a235f9369f6f53887da12a718a19db4/base/process/process_handle_mac.cc#L37-L44
|
||||
# https://github.com/apple-oss-distributions/xnu/blob/e3723e1f17661b24996789d8afc084c0c3303b26/libsyscall/wrappers/libproc/libproc.c#L263-L283
|
||||
return_value = libproc_proc_pidpath_function.call(pid, pointer_to_buffer, buffer_size)
|
||||
raise "Call to `proc_pidpath` failed! `proc_pidpath` returned #{return_value}." unless return_value.positive?
|
||||
|
||||
puts pointer_to_buffer.to_s.strip
|
||||
@@ -1,82 +0,0 @@
|
||||
# `brew` wrapper handling helpers.
|
||||
|
||||
# HOMEBREW_LIBRARY, HOMEBREW_BREW_FILE, HOMEBREW_ORIGINAL_BREW_FILE, HOMEBREW_PREFIX are set by bin/brew.
|
||||
# HOMEBREW_FORCE_BREW_WRAPPER is set by the user environment.
|
||||
# shellcheck disable=SC2154
|
||||
odie-with-wrapper-message() {
|
||||
source "${HOMEBREW_LIBRARY}/Homebrew/utils.sh"
|
||||
|
||||
local CUSTOM_MESSAGE="${1}"
|
||||
local HOMEBREW_FORCE_BREW_WRAPPER_WITHOUT_BREW="${HOMEBREW_FORCE_BREW_WRAPPER%/brew}"
|
||||
|
||||
onoe <<EOS
|
||||
conflicting Homebrew wrapper configuration!
|
||||
HOMEBREW_FORCE_BREW_WRAPPER was set to ${HOMEBREW_FORCE_BREW_WRAPPER}
|
||||
${CUSTOM_MESSAGE}
|
||||
|
||||
$(bold "Ensure you run ${HOMEBREW_FORCE_BREW_WRAPPER} directly (not ${HOMEBREW_ORIGINAL_BREW_FILE})")!
|
||||
|
||||
Manually setting your PATH can interfere with Homebrew wrappers.
|
||||
Ensure your shell configuration contains:
|
||||
eval "\$(${HOMEBREW_BREW_FILE} shellenv)"
|
||||
or that ${HOMEBREW_FORCE_BREW_WRAPPER_WITHOUT_BREW} comes before ${HOMEBREW_PREFIX}/bin in your PATH:
|
||||
export PATH="${HOMEBREW_FORCE_BREW_WRAPPER_WITHOUT_BREW}:${HOMEBREW_PREFIX}/bin:\$PATH"
|
||||
EOS
|
||||
|
||||
if [[ -n "${HOMEBREW_FORCE_BREW_WRAPPER_HELP_MESSAGE:-}" ]]
|
||||
then
|
||||
echo "${HOMEBREW_FORCE_BREW_WRAPPER_HELP_MESSAGE}" >&2
|
||||
fi
|
||||
|
||||
exit 1
|
||||
}
|
||||
|
||||
check-brew-wrapper() {
|
||||
[[ -z "${HOMEBREW_FORCE_BREW_WRAPPER:-}" ]] && return
|
||||
[[ -z "${HOMEBREW_DISABLE_NO_FORCE_BREW_WRAPPER:-}" && -n "${HOMEBREW_NO_FORCE_BREW_WRAPPER:-}" ]] && return
|
||||
|
||||
# Require HOMEBREW_BREW_WRAPPER to be set if HOMEBREW_FORCE_BREW_WRAPPER is set
|
||||
# (and HOMEBREW_NO_FORCE_BREW_WRAPPER and HOMEBREW_DISABLE_NO_FORCE_BREW_WRAPPER are not set).
|
||||
if [[ -z "${HOMEBREW_DISABLE_NO_FORCE_BREW_WRAPPER:-}" && -z "${HOMEBREW_NO_FORCE_BREW_WRAPPER:-}" ]]
|
||||
then
|
||||
if [[ -z "${HOMEBREW_BREW_WRAPPER:-}" ]]
|
||||
then
|
||||
odie-with-wrapper-message "but HOMEBREW_BREW_WRAPPER was unset."
|
||||
elif [[ "${HOMEBREW_FORCE_BREW_WRAPPER}" != "${HOMEBREW_BREW_WRAPPER}" ]]
|
||||
then
|
||||
odie-with-wrapper-message "but HOMEBREW_BREW_WRAPPER was set to ${HOMEBREW_BREW_WRAPPER}"
|
||||
fi
|
||||
|
||||
return
|
||||
fi
|
||||
|
||||
# If HOMEBREW_FORCE_BREW_WRAPPER and HOMEBREW_DISABLE_NO_FORCE_BREW_WRAPPER are set,
|
||||
# verify that the path to our parent process is the same as the value of HOMEBREW_FORCE_BREW_WRAPPER.
|
||||
# We can't check this for `brew vendor-install` as this would cause an infinite loop on macOS.
|
||||
if [[ -n "${HOMEBREW_DISABLE_NO_FORCE_BREW_WRAPPER:-}" && "$1" != "vendor-install" ]]
|
||||
then
|
||||
local HOMEBREW_BREW_CALLER HOMEBREW_BREW_CALLER_CHECK_EXIT_CODE
|
||||
|
||||
if [[ -n "${HOMEBREW_MACOS:-}" ]]
|
||||
then
|
||||
source "${HOMEBREW_LIBRARY}/Homebrew/utils/ruby.sh"
|
||||
setup-ruby-path
|
||||
HOMEBREW_BREW_CALLER="$("${HOMEBREW_RUBY_PATH}" "${HOMEBREW_LIBRARY}/Homebrew/utils/pid_path.rb" "${PPID}")"
|
||||
else
|
||||
HOMEBREW_BREW_CALLER="$(readlink -f "/proc/${PPID}/exe")"
|
||||
fi
|
||||
HOMEBREW_BREW_CALLER_CHECK_EXIT_CODE="$?"
|
||||
|
||||
if ((HOMEBREW_BREW_CALLER_CHECK_EXIT_CODE != 0))
|
||||
then
|
||||
source "${HOMEBREW_LIBRARY}/Homebrew/utils.sh"
|
||||
# Error message already printed above when populating `HOMEBREW_BREW_CALLER`.
|
||||
odie "failed to check the path to the parent process!"
|
||||
fi
|
||||
|
||||
if [[ "${HOMEBREW_BREW_CALLER:-}" != "${HOMEBREW_FORCE_BREW_WRAPPER}" ]]
|
||||
then
|
||||
odie-with-wrapper-message "but \`brew\` was invoked by ${HOMEBREW_BREW_CALLER}."
|
||||
fi
|
||||
fi
|
||||
}
|
||||
@@ -120,7 +120,6 @@ BIN_BREW_EXPORTED_VARS=(
|
||||
HOMEBREW_REPOSITORY
|
||||
HOMEBREW_LIBRARY
|
||||
HOMEBREW_USER_CONFIG_HOME
|
||||
HOMEBREW_ORIGINAL_BREW_FILE
|
||||
)
|
||||
printf -v BIN_BREW_EXPORTED_VARS_REGEX '%s|' "${BIN_BREW_EXPORTED_VARS[@]}"
|
||||
BIN_BREW_EXPORTED_VARS_REGEX="^(${BIN_BREW_EXPORTED_VARS_REGEX%|})(=|$)"
|
||||
@@ -150,9 +149,6 @@ export_homebrew_env_file() {
|
||||
done <"${env_file}"
|
||||
}
|
||||
|
||||
# We only want to be able to set this in `brew.env` files.
|
||||
unset HOMEBREW_DISABLE_NO_FORCE_BREW_WRAPPER
|
||||
|
||||
# First, load the system-wide configuration.
|
||||
export_homebrew_env_file "/etc/homebrew/brew.env"
|
||||
|
||||
@@ -184,13 +180,6 @@ then
|
||||
export_homebrew_env_file "/etc/homebrew/brew.env"
|
||||
fi
|
||||
|
||||
# Use HOMEBREW_FORCE_BREW_WRAPPER if set.
|
||||
export HOMEBREW_ORIGINAL_BREW_FILE="${HOMEBREW_BREW_FILE}"
|
||||
if [[ -n "${HOMEBREW_FORCE_BREW_WRAPPER:-}" ]]
|
||||
then
|
||||
HOMEBREW_BREW_FILE="${HOMEBREW_FORCE_BREW_WRAPPER}"
|
||||
fi
|
||||
|
||||
# Record which HOMEBREW_* variables the user set (including via brew.env
|
||||
# above) before brew exports more itself, e.g. HOMEBREW_EDITOR from
|
||||
# EDITOR/VISUAL below or HOMEBREW_UPDATE_TO_TAG in cmd/update.sh, so
|
||||
|
||||
@@ -210,14 +210,24 @@ When `odeprecated: true`, the flag is hidden from `--help` and completions and p
|
||||
|
||||
### Environment variables
|
||||
|
||||
Environment variables follow the same four-stage lifecycle. Include migration logic to copy the old value during the transition:
|
||||
Environment variables follow the same four-stage lifecycle.
|
||||
Define deprecations in `Homebrew::EnvConfig::ENVS` in `Library/Homebrew/env_config.rb`:
|
||||
|
||||
```ruby
|
||||
if (old_value = ENV["HOMEBREW_OLD_VAR"].presence)
|
||||
opoo "`HOMEBREW_OLD_VAR` is deprecated. Use `HOMEBREW_NEW_VAR` instead."
|
||||
# odeprecated "HOMEBREW_OLD_VAR", "HOMEBREW_NEW_VAR"
|
||||
ENV["HOMEBREW_NEW_VAR"] = old_value
|
||||
end
|
||||
{
|
||||
HOMEBREW_OLD_VAR: {
|
||||
description: "Use this value for the old setting.",
|
||||
replacement: :HOMEBREW_NEW_VAR,
|
||||
# odeprecated: true,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
The `# odeprecated` comment is then uncommented, changed to `odisabled` and finally removed following the standard lifecycle.
|
||||
The `# odeprecated: true` comment is then uncommented, changed to `odisabled: true` and finally removed with the variable definition following the standard lifecycle.
|
||||
A symbol `replacement:` copies the old value to the replacement variable if that variable is unset; a string provides migration guidance without copying the value.
|
||||
|
||||
Ruby accessors report deprecations when variables are read.
|
||||
For deprecated variables previously consumed only by Bash, add their accessors to `Homebrew::EnvConfig.check_deprecated_bash_variables` so Ruby commands still report their deprecations.
|
||||
This check runs before a recognised command is executed.
|
||||
Each variable's warning is printed at most once per Ruby process.
|
||||
Help and unknown commands do not run this check, and shell-only commands do not load Ruby for it.
|
||||
@@ -4774,16 +4774,6 @@ command execution (e.g. `$(cat file)`).
|
||||
: If set, always use a Homebrew-installed `git`(1) rather than the system
|
||||
version. Automatically set if the system version of `git` is too old.
|
||||
|
||||
`HOMEBREW_FORCE_BREW_WRAPPER`
|
||||
|
||||
: If set, require `brew` to be invoked by the value of
|
||||
`$HOMEBREW_FORCE_BREW_WRAPPER` for non-trivial `brew` commands.
|
||||
|
||||
`HOMEBREW_FORCE_BREW_WRAPPER_HELP_MESSAGE`
|
||||
|
||||
: If set, appended to the `$HOMEBREW_FORCE_BREW_WRAPPER` error message to
|
||||
provide additional help or context to the user.
|
||||
|
||||
`HOMEBREW_FORCE_VENDOR_RUBY`
|
||||
|
||||
: If set, always use Homebrew's vendored, relocatable Ruby version even if the
|
||||
@@ -4941,11 +4931,6 @@ command execution (e.g. `$(cat file)`).
|
||||
: If set, do not print any hints about changing Homebrew's behaviour with
|
||||
environment variables.
|
||||
|
||||
`HOMEBREW_NO_FORCE_BREW_WRAPPER`
|
||||
|
||||
: `Deprecated:` If set, disables `$HOMEBREW_FORCE_BREW_WRAPPER` behaviour, even
|
||||
if set.
|
||||
|
||||
`HOMEBREW_NO_GITHUB_API`
|
||||
|
||||
: If set, do not use the GitHub API, e.g. for searches or fetching relevant
|
||||
|
||||
@@ -92,10 +92,16 @@ Tier 3 configurations include:
|
||||
- Systems that build official packages from source despite available bottles
|
||||
- Homebrew installed outside the default prefix (e.g. `/opt/homebrew`, `/usr/local` or `/home/linuxbrew/.linuxbrew` used on mismatched architectures)
|
||||
- Homebrew installations managed by Nix (e.g. nix-darwin or nix-homebrew)
|
||||
- Homebrew invoked through a third-party wrapper
|
||||
- Installing formulae using `--HEAD`
|
||||
- Installing deprecated or disabled formulae
|
||||
- Intel x86_64 systems running macOS
|
||||
|
||||
If you are using a Homebrew wrapper, get support from and file issues with that wrapper instead of Homebrew unless the same problem is reproducible when running Homebrew directly.
|
||||
Homebrew's internal `brew` commands invoke Homebrew directly, not the wrapper.
|
||||
The legacy `HOMEBREW_FORCE_BREW_WRAPPER`, `HOMEBREW_FORCE_BREW_WRAPPER_HELP_MESSAGE` and `HOMEBREW_NO_FORCE_BREW_WRAPPER` settings are ignored and produce deprecation warnings in Ruby commands.
|
||||
`brew doctor` warns if another `brew` executable takes precedence over the current installation in your `PATH`.
|
||||
|
||||
## Unsupported
|
||||
|
||||
An unsupported configuration is one in which:
|
||||
@@ -121,8 +127,6 @@ While Homebrew may assist third-party maintainers in resolving issues related to
|
||||
|
||||
Bugs that occur only when using third-party formulae or casks may be closed without investigation.
|
||||
|
||||
If you are using a Homebrew wrapper, get support from and file issues with that wrapper instead of Homebrew unless the same problem is reproducible when running Homebrew directly.
|
||||
|
||||
## Future macOS support
|
||||
|
||||
macOS Tahoe 26 is the final version of macOS to run on Intel hardware. In alignment with this change, Homebrew has stopped building new bottles for Intel systems, and will remove the ability to run Homebrew on Intel systems in or after September 2027.
|
||||
|
||||
@@ -3073,12 +3073,6 @@ If set, always use a Homebrew\-installed \fBcurl\fP(1) rather than the system ve
|
||||
\fBHOMEBREW_FORCE_BREWED_GIT\fP
|
||||
If set, always use a Homebrew\-installed \fBgit\fP(1) rather than the system version\. Automatically set if the system version of \fBgit\fP is too old\.
|
||||
.TP
|
||||
\fBHOMEBREW_FORCE_BREW_WRAPPER\fP
|
||||
If set, require \fBbrew\fP to be invoked by the value of \fB$HOMEBREW_FORCE_BREW_WRAPPER\fP for non\-trivial \fBbrew\fP commands\.
|
||||
.TP
|
||||
\fBHOMEBREW_FORCE_BREW_WRAPPER_HELP_MESSAGE\fP
|
||||
If set, appended to the \fB$HOMEBREW_FORCE_BREW_WRAPPER\fP error message to provide additional help or context to the user\.
|
||||
.TP
|
||||
\fBHOMEBREW_FORCE_VENDOR_RUBY\fP
|
||||
If set, always use Homebrew\[u2019]s vendored, relocatable Ruby version even if the system version of Ruby is new enough\.
|
||||
.TP
|
||||
@@ -3194,9 +3188,6 @@ If set, do not print \fB$HOMEBREW_INSTALL_BADGE\fP on a successful build\.
|
||||
\fBHOMEBREW_NO_ENV_HINTS\fP
|
||||
If set, do not print any hints about changing Homebrew\[u2019]s behaviour with environment variables\.
|
||||
.TP
|
||||
\fBHOMEBREW_NO_FORCE_BREW_WRAPPER\fP
|
||||
\fBDeprecated:\fP If set, disables \fB$HOMEBREW_FORCE_BREW_WRAPPER\fP behaviour, even if set\.
|
||||
.TP
|
||||
\fBHOMEBREW_NO_GITHUB_API\fP
|
||||
If set, do not use the GitHub API, e\.g\. for searches or fetching relevant issues after a failed install\.
|
||||
.TP
|
||||
|
||||
Reference in new issue
Block a user