Skip to content
Snippets Groups Projects
brew.rb 5.12 KiB
Newer Older
#!/System/Library/Frameworks/Ruby.framework/Versions/Current/usr/bin/ruby -W0
# encoding: UTF-8
Max Howell's avatar
Max Howell committed
std_trap = trap("INT") { exit! 130 } # no backtrace thanks

HOMEBREW_BREW_FILE = ENV['HOMEBREW_BREW_FILE']
if ARGV == %w{--prefix}
  puts File.dirname(File.dirname(HOMEBREW_BREW_FILE))
  exit 0
end

HOMEBREW_LIBRARY_PATH = Pathname.new(__FILE__).realpath.dirname.parent.join("Library", "Homebrew")
$:.unshift(HOMEBREW_LIBRARY_PATH.to_s)
require 'global'
Max Howell's avatar
Max Howell committed

if ARGV.first == '--version'
  puts HOMEBREW_VERSION
  exit 0
elsif ARGV.first == '-v'
  puts "Homebrew #{HOMEBREW_VERSION}"
  # Shift the -v to the end of the parameter list
  ARGV << ARGV.shift
  # If no other arguments, just quit here.
  exit 0 if ARGV.length == 1
# Check for bad xcode-select before anything else, because `doctor` and
# many other things will hang
# Note that this bug was fixed in 10.9
if OS.mac? && MacOS.version < :mavericks && MacOS.active_developer_dir == "/"
  Your xcode-select path is currently set to '/'.
  This causes the `xcrun` tool to hang, and can render Homebrew unusable.
  If you are using Xcode, you should:
    sudo xcode-select -switch /Applications/Xcode.app
  Otherwise, you should:
    sudo rm -rf /usr/share/xcode-select
  EOS
end

case HOMEBREW_PREFIX.to_s when '/', '/usr'
  # it may work, but I only see pain this route and don't want to support it
  abort "Cowardly refusing to continue at this prefix: #{HOMEBREW_PREFIX}"
Max Howell's avatar
Max Howell committed
end
if OS.mac? and MacOS.version < "10.5"
Max Howell's avatar
Max Howell committed
  abort <<-EOABORT.undent
    Homebrew requires Leopard or higher. For Tiger support, see:
    https://github.com/mistydemeo/tigerbrew
Max Howell's avatar
Max Howell committed
  EOABORT
# Many Pathname operations use getwd when they shouldn't, and then throw
# odd exceptions. Reduce our support burden by showing a user-friendly error.
Dir.getwd rescue abort "The current working directory doesn't exist, cannot proceed."

Jack Nagel's avatar
Jack Nagel committed
  require path
rescue LoadError => e
  # HACK :( because we should raise on syntax errors but
  # not if the file doesn't exist. TODO make robust!
  raise unless e.to_s.include? path
Max Howell's avatar
Max Howell committed
begin
Max Howell's avatar
Max Howell committed
  trap("INT", std_trap) # restore default CTRL-C handler

  aliases = {'ls' => 'list',
             'homepage' => 'home',
             '-S' => 'search',
             'up' => 'update',
             'ln' => 'link',
             'instal' => 'install', # gem does the same
             'rm' => 'uninstall',
             'remove' => 'uninstall',
             'configure' => 'diy',
             'abv' => 'info',
             'dr' => 'doctor',
             '--repo' => '--repository',
Jack Nagel's avatar
Jack Nagel committed
             'environment' => '--env',
Adam Vandenberg's avatar
Adam Vandenberg committed
             '--config' => 'config',
  empty_argv = ARGV.empty?
  help_regex = /(-h$|--help$|--usage$|-\?$|help$)/
  help_flag = false
  cmd = nil

  ARGV.dup.each_with_index do |arg, i|
    if help_flag && cmd
      break
    elsif arg =~ help_regex
      help_flag = true
    elsif !cmd
      cmd = ARGV.delete_at(i)
    end
  end

  cmd = aliases[cmd] if aliases[cmd]

  sudo_check = Set.new %w[ install link pin unpin upgrade ]

  if sudo_check.include? cmd
    if Process.uid.zero? and not File.stat(HOMEBREW_BREW_FILE).uid.zero?
      raise "Cowardly refusing to `sudo brew #{cmd}`\n#{SUDO_BAD_ERRMSG}"
    end
  end

Adam Vandenberg's avatar
Adam Vandenberg committed
  # Add contributed commands to PATH before checking.
Jack Nagel's avatar
Jack Nagel committed
  ENV['PATH'] += "#{File::PATH_SEPARATOR}#{HOMEBREW_CONTRIB}/cmd"
  Dir["#{HOMEBREW_LIBRARY}/Taps/*/*/cmd"].each do |tap_cmd_dir|
    ENV["PATH"] += "#{File::PATH_SEPARATOR}#{tap_cmd_dir}"
  end
  internal_cmd = require? HOMEBREW_LIBRARY_PATH.join("cmd", cmd) if cmd

  # Usage instructions should be displayed if and only if one of:
  # - a help flag is passed AND an internal command is matched
  # - a help flag is passed AND there is no command specified
  # - no arguments are passed
  #
  # It should never affect external commands so they can handle usage
  # arguments themselves.

  if empty_argv || (help_flag && (cmd.nil? || internal_cmd))
    # TODO - `brew help cmd` should display subcommand help
    require 'cmd/help'
    puts ARGV.usage
    exit ARGV.any? ? 0 : 1
  end

  if internal_cmd
    Homebrew.send cmd.to_s.gsub('-', '_').downcase
  elsif which "brew-#{cmd}"
    %w[CACHE CELLAR LIBRARY_PATH PREFIX REPOSITORY].each do |e|
      ENV["HOMEBREW_#{e}"] = Object.const_get("HOMEBREW_#{e}").to_s
Max Howell's avatar
Max Howell committed
    end
    exec "brew-#{cmd}", *ARGV
Jack Nagel's avatar
Jack Nagel committed
  elsif (path = which("brew-#{cmd}.rb")) && require?(path)
    exit Homebrew.failed? ? 1 : 0
Max Howell's avatar
Max Howell committed
  else
    onoe "Unknown command: #{cmd}"
    exit 1
Max Howell's avatar
Max Howell committed
  end
Max Howell's avatar
Max Howell committed

rescue FormulaUnspecifiedError
  abort "This command requires a formula argument"
rescue KegUnspecifiedError
  abort "This command requires a keg argument"
rescue UsageError
  onoe "Invalid usage"
  abort ARGV.usage
Max Howell's avatar
Max Howell committed
rescue SystemExit
  puts "Kernel.exit" if ARGV.verbose?
Max Howell's avatar
Max Howell committed
rescue Interrupt => e
  puts # seemingly a newline is typical
Max Howell's avatar
Max Howell committed
  exit 130
rescue BuildError => e
  exit 1
rescue RuntimeError, SystemCallError => e
  raise if e.message.empty?
  onoe e
  puts e.backtrace if ARGV.debug?
  exit 1
Max Howell's avatar
Max Howell committed
rescue Exception => e
  puts "#{Tty.white}Please report this bug:"
Jack Nagel's avatar
Jack Nagel committed
  puts "    #{Tty.em}#{OS::ISSUES_URL}#{Tty.reset}"
  puts e.backtrace
else
  exit 1 if Homebrew.failed?