
Don’t rely on having external commands always present in the PATH in order to find them. Instead, provide an accessory method to Tap so they can be added and used when needed. While we’re here, do some general refactoring and cleanup of the command code in these places.
164 lines
5.0 KiB
Ruby
164 lines
5.0 KiB
Ruby
unless ENV["HOMEBREW_BREW_FILE"]
|
|
raise "HOMEBREW_BREW_FILE was not exported! Please call bin/brew directly!"
|
|
end
|
|
|
|
std_trap = trap("INT") { exit! 130 } # no backtrace thanks
|
|
|
|
# check ruby version before requiring any modules.
|
|
RUBY_VERSION_SPLIT = RUBY_VERSION.split "."
|
|
RUBY_X = RUBY_VERSION_SPLIT[0].to_i
|
|
RUBY_Y = RUBY_VERSION_SPLIT[1].to_i
|
|
if RUBY_X < 2 || (RUBY_X == 2 && RUBY_Y < 3)
|
|
raise "Homebrew must be run under Ruby 2.3! You're running #{RUBY_VERSION}."
|
|
end
|
|
|
|
require "pathname"
|
|
HOMEBREW_LIBRARY_PATH = Pathname.new(__FILE__).realpath.parent
|
|
require "English"
|
|
unless $LOAD_PATH.include?(HOMEBREW_LIBRARY_PATH.to_s)
|
|
$LOAD_PATH.unshift(HOMEBREW_LIBRARY_PATH.to_s)
|
|
end
|
|
require "global"
|
|
require "tap"
|
|
|
|
if ARGV == %w[--version] || ARGV == %w[-v]
|
|
puts "Homebrew #{HOMEBREW_VERSION}"
|
|
puts "Homebrew/homebrew-core #{CoreTap.instance.version_string}"
|
|
exit 0
|
|
end
|
|
|
|
begin
|
|
trap("INT", std_trap) # restore default CTRL-C handler
|
|
|
|
empty_argv = ARGV.empty?
|
|
help_flag_list = %w[-h --help --usage -?]
|
|
help_flag = !ENV["HOMEBREW_HELP"].nil?
|
|
cmd = nil
|
|
|
|
ARGV.dup.each_with_index do |arg, i|
|
|
break if help_flag && cmd
|
|
|
|
if arg == "help" && !cmd
|
|
# Command-style help: `help <cmd>` is fine, but `<cmd> help` is not.
|
|
help_flag = true
|
|
elsif !cmd && !help_flag_list.include?(arg)
|
|
cmd = ARGV.delete_at(i)
|
|
end
|
|
end
|
|
|
|
path = PATH.new(ENV["PATH"])
|
|
homebrew_path = PATH.new(ENV["HOMEBREW_PATH"])
|
|
|
|
# Add SCM wrappers.
|
|
path.append(HOMEBREW_SHIMS_PATH/"scm")
|
|
homebrew_path.append(HOMEBREW_SHIMS_PATH/"scm")
|
|
|
|
ENV["PATH"] = path
|
|
|
|
if cmd
|
|
internal_cmd = require? HOMEBREW_LIBRARY_PATH/"cmd"/cmd
|
|
|
|
unless internal_cmd
|
|
internal_dev_cmd = require? HOMEBREW_LIBRARY_PATH/"dev-cmd"/cmd
|
|
internal_cmd = internal_dev_cmd
|
|
if internal_dev_cmd && !ARGV.homebrew_developer?
|
|
system "git", "config", "--file=#{HOMEBREW_REPOSITORY}/.git/config",
|
|
"--replace-all", "homebrew.devcmdrun", "true"
|
|
ENV["HOMEBREW_DEV_CMD_RUN"] = "1"
|
|
end
|
|
end
|
|
end
|
|
|
|
# Usage instructions should be displayed if and only if one of:
|
|
# - a help flag is passed AND a command is matched
|
|
# - a help flag is passed AND there is no command specified
|
|
# - no arguments are passed
|
|
# - if cmd is Cask, let Cask handle the help command instead
|
|
if (empty_argv || help_flag) && cmd != "cask"
|
|
require "cmd/help"
|
|
Homebrew.help cmd, empty_argv: empty_argv
|
|
# `Homebrew.help` never returns, except for external/unknown commands.
|
|
end
|
|
|
|
# Migrate LinkedKegs/PinnedKegs if update didn't already do so
|
|
migrate_legacy_keg_symlinks_if_necessary
|
|
|
|
# Uninstall old brew-cask if it's still around; we just use the tap now.
|
|
if cmd == "cask" && (HOMEBREW_CELLAR/"brew-cask").exist?
|
|
system(HOMEBREW_BREW_FILE, "uninstall", "--force", "brew-cask")
|
|
end
|
|
|
|
unless internal_cmd
|
|
# Add contributed commands to PATH before checking.
|
|
homebrew_path.append(Tap.cmd_directories)
|
|
|
|
# External commands expect a normal PATH
|
|
ENV["PATH"] = homebrew_path
|
|
end
|
|
|
|
if internal_cmd
|
|
Homebrew.send cmd.to_s.tr("-", "_").downcase
|
|
elsif which "brew-#{cmd}"
|
|
%w[CACHE LIBRARY_PATH].each do |env|
|
|
ENV["HOMEBREW_#{env}"] = Object.const_get("HOMEBREW_#{env}").to_s
|
|
end
|
|
exec "brew-#{cmd}", *ARGV
|
|
elsif (path = which("brew-#{cmd}.rb")) && require?(path)
|
|
exit Homebrew.failed? ? 1 : 0
|
|
else
|
|
possible_tap = OFFICIAL_CMD_TAPS.find { |_, cmds| cmds.include?(cmd) }
|
|
possible_tap = Tap.fetch(possible_tap.first) if possible_tap
|
|
|
|
odie "Unknown command: #{cmd}" if !possible_tap || possible_tap.installed?
|
|
|
|
brew_uid = HOMEBREW_BREW_FILE.stat.uid
|
|
tap_commands = []
|
|
if Process.uid.zero? && !brew_uid.zero?
|
|
tap_commands += %W[/usr/bin/sudo -u ##{brew_uid}]
|
|
end
|
|
# Unset HOMEBREW_HELP to avoid confusing the tap
|
|
ENV.delete("HOMEBREW_HELP") if help_flag
|
|
tap_commands += %W[#{HOMEBREW_BREW_FILE} tap #{possible_tap}]
|
|
safe_system(*tap_commands)
|
|
ENV["HOMEBREW_HELP"] = "1" if help_flag
|
|
exec HOMEBREW_BREW_FILE, cmd, *ARGV
|
|
end
|
|
rescue UsageError => e
|
|
require "cmd/help"
|
|
Homebrew.help cmd, usage_error: e.message
|
|
rescue SystemExit => e
|
|
onoe "Kernel.exit" if ARGV.verbose? && !e.success?
|
|
$stderr.puts e.backtrace if ARGV.debug?
|
|
raise
|
|
rescue Interrupt
|
|
$stderr.puts # seemingly a newline is typical
|
|
exit 130
|
|
rescue BuildError => e
|
|
Utils::Analytics.report_build_error(e)
|
|
e.dump
|
|
exit 1
|
|
rescue RuntimeError, SystemCallError => e
|
|
raise if e.message.empty?
|
|
onoe e
|
|
$stderr.puts e.backtrace if ARGV.debug?
|
|
exit 1
|
|
rescue MethodDeprecatedError => e
|
|
onoe e
|
|
if e.issues_url
|
|
$stderr.puts "If reporting this issue please do so at (not Homebrew/brew or Homebrew/core):"
|
|
$stderr.puts " #{Formatter.url(e.issues_url)}"
|
|
end
|
|
exit 1
|
|
rescue Exception => e # rubocop:disable Lint/RescueException
|
|
onoe e
|
|
if internal_cmd && defined?(OS::ISSUES_URL) &&
|
|
!ENV["HOMEBREW_NO_AUTO_UPDATE"]
|
|
$stderr.puts "#{Tty.bold}Please report this bug:#{Tty.reset}"
|
|
$stderr.puts " #{Formatter.url(OS::ISSUES_URL)}"
|
|
end
|
|
$stderr.puts e.backtrace
|
|
exit 1
|
|
else
|
|
exit 1 if Homebrew.failed?
|
|
end
|