aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xLibrary/Contributions/examples/brew-missing.rb17
-rwxr-xr-xLibrary/Contributions/examples/brew-server1
-rwxr-xr-xLibrary/Contributions/examples/brew-upgrade.rb10
-rw-r--r--Library/Homebrew/beer_events.rb199
-rw-r--r--Library/Homebrew/brew.h.rb600
-rw-r--r--Library/Homebrew/cleaner.rb15
-rw-r--r--Library/Homebrew/cmd/--cache.rb9
-rw-r--r--Library/Homebrew/cmd/--cellar.rb9
-rw-r--r--Library/Homebrew/cmd/--config.rb66
-rw-r--r--Library/Homebrew/cmd/--env.rb32
-rw-r--r--Library/Homebrew/cmd/--prefix.rb9
-rw-r--r--Library/Homebrew/cmd/--repository.rb5
-rw-r--r--Library/Homebrew/cmd/cat.rb10
-rw-r--r--Library/Homebrew/cmd/cleanup.rb42
-rw-r--r--Library/Homebrew/cmd/create.rb153
-rw-r--r--Library/Homebrew/cmd/deps.rb14
-rw-r--r--Library/Homebrew/cmd/diy.rb34
-rw-r--r--Library/Homebrew/cmd/doctor.rb (renamed from Library/Homebrew/brew_doctor.rb)4
-rw-r--r--Library/Homebrew/cmd/edit.rb26
-rw-r--r--Library/Homebrew/cmd/home.rb9
-rw-r--r--Library/Homebrew/cmd/info.rb92
-rw-r--r--Library/Homebrew/cmd/install.rb87
-rw-r--r--Library/Homebrew/cmd/link.rb8
-rw-r--r--Library/Homebrew/cmd/list.rb88
-rw-r--r--Library/Homebrew/cmd/log.rb10
-rw-r--r--Library/Homebrew/cmd/outdated.rb28
-rw-r--r--Library/Homebrew/cmd/prune.rb31
-rw-r--r--Library/Homebrew/cmd/search.rb42
-rw-r--r--Library/Homebrew/cmd/uninstall.rb31
-rw-r--r--Library/Homebrew/cmd/unlink.rb8
-rw-r--r--Library/Homebrew/cmd/update.rb (renamed from Library/Homebrew/update.rb)13
-rw-r--r--Library/Homebrew/cmd/uses.rb25
-rw-r--r--Library/Homebrew/compatibility.rb47
-rw-r--r--Library/Homebrew/exceptions.rb99
-rw-r--r--Library/Homebrew/extend/ENV.rb2
-rw-r--r--Library/Homebrew/formula.rb66
-rw-r--r--Library/Homebrew/global.rb10
-rwxr-xr-xLibrary/Homebrew/install.rb5
-rw-r--r--Library/Homebrew/keg.rb4
-rw-r--r--Library/Homebrew/test/test_ENV.rb1
-rw-r--r--Library/Homebrew/test/test_bucket.rb28
-rw-r--r--Library/Homebrew/test/test_external_deps.rb34
-rw-r--r--Library/Homebrew/test/test_formula.rb1
-rw-r--r--Library/Homebrew/test/test_formula_install.rb2
-rw-r--r--Library/Homebrew/test/test_updater.rb2
-rw-r--r--Library/Homebrew/test/testing_env.rb6
-rw-r--r--Library/Homebrew/utils.rb143
-rwxr-xr-xbin/brew345
48 files changed, 1284 insertions, 1238 deletions
diff --git a/Library/Contributions/examples/brew-missing.rb b/Library/Contributions/examples/brew-missing.rb
index 68206278c..701bb1ca2 100755
--- a/Library/Contributions/examples/brew-missing.rb
+++ b/Library/Contributions/examples/brew-missing.rb
@@ -1,21 +1,18 @@
require "formula"
-require 'formula_installer'
+require "cmd/outdated"
def main
# Names of outdated brews; they count as installed.
- outdated = outdated_brews.collect {|b| b[1]}
+ outdated = Homebrew.outdated_brews.collect{ |b| b[1] }
- HOMEBREW_CELLAR.subdirs.each do |keg|
- next unless keg.subdirs
- if ((f = Formula.factory(keg.basename.to_s)).installed? rescue false)
- f_deps = FormulaInstaller.expand_deps(f).collect{|g| g.name}.uniq
- next if f_deps.empty?
-
- missing_deps = f_deps.reject do |dep_name|
+ HOMEBREW_CELLAR.subdirs.each do |rack|
+ f = Formula.factory rack.basename.to_s rescue nil
+ if f and f.installed?
+ missing_deps = f.recursive_deps.map{ |g| g.name }.uniq.reject do |dep_name|
Formula.factory(dep_name).installed? or outdated.include?(dep_name)
end
- puts "#{f.name}: #{missing_deps.join(', ')}" unless missing_deps.empty?
+ puts "#{f.name}: #{missing_deps * ', '}" unless missing_deps.empty?
end
end
end
diff --git a/Library/Contributions/examples/brew-server b/Library/Contributions/examples/brew-server
index b9919cf7a..5e7f80b58 100755
--- a/Library/Contributions/examples/brew-server
+++ b/Library/Contributions/examples/brew-server
@@ -82,7 +82,6 @@ get '/' do
end
get '/search' do
- require 'brew.h'
q = params['q']
results = search_brews(q)
diff --git a/Library/Contributions/examples/brew-upgrade.rb b/Library/Contributions/examples/brew-upgrade.rb
index 6c7831fde..3ffb570ac 100755
--- a/Library/Contributions/examples/brew-upgrade.rb
+++ b/Library/Contributions/examples/brew-upgrade.rb
@@ -1,11 +1,7 @@
# Updates all outdated brews
# See: http://github.com/mxcl/homebrew/issues/issue/1324
-# patch ARGV to use all of the outdated packages as the names passed in
-module HomebrewArgvExtension
- def formulae
- @formulae = outdated_brews.map {|_keg, name, _version| Formula.factory name}
- end
-end
+require 'cmd/outdated'
+require 'cmd/install'
-brew_install
+Homebrew.install_formulae Homebrew.outdated_brews.map{ |_keg, name, _version| Formula.factory name }
diff --git a/Library/Homebrew/beer_events.rb b/Library/Homebrew/beer_events.rb
deleted file mode 100644
index 18d0d0a6c..000000000
--- a/Library/Homebrew/beer_events.rb
+++ /dev/null
@@ -1,199 +0,0 @@
-# Vendored from Rucola: http://github.com/alloy/rucola/tree/master
-#
-# Copyright (c) 2007, 2008, 2009 Eloy Duran <eloy.de.enige@gmail.com>
-#
-# Permission is hereby granted, free of charge, to any person
-# obtaining a copy of this software and associated documentation
-# files (the "Software"), to deal in the Software without
-# restriction, including without limitation the rights to use,
-# copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following
-# conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-# OTHER DEALINGS IN THE SOFTWARE.
-
-begin
- require 'osx/cocoa'
- OSX.require_framework '/System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework'
-
- module Rucola
- class FSEvents
- class FSEvent
- attr_reader :fsevents_object
- attr_reader :id
- attr_reader :path
- def initialize(fsevents_object, id, path)
- @fsevents_object, @id, @path = fsevents_object, id, path
- end
-
- # Returns an array of the files/dirs in the path that the event occurred in.
- # The files are sorted by the modification time, the first entry is the last modified file.
- def files
- Dir.glob("#{File.expand_path(path)}/*").sort_by {|f| File.mtime(f) }.reverse
- end
-
- # Returns the last modified file in the path that the event occurred in.
- def last_modified_file
- files.first
- end
- end
-
- class StreamError < StandardError; end
-
- attr_reader :paths
- attr_reader :stream
-
- attr_accessor :allocator
- attr_accessor :context
- attr_accessor :since
- attr_accessor :latency
- attr_accessor :flags
-
- # Initializes a new FSEvents `watchdog` object and starts watching the directories you specify for events. The
- # block is used as a handler for events, which are passed as the block's argument. This method is the easiest
- # way to start watching some directories if you don't care about the details of setting up the event stream.
- #
- # Rucola::FSEvents.start_watching('/tmp') do |events|
- # events.each { |event| log.debug("#{event.files.inspect} were changed.") }
- # end
- #
- # Rucola::FSEvents.start_watching('/var/log/system.log', '/var/log/secure.log', :since => last_id, :latency => 5) do
- # Growl.notify("Something was added to your log files!")
- # end
- #
- # Note that the method also returns the FSEvents object. This enables you to control the event stream if you want to.
- #
- # fsevents = Rucola::FSEvents.start_watching('/Volumes') do |events|
- # events.each { |event| Growl.notify("Volume changes: #{event.files.to_sentence}") }
- # end
- # fsevents.stop
- def self.start_watching(*params, &block)
- fsevents = new(*params, &block)
- fsevents.create_stream
- fsevents.start
- fsevents
- end
-
- # Creates a new FSEvents `watchdog` object. You can specify a list of paths to watch and options to control the
- # behaviour of the watchdog. The block you pass serves as a callback when an event is generated on one of the
- # specified paths.
- #
- # fsevents = FSEvents.new('/etc/passwd') { Mailer.send_mail("Someone touched the password file!") }
- # fsevents.create_stream
- # fsevents.start
- #
- # fsevents = FSEvents.new('/home/upload', :since => UploadWatcher.last_event_id) do |events|
- # events.each do |event|
- # UploadWatcher.last_event_id = event.id
- # event.files.each do |file|
- # UploadWatcher.logfile.append("#{file} was changed")
- # end
- # end
- # end
- #
- # *:since: The service will report events that have happened after the supplied event ID. Never use 0 because that
- # will cause every fsevent since the "beginning of time" to be reported. Use OSX::KFSEventStreamEventIdSinceNow
- # if you want to receive events that have happened after this call. (Default: OSX::KFSEventStreamEventIdSinceNow).
- # You can find the ID's passed with :since in the events passed to your block.
- # *:latency: Number of seconds to wait until an FSEvent is reported, this allows the service to bundle events. (Default: 0.0)
- #
- # Please refer to the Cocoa documentation for the rest of the options.
- def initialize(*params, &block)
- raise ArgumentError, 'No callback block was specified.' unless block_given?
-
- options = params.last.kind_of?(Hash) ? params.pop : {}
- @paths = params.flatten
-
- paths.each { |path| raise ArgumentError, "The specified path (#{path}) does not exist." unless File.exist?(path) }
-
- @allocator = options[:allocator] || OSX::KCFAllocatorDefault
- @context = options[:context] || nil
- @since = options[:since] || OSX::KFSEventStreamEventIdSinceNow
- @latency = options[:latency] || 0.0
- @flags = options[:flags] || 0
- @stream = options[:stream] || nil
-
- @user_callback = block
- @callback = Proc.new do |stream, client_callback_info, number_of_events, paths_pointer, event_flags, event_ids|
- paths_pointer.regard_as('*')
- events = []
- number_of_events.times {|i| events << Rucola::FSEvents::FSEvent.new(self, event_ids[i], paths_pointer[i]) }
- @user_callback.call(events)
- end
- end
-
- # Create the stream.
- # Raises a Rucola::FSEvents::StreamError if the stream could not be created.
- def create_stream
- @stream = OSX.FSEventStreamCreate(@allocator, @callback, @context, @paths, @since, @latency, @flags)
- raise(StreamError, 'Unable to create FSEvents stream.') unless @stream
- OSX.FSEventStreamScheduleWithRunLoop(@stream, OSX.CFRunLoopGetCurrent, OSX::KCFRunLoopDefaultMode)
- end
-
- # Start the stream.
- # Raises a Rucola::FSEvents::StreamError if the stream could not be started.
- def start
- raise(StreamError, 'Unable to start FSEvents stream.') unless OSX.FSEventStreamStart(@stream)
- end
-
- # Stop the stream.
- # You can resume it by calling `start` again.
- def stop
- OSX.FSEventStreamStop(@stream)
- end
- end
- end
-
- # The complete BeerEvents API :)
- HOMEBREW_KEEP_DRY = %w{ /System /usr /etc /sbin /bin /Applications /Library }
-
- def watch_out_for_spill
- # Disable the RubyCocoa thread hook as apparently Laurent did not apply the
- # thread patches to the OS X system Ruby
- ENV['RUBYCOCOA_THREAD_HOOK_DISABLE'] = 'kampai'
-
- Thread.new { OSX.CFRunLoopRun() }
-
- start = Time.now
- dog = Rucola::FSEvents.start_watching(*HOMEBREW_KEEP_DRY) do |events|
- spill = events.map { |e| e.files }.flatten
- spill.reject! { |f| File.mtime(f) < start }
- spill.reject! { |path| path =~ /^#{HOMEBREW_PREFIX}/ }
- # irrelevent files that change a lot
- spill.reject! { |path| path == "/Library/Preferences/SystemConfiguration/com.apple.PowerManagement.plist-lock" }
- spill.reject! { |path| path =~ %r{^(/System)?/Library/Caches/} }
- unless spill.empty?
- opoo "Detected installation of files outside the Homebrew prefix:"
- puts *spill
- end
- end
- yield
- ensure
- dog.stop
- end
-rescue LoadError => e
- onoe "RubyCocoa could not be loaded, therefore checking for spill is disabled."
- puts "When using a custom Ruby installation, you'll need to install RubyCocoa."
- puts "If this is not the case, see if the following ticket applies, or create one."
- puts " http://github.com/mxcl/homebrew/issues#issue/37"
-
- if ARGV.verbose?
- onoe e.message
- puts e.backtrace
- end
-
- def watch_out_for_spill
- yield
- end
-end \ No newline at end of file
diff --git a/Library/Homebrew/brew.h.rb b/Library/Homebrew/brew.h.rb
deleted file mode 100644
index c4bfd1de1..000000000
--- a/Library/Homebrew/brew.h.rb
+++ /dev/null
@@ -1,600 +0,0 @@
-FORMULA_META_FILES = %w[README README.md ChangeLog COPYING LICENSE LICENCE COPYRIGHT AUTHORS]
-PLEASE_REPORT_BUG = "#{Tty.white}Please follow the instructions to report this bug at: #{Tty.em}\nhttps://github.com/mxcl/homebrew/wiki/new-issue#{Tty.reset}"
-
-def check_for_blacklisted_formula names
- return if ARGV.force?
-
- names.each do |name|
- case name
- when 'tex', 'tex-live', 'texlive' then abort <<-EOS.undent
- Installing TeX from source is weird and gross, requires a lot of patches,
- and only builds 32-bit (and thus can't use Homebrew deps on Snow Leopard.)
-
- We recommend using a MacTeX distribution:
- http://www.tug.org/mactex/
- EOS
-
- when 'mercurial', 'hg' then abort <<-EOS.undent
- Mercurial can be install thusly:
- brew install pip && pip install mercurial
- EOS
-
- when 'npm' then abort <<-EOS.undent
- npm can be installed thusly by following the instructions at
- http://npmjs.org/
-
- To do it in one line, use this command:
- curl http://npmjs.org/install.sh | sh
- EOS
-
-
- when 'setuptools' then abort <<-EOS.undent
- When working with a Homebrew-built Python, distribute is preferred
- over setuptools, and can be used as the prerequisite for pip.
-
- Install distribute using:
- brew install distribute
- EOS
- end
- end
-end
-
-def __make url, name
- require 'formula'
- require 'digest'
- require 'erb'
-
- path = Formula.path(name)
- raise "#{path} already exists" if path.exist?
-
- if Formula.aliases.include? name and not ARGV.force?
- realname = Formula.resolve_alias(name)
- raise <<-EOS.undent
- "#{name}" is an alias for formula "#{realname}".
- Please check that you are not creating a duplicate.
- To force creation use --force.
- EOS
- end
-
- if ARGV.include? '--cmake'
- mode = :cmake
- elsif ARGV.include? '--autotools'
- mode = :autotools
- else
- mode = nil
- end
-
- version = Pathname.new(url).version
- if version.nil?
- opoo "Version cannot be determined from URL."
- puts "You'll need to add an explicit 'version' to the formula."
- else
- puts "Version detected as #{version}."
- end
-
- md5 = ''
- if ARGV.include? "--cache" and version != nil
- strategy = detect_download_strategy url
- if strategy == CurlDownloadStrategy
- d = strategy.new url, name, version, nil
- the_tarball = d.fetch
- md5 = the_tarball.md5
- puts "MD5 is #{md5}"
- else
- puts "--cache requested, but we can only cache formulas that use Curl."
- end
- end
-
- formula_template = <<-EOS
-require 'formula'
-
-class #{Formula.class_s name} <Formula
- url '#{url}'
- homepage ''
- md5 '#{md5}'
-
-<% if mode == :cmake %>
- depends_on 'cmake'
-<% elsif mode == nil %>
- # depends_on 'cmake'
-<% end %>
-
- def install
-<% if mode == :cmake %>
- system "cmake . \#{std_cmake_parameters}"
-<% elsif mode == :autotools %>
- system "./configure", "--disable-debug", "--disable-dependency-tracking",
- "--prefix=\#{prefix}"
-<% else %>
- system "./configure", "--disable-debug", "--disable-dependency-tracking",
- "--prefix=\#{prefix}"
- # system "cmake . \#{std_cmake_parameters}"
-<% end %>
- system "make install"
- end
-end
- EOS
-
- path.write(ERB.new(formula_template, nil, '>').result(binding))
- return path
-end
-
-def make url
- path = Pathname.new url
-
- /(.*?)[-_.]?#{path.version}/.match path.basename
-
- unless $1.to_s.empty?
- name = $1
- else
- print "Formula name [#{path.stem}]: "
- gots = $stdin.gets.chomp
- if gots.empty?
- name = path.stem
- else
- name = gots
- end
- end
-
- force_text = "If you really want to make this formula use --force."
-
- case name.downcase
- when 'vim', 'screen'
- raise <<-EOS
-#{name} is blacklisted for creation
-Apple distributes this program with OS X.
-
-#{force_text}
- EOS
- when 'libarchive', 'libpcap'
- raise <<-EOS
-#{name} is blacklisted for creation
-Apple distributes this library with OS X, you can find it in /usr/lib.
-
-#{force_text}
- EOS
- when 'libxml', 'libxlst', 'freetype', 'libpng'
- raise <<-EOS
-#{name} is blacklisted for creation
-Apple distributes this library with OS X, you can find it in /usr/X11/lib.
-However not all build scripts look here, so you may need to call ENV.x11 or
-ENV.libxml2 in your formula's install function.
-
-#{force_text}
- EOS
- when 'rubygem'
- raise "Sorry RubyGems comes with OS X so we don't package it.\n\n#{force_text}"
- when 'wxwidgets'
- raise <<-EOS
-#{name} is blacklisted for creation
-An older version of wxWidgets is provided by Apple with OS X, but
-a formula for wxWidgets 2.8.10 is provided:
-
- brew install wxmac
-
- #{force_text}
- EOS
- end unless ARGV.force?
-
- __make url, name
-end
-
-def github_info name
- formula_name = Formula.path(name).basename
- user = 'mxcl'
- branch = 'master'
-
- if system "/usr/bin/which -s git"
- gh_user=`git config --global github.user 2>/dev/null`.chomp
- /^\*\s*(.*)/.match(`git --work-tree=#{HOMEBREW_REPOSITORY} branch 2>/dev/null`)
- unless $1.nil? || $1.empty? || gh_user.empty?
- branch = $1.chomp
- user = gh_user
- end
- end
-
- return "http://github.com/#{user}/homebrew/commits/#{branch}/Library/Formula/#{formula_name}"
-end
-
-def info f
- exec 'open', github_info(f.name) if ARGV.flag? '--github'
-
- puts "#{f.name} #{f.version}"
- puts f.homepage
-
- puts "Depends on: #{f.deps.join(', ')}" unless f.deps.empty?
-
- if f.prefix.parent.directory?
- kids=f.prefix.parent.children
- kids.each do |keg|
- next if keg.basename.to_s == '.DS_Store'
- print "#{keg} (#{keg.abv})"
- print " *" if f.installed_prefix == keg and kids.length > 1
- puts
- end
- else
- puts "Not installed"
- end
-
- if f.caveats
- puts
- puts f.caveats
- puts
- end
-
- history = github_info(f.name)
- puts history if history
-
-rescue FormulaUnavailableError
- # check for DIY installation
- d=HOMEBREW_PREFIX+name
- if d.directory?
- ohai "DIY Installation"
- d.children.each {|keg| puts "#{keg} (#{keg.abv})"}
- else
- raise "No such formula or keg"
- end
-end
-
-def issues_for_formula name
- # bit basic as depends on the issue at github having the exact name of the
- # formula in it. Which for stuff like objective-caml is unlikely. So we
- # really should search for aliases too.
-
- name = f.name if Formula === name
-
- require 'open-uri'
- require 'yaml'
-
- issues = []
-
- open("http://github.com/api/v2/yaml/issues/search/mxcl/homebrew/open/"+name) do |f|
- YAML::load(f.read)['issues'].each do |issue|
- issues << 'http://github.com/mxcl/homebrew/issues/#issue/%s' % issue['number']
- end
- end
-
- issues
-rescue
- []
-end
-
-def cleanup name
- require 'formula'
-
- f = Formula.factory name
- formula_cellar = f.prefix.parent
-
- if f.installed? and formula_cellar.directory?
- kids = f.prefix.parent.children
- kids.each do |keg|
- next if f.installed_prefix == keg
- print "Uninstalling #{keg}..."
- FileUtils.rm_rf keg
- puts
- end
- else
- # If the cellar only has one version installed, don't complain
- # that we can't tell which one to keep.
- if formula_cellar.children.length > 1
- opoo "Skipping #{name}: most recent version #{f.version} not installed"
- end
- end
-end
-
-def clean f
- require 'cleaner'
- Cleaner.new f
-
- # Hunt for empty folders and nuke them unless they are
- # protected by f.skip_clean?
- # We want post-order traversal, so put the dirs in a stack
- # and then pop them off later.
- paths = []
- f.prefix.find do |path|
- paths << path if path.directory?
- end
-
- until paths.empty? do
- d = paths.pop
- if d.children.empty? and not f.skip_clean? d
- puts "rmdir: #{d} (empty)" if ARGV.verbose?
- d.rmdir
- end
- end
-end
-
-
-def prune
- $n=0
- $d=0
-
- dirs=Array.new
- paths=%w[bin sbin etc lib include share].collect {|d| HOMEBREW_PREFIX+d}
-
- paths.each do |path|
- path.find do |path|
- path.extend ObserverPathnameExtension
- if path.symlink?
- path.unlink unless path.resolved_path_exists?
- elsif path.directory?
- dirs<<path
- end
- end
- end
-
- dirs.sort.reverse_each {|d| d.rmdir_if_possible}
-
- if $n == 0 and $d == 0
- puts "Nothing pruned" if ARGV.verbose?
- else
- # always showing symlinks text is deliberate
- print "Pruned #{$n} symbolic links "
- print "and #{$d} directories " if $d > 0
- puts "from #{HOMEBREW_PREFIX}"
- end
-end
-
-
-def diy
- path=Pathname.getwd
-
- if ARGV.include? '--set-version'
- version=ARGV.next
- else
- version=path.version
- raise "Couldn't determine version, try --set-version" if version.to_s.empty?
- end
-
- if ARGV.include? '--set-name'
- name=ARGV.next
- else
- path.basename.to_s =~ /(.*?)-?#{version}/
- if $1.nil? or $1.empty?
- name=path.basename
- else
- name=$1
- end
- end
-
- prefix=HOMEBREW_CELLAR+name+version
-
- if File.file? 'CMakeLists.txt'
- "-DCMAKE_INSTALL_PREFIX=#{prefix}"
- elsif File.file? 'Makefile.am'
- "--prefix=#{prefix}"
- else
- raise "Couldn't determine build system"
- end
-end
-
-def macports_or_fink_installed?
- # See these issues for some history:
- # http://github.com/mxcl/homebrew/issues/#issue/13
- # http://github.com/mxcl/homebrew/issues/#issue/41
- # http://github.com/mxcl/homebrew/issues/#issue/48
-
- %w[port fink].each do |ponk|
- path = `/usr/bin/which -s #{ponk}`
- return ponk unless path.empty?
- end
-
- # we do the above check because macports can be relocated and fink may be
- # able to be relocated in the future. This following check is because if
- # fink and macports are not in the PATH but are still installed it can
- # *still* break the build -- because some build scripts hardcode these paths:
- %w[/sw/bin/fink /opt/local/bin/port].each do |ponk|
- return ponk if File.exist? ponk
- end
-
- # finally, sometimes people make their MacPorts or Fink read-only so they
- # can quickly test Homebrew out, but still in theory obey the README's
- # advise to rename the root directory. This doesn't work, many build scripts
- # error out when they try to read from these now unreadable directories.
- %w[/sw /opt/local].each do |path|
- path = Pathname.new(path)
- return path if path.exist? and not path.readable?
- end
-
- false
-end
-
-def versions_of(keg_name)
- `/bin/ls #{HOMEBREW_CELLAR}/#{keg_name}`.collect { |version| version.strip }.reverse
-end
-
-
-def outdated_brews
- require 'formula'
-
- results = []
- HOMEBREW_CELLAR.subdirs.each do |keg|
- # Skip kegs with no versions installed
- next unless keg.subdirs
-
- # Skip HEAD formulae, consider them "evergreen"
- next if keg.subdirs.collect{|p|p.basename.to_s}.include? "HEAD"
-
- name = keg.basename.to_s
- if (not (f = Formula.factory(name)).installed? rescue nil)
- results << [keg, name, f.version]
- end
- end
- return results
-end
-
-def search_brews text
- require "formula"
-
- return Formula.names if text.to_s.empty?
-
- rx = if text =~ %r{^/(.*)/$}
- Regexp.new($1)
- else
- /.*#{Regexp.escape text}.*/i
- end
-
- aliases = Formula.aliases
- results = (Formula.names+aliases).grep rx
-
- # Filter out aliases when the full name was also found
- results.reject do |alias_name|
- if aliases.include? alias_name
- results.include? Formula.resolve_alias(alias_name)
- end
- end
-end
-
-def brew_install
- require 'formula_installer'
- require 'hardware'
-
- ############################################################ sanity checks
- case Hardware.cpu_type when :ppc, :dunno
- abort "Sorry, Homebrew does not support your computer's CPU architecture.\n"+
- "For PPC support, see: http://github.com/sceaga/homebrew/tree/powerpc"
- end
-
- raise "Cannot write to #{HOMEBREW_CELLAR}" if HOMEBREW_CELLAR.exist? and not HOMEBREW_CELLAR.writable?
- raise "Cannot write to #{HOMEBREW_PREFIX}" unless HOMEBREW_PREFIX.writable?
-
- ################################################################# warnings
- begin
- if MACOS_VERSION >= 10.6
- opoo "You should upgrade to Xcode 3.2.3" if llvm_build < RECOMMENDED_LLVM
- else
- opoo "You should upgrade to Xcode 3.1.4" if (gcc_40_build < RECOMMENDED_GCC_40) or (gcc_42_build < RECOMMENDED_GCC_42)
- end
- rescue
- # the reason we don't abort is some formula don't require Xcode
- # TODO allow formula to declare themselves as "not needing Xcode"
- opoo "Xcode is not installed! Builds may fail!"
- end
-
- if macports_or_fink_installed?
- opoo "It appears you have MacPorts or Fink installed."
- puts "Software installed with MacPorts and Fink are known to cause problems."
- puts "If you experience issues try uninstalling these tools."
- end
-
- ################################################################# install!
- installer = FormulaInstaller.new
- installer.install_deps = !ARGV.include?('--ignore-dependencies')
-
- ARGV.formulae.each do |f|
- if not f.installed? or ARGV.force?
- installer.install f
- else
- puts "Formula already installed: #{f.prefix}"
- end
- end
-end
-
-########################################################## class PrettyListing
-class PrettyListing
- def initialize path
- Pathname.new(path).children.sort{ |a,b| a.to_s.downcase <=> b.to_s.downcase }.each do |pn|
- case pn.basename.to_s
- when 'bin', 'sbin'
- pn.find { |pnn| puts pnn unless pnn.directory? }
- when 'lib'
- print_dir pn do |pnn|
- # dylibs have multiple symlinks and we don't care about them
- (pnn.extname == '.dylib' or pnn.extname == '.pc') and not pnn.symlink?
- end
- else
- if pn.directory?
- if pn.symlink?
- puts "#{pn} -> #{pn.readlink}"
- else
- print_dir pn
- end
- elsif not (FORMULA_META_FILES.include? pn.basename.to_s or pn.basename.to_s == '.DS_Store')
- puts pn
- end
- end
- end
- end
-
-private
- def print_dir root
- dirs = []
- remaining_root_files = []
- other = ''
-
- root.children.sort.each do |pn|
- if pn.directory?
- dirs << pn
- elsif block_given? and yield pn
- puts pn
- other = 'other '
- else
- remaining_root_files << pn unless pn.basename.to_s == '.DS_Store'
- end
- end
-
- dirs.each do |d|
- files = []
- d.find { |pn| files << pn unless pn.directory? }
- print_remaining_files files, d
- end
-
- print_remaining_files remaining_root_files, root, other
- end
-
- def print_remaining_files files, root, other = ''
- case files.length
- when 0
- # noop
- when 1
- puts files
- else
- puts "#{root}/ (#{files.length} #{other}files)"
- end
- end
-end
-
-
-def gcc_42_build
- `/usr/bin/gcc-4.2 -v 2>&1` =~ /build (\d{4,})/
- if $1
- $1.to_i
- elsif system "/usr/bin/which gcc"
- # Xcode 3.0 didn't come with gcc-4.2
- # We can't change the above regex to use gcc because the version numbers
- # are different and thus, not useful.
- # FIXME I bet you 20 quid this causes a side effect — magic values tend to
- 401
- else
- nil
- end
-end
-alias :gcc_build :gcc_42_build # For compatibility
-
-def gcc_40_build
- `/usr/bin/gcc-4.0 -v 2>&1` =~ /build (\d{4,})/
- if $1
- $1.to_i
- else
- nil
- end
-end
-
-def llvm_build
- if MACOS_VERSION >= 10.6
- xcode_path = `/usr/bin/xcode-select -print-path`.chomp
- return nil if xcode_path.empty?
- `#{xcode_path}/usr/bin/llvm-gcc -v 2>&1` =~ /LLVM build (\d{4,})/
- $1.to_i
- end
-end
-
-def xcode_version
- `xcodebuild -version 2>&1` =~ /Xcode (\d(\.\d)*)/
- return $1 ? $1 : nil
-end
-
-def _compiler_recommendation build, recommended
- message = (!build.nil? && build < recommended) ? "(#{recommended} or newer recommended)" : ""
- return build, message
-end
diff --git a/Library/Homebrew/cleaner.rb b/Library/Homebrew/cleaner.rb
index 84335f8a3..f19efc23b 100644
--- a/Library/Homebrew/cleaner.rb
+++ b/Library/Homebrew/cleaner.rb
@@ -6,6 +6,21 @@ class Cleaner
unless ENV['HOMEBREW_KEEP_INFO'].nil?
f.info.rmtree if f.info.directory? and not f.skip_clean? f.info
end
+
+ # Hunt for empty folders and nuke them unless they are protected by
+ # f.skip_clean? We want post-order traversal, so put the dirs in a stack
+ # and then pop them off later.
+ paths = []
+ f.prefix.find do |path|
+ paths << path if path.directory?
+ end
+
+ paths.each do |d|
+ if d.children.empty? and not f.skip_clean? d
+ puts "rmdir: #{d} (empty)" if ARGV.verbose?
+ d.rmdir
+ end
+ end
end
private
diff --git a/Library/Homebrew/cmd/--cache.rb b/Library/Homebrew/cmd/--cache.rb
new file mode 100644
index 000000000..f0a5b22f2
--- /dev/null
+++ b/Library/Homebrew/cmd/--cache.rb
@@ -0,0 +1,9 @@
+module Homebrew extend self
+ def __cache
+ if ARGV.named.empty?
+ puts HOMEBREW_CACHE
+ else
+ puts ARGV.formulae.map{ |f| f.cached_download }
+ end
+ end
+end
diff --git a/Library/Homebrew/cmd/--cellar.rb b/Library/Homebrew/cmd/--cellar.rb
new file mode 100644
index 000000000..c7e140dc5
--- /dev/null
+++ b/Library/Homebrew/cmd/--cellar.rb
@@ -0,0 +1,9 @@
+module Homebrew extend self
+ def __cellar
+ if ARGV.named.empty?
+ puts HOMEBREW_CELLAR
+ else
+ puts ARGV.formulae.map{ |f| HOMEBREW_CELLAR/f }
+ end
+ end
+end
diff --git a/Library/Homebrew/cmd/--config.rb b/Library/Homebrew/cmd/--config.rb
new file mode 100644
index 000000000..7a70df007
--- /dev/null
+++ b/Library/Homebrew/cmd/--config.rb
@@ -0,0 +1,66 @@
+require 'hardware'
+
+module Homebrew extend self
+ def __config
+ puts config_s
+ end
+
+ def llvm
+ @llvm ||= MacOS.llvm_build_version
+ end
+
+ def gcc_42
+ @gcc_42 ||= MacOS.gcc_42_build_version
+ end
+
+ def gcc_40
+ @gcc_40 ||= MacOS.gcc_40_build_version
+ end
+
+ def xcode_version
+ `xcodebuild -version 2>&1` =~ /Xcode (\d(\.\d)*)/
+ $1
+ end
+
+ def llvm_recommendation
+ "(#{RECOMMENDED_LLVM} or newer recommended)" if llvm and llvm < RECOMMENDED_LLVM
+ end
+
+ def gcc_42_recommendation
+ "(#{RECOMMENDED_GCC_42} or newer recommended)" if gcc_42 and gcc_42 < RECOMMENDED_GCC_42
+ end
+
+ def gcc_40_recommendation
+ "(#{RECOMMENDED_GCC_40} or newer recommended)" if gcc_40.nil? and gcc_40 < RECOMMENDED_GCC_40
+ end
+
+ def sha
+ sha = `cd #{HOMEBREW_REPOSITORY} && git rev-parse --verify HEAD 2> /dev/null`.chomp
+ if sha.empty? then "(none)" else sha end
+ end
+
+ def system_ruby
+ Pathname.new('/usr/bin/ruby').realpath.to_s
+ end
+
+ def config_s; <<-EOS.undent
+ HOMEBREW_VERSION: #{HOMEBREW_VERSION}
+ HEAD: #{sha}
+ HOMEBREW_PREFIX: #{HOMEBREW_PREFIX}
+ HOMEBREW_CELLAR: #{HOMEBREW_CELLAR}
+ HOMEBREW_REPOSITORY: #{HOMEBREW_REPOSITORY}
+ HOMEBREW_LIBRARY_PATH: #{HOMEBREW_LIBRARY_PATH}
+ Hardware: #{Hardware.cores_as_words}-core #{Hardware.bits}-bit #{Hardware.intel_family}
+ OS X: #{MACOS_FULL_VERSION}
+ Kernel Architecture: #{`uname -m`.chomp}
+ Ruby: #{RUBY_VERSION}-#{RUBY_PATCHLEVEL}
+ /usr/bin/ruby => #{system_ruby}
+ Xcode: #{xcode_version}
+ GCC-4.0: #{gcc_40 ? "build #{gcc_40}" : "N/A"} #{gcc_40_recommendation}
+ GCC-4.2: #{gcc_42 ? "build #{gcc_42}" : "N/A"} #{gcc_42_recommendation}
+ LLVM: #{llvm ? "build #{llvm}" : "N/A" } #{llvm_recommendation}
+ MacPorts or Fink? #{macports_or_fink_installed?}
+ X11 installed? #{x11_installed?}
+ EOS
+ end
+end
diff --git a/Library/Homebrew/cmd/--env.rb b/Library/Homebrew/cmd/--env.rb
new file mode 100644
index 000000000..07623171d
--- /dev/null
+++ b/Library/Homebrew/cmd/--env.rb
@@ -0,0 +1,32 @@
+require 'extend/ENV'
+require 'hardware'
+
+module Homebrew extend self
+ def __env
+ ENV.extend(HomebrewEnvExtension)
+ ENV.setup_build_environment
+ dump_build_env ENV
+ end
+
+ def dump_build_env env
+ puts %["--use-llvm" was specified] if ARGV.include? '--use-llvm'
+
+ %w[ CC CXX LD ].each do |k|
+ value = env[k]
+ if value
+ results = value
+ if File.exists? value and File.symlink? value
+ target = Pathname.new(value)
+ results += " => #{target.realpath}"
+ end
+ puts "#{k}: #{results}"
+ end
+ end
+
+ %w[ CFLAGS CXXFLAGS CPPFLAGS LDFLAGS MACOSX_DEPLOYMENT_TARGET MAKEFLAGS PKG_CONFIG_PATH
+ HOMEBREW_DEBUG HOMEBREW_VERBOSE HOMEBREW_USE_LLVM HOMEBREW_SVN ].each do |k|
+ value = env[k]
+ puts "#{k}: #{value}" if value
+ end
+ end
+end
diff --git a/Library/Homebrew/cmd/--prefix.rb b/Library/Homebrew/cmd/--prefix.rb
new file mode 100644
index 000000000..9a15203a9
--- /dev/null
+++ b/Library/Homebrew/cmd/--prefix.rb
@@ -0,0 +1,9 @@
+module Homebrew extend self
+ def __prefix
+ if ARGV.named.empty?
+ puts HOMEBREW_PREFIX
+ else
+ puts ARGV.formulae.map{ |f| f.prefix }
+ end
+ end
+end
diff --git a/Library/Homebrew/cmd/--repository.rb b/Library/Homebrew/cmd/--repository.rb
new file mode 100644
index 000000000..f14ab9901
--- /dev/null
+++ b/Library/Homebrew/cmd/--repository.rb
@@ -0,0 +1,5 @@
+module Homebrew extend self
+ def __repository
+ puts HOMEBREW_REPOSITORY
+ end
+end
diff --git a/Library/Homebrew/cmd/cat.rb b/Library/Homebrew/cmd/cat.rb
new file mode 100644
index 000000000..a87eba61e
--- /dev/null
+++ b/Library/Homebrew/cmd/cat.rb
@@ -0,0 +1,10 @@
+module Homebrew extend self
+ def cat
+ # do not "fix" this to support multiple arguments, the output would be
+ # unparsable, if the user wants to cat multiple formula they can call
+ # brew cat multiple times.
+
+ cd HOMEBREW_REPOSITORY
+ exec "cat", ARGV.formulae.first.path, *ARGV.options_only
+ end
+end
diff --git a/Library/Homebrew/cmd/cleanup.rb b/Library/Homebrew/cmd/cleanup.rb
new file mode 100644
index 000000000..f5e4637ec
--- /dev/null
+++ b/Library/Homebrew/cmd/cleanup.rb
@@ -0,0 +1,42 @@
+require 'formula'
+require 'cmd/prune'
+
+module Homebrew extend self
+ def cleanup
+ if ARGV.named.empty?
+ HOMEBREW_CELLAR.children.each do |rack|
+ begin
+ cleanup_formula rack.basename.to_s if rack.directory?
+ rescue FormulaUnavailableError => e
+ opoo "Formula not found for #{e.name}"
+ end
+ end
+ # seems like a good time to do some additional cleanup
+ Homebrew.prune
+ else
+ ARGV.formulae.each do |f|
+ cleanup_formula f
+ end
+ end
+ end
+
+ def cleanup_formula f
+ f = Formula.factory f
+ rack = f.prefix.parent
+
+ if f.installed? and rack.directory?
+ rack.children.each do |keg|
+ if f.installed_prefix != keg
+ print "Uninstalling #{keg}..."
+ rm_rf keg
+ puts
+ end
+ end
+ elsif rack.children.length > 1
+ # If the cellar only has one version installed, don't complain
+ # that we can't tell which one to keep.
+ opoo "Skipping #{name}: most recent version #{f.version} not installed"
+ end
+ end
+
+end
diff --git a/Library/Homebrew/cmd/create.rb b/Library/Homebrew/cmd/create.rb
new file mode 100644
index 000000000..e21c9a524
--- /dev/null
+++ b/Library/Homebrew/cmd/create.rb
@@ -0,0 +1,153 @@
+require 'formula'
+
+module Homebrew extend self
+ def create
+ if ARGV.include? '--macports'
+ exec "open", "http://www.macports.org/ports.php?by=name&substr=#{ARGV.next}"
+ elsif ARGV.include? '--fink'
+ exec "open", "http://pdb.finkproject.org/pdb/browse.php?summary=#{ARGV.next}"
+ elsif ARGV.named.empty?
+ raise UsageError
+ else
+ paths = ARGV.named.map do |url|
+ fc = FormulaCreator.new
+ fc.url = url
+ fc.mode = if ARGV.include? '--cmake'
+ :cmake
+ elsif ARGV.include? '--autotools'
+ :autotools
+ end
+
+ if fc.name.to_s.strip.empty?
+ path = Pathname.new url
+ print "Formula name [#{path.stem}]: "
+ fc.name = __gets || path.stem
+ end
+
+ unless ARGV.force?
+ if msg = blacklisted?(fc.name)
+ raise "#{msg}\n\nIf you really want to make this formula use --force."
+ end
+
+ if Formula.aliases.include? fc.name
+ realname = Formula.caniconical_name fc.name
+ raise <<-EOS.undent
+ The formula #{realname} is already aliased to #{fc.name}
+ Please check that you are not creating a duplicate.
+ To force creation use --force.
+ EOS
+ end
+ end
+ fc.generate
+ fc.path
+ end
+ exec_editor *paths
+ end
+ end
+
+ def __gets
+ gots = $stdin.gets.chomp
+ if gots.empty? then nil else gots end
+ end
+
+ def blacklisted? name
+ case name.downcase
+ when 'vim', 'screen' then <<-EOS.undent
+ #{name} is blacklisted for creation
+ Apple distributes this program with OS X.
+ EOS
+ when 'libarchive', 'libpcap' then <<-EOS.undent
+ #{name} is blacklisted for creation
+ Apple distributes this library with OS X, you can find it in /usr/lib.
+ EOS
+ when 'libxml', 'libxlst', 'freetype', 'libpng' then <<-EOS.undent
+ #{name} is blacklisted for creation
+ Apple distributes this library with OS X, you can find it in /usr/X11/lib.
+ However not all build scripts look here, so you may need to call ENV.x11 or
+ ENV.libxml2 in your formula's install function.
+ EOS
+ when /^rubygems?$/
+ "Sorry RubyGems comes with OS X so we don't package it."
+ when 'wxwidgets' then <<-EOS.undent
+ #{name} is blacklisted for creation
+ An older version of wxWidgets is provided by Apple with OS X, but
+ a formula for wxWidgets 2.8.10 is provided:
+
+ brew install wxmac
+ EOS
+ end
+ end
+end
+
+class FormulaCreator
+ attr :url
+ attr :md5
+ attr :name, true
+ attr :path
+ attr :mode, true
+
+ def url= url
+ @url = url
+ path = Pathname.new url
+ /(.*?)[-_.]?#{path.version}/.match path.basename
+ @name = $1
+ @path = Formula.path $1
+ end
+
+ def version
+ Pathname.new(url).version
+ end
+
+ def generate
+ raise "#{path} already exists" if path.exist?
+ raise VersionUndetermined if version.nil?
+
+ require 'digest'
+ require 'erb'
+
+ if version.nil?
+ opoo "Version cannot be determined from URL."
+ puts "You'll need to add an explicit 'version' to the formula."
+ else
+ puts "Version detected as #{version}."
+ end
+
+ unless ARGV.include? "--no-md5" and version
+ strategy = detect_download_strategy url
+ @md5 = strategy.new(url, name, version, nil).fetch.md5 if strategy == CurlDownloadStrategy
+ end
+
+ path.write ERB.new(template, nil, '>').result(binding)
+ end
+
+ def template; <<-EOS.undent
+ require 'formula'
+
+ class #{Formula.class_s name} <Formula
+ url '#{url}'
+ homepage ''
+ md5 '#{md5}'
+
+ <% if mode == :cmake %>
+ depends_on 'cmake'
+ <% elsif mode == nil %>
+ # depends_on 'cmake'
+ <% end %>
+
+ def install
+ <% if mode == :cmake %>
+ system "cmake . \#{std_cmake_parameters}"
+ <% elsif mode == :autotools %>
+ system "./configure", "--disable-debug", "--disable-dependency-tracking",
+ "--prefix=\#{prefix}"
+ <% else %>
+ system "./configure", "--disable-debug", "--disable-dependency-tracking",
+ "--prefix=\#{prefix}"
+ # system "cmake . \#{std_cmake_parameters}"
+ <% end %>
+ system "make install"
+ end
+ end
+ EOS
+ end
+end
diff --git a/Library/Homebrew/cmd/deps.rb b/Library/Homebrew/cmd/deps.rb
new file mode 100644
index 000000000..2e9a723f4
--- /dev/null
+++ b/Library/Homebrew/cmd/deps.rb
@@ -0,0 +1,14 @@
+module Homebrew extend self
+ def deps
+ puts if ARGV.include?('--all')
+ require 'formula'
+ Formula.all.each do |f|
+ "#{f.name}:#{f.deps.join(' ')}"
+ end
+ elsif ARGV.include?("-1") or ARGV.include?("--1")
+ *ARGV.formulae.map{ |f| f.deps or [] }.flatten.uniq.sort
+ else
+ *ARGV.formulae.map{ |f| f.recursive_deps.map{ |f| f.name } }.flatten.uniq.sort
+ end
+ end
+end
diff --git a/Library/Homebrew/cmd/diy.rb b/Library/Homebrew/cmd/diy.rb
new file mode 100644
index 000000000..174626afc
--- /dev/null
+++ b/Library/Homebrew/cmd/diy.rb
@@ -0,0 +1,34 @@
+module Homebrew extend self
+ def diy
+ path = Pathname.getwd
+
+ version = if ARGV.include? '--set-version'
+ ARGV.next
+ elsif path.version.to_s.empty?
+ raise "Couldn't determine version, try --set-version"
+ else
+ path.version
+ end
+
+ name = if ARGV.include? '--set-name'
+ ARGV.next
+ else
+ path.basename.to_s =~ /(.*?)-?#{version}/
+ if $1.to_s.empty?
+ path.basename
+ else
+ $1
+ end
+ end
+
+ prefix = HOMEBREW_CELLAR/name/version
+
+ if File.file? 'CMakeLists.txt'
+ puts "-DCMAKE_INSTALL_PREFIX=#{prefix}"
+ elsif File.file? 'Makefile.am'
+ puts "--prefix=#{prefix}"
+ else
+ raise "Couldn't determine build system"
+ end
+ end
+end
diff --git a/Library/Homebrew/brew_doctor.rb b/Library/Homebrew/cmd/doctor.rb
index b26cd4f5d..bad3a5dc0 100644
--- a/Library/Homebrew/brew_doctor.rb
+++ b/Library/Homebrew/cmd/doctor.rb
@@ -583,7 +583,8 @@ def check_for_other_vars
end
end
-def brew_doctor
+module Homebrew extend self
+def doctor
read, write = IO.pipe
if fork == nil
@@ -629,3 +630,4 @@ def brew_doctor
end
end
end
+end
diff --git a/Library/Homebrew/cmd/edit.rb b/Library/Homebrew/cmd/edit.rb
new file mode 100644
index 000000000..6ab91dccf
--- /dev/null
+++ b/Library/Homebrew/cmd/edit.rb
@@ -0,0 +1,26 @@
+require 'formula'
+
+module Homebrew extend self
+ def edit
+ if ARGV.named.empty?
+ # EDITOR isn't a good fit here, we need a GUI client that actually has
+ # a UI for projects, so apologies if this wasn't what you expected,
+ # please improve it! :)
+ exec 'mate', HOMEBREW_REPOSITORY/"bin/brew",
+ HOMEBREW_REPOSITORY/'README.md',
+ HOMEBREW_REPOSITORY/".gitignore",
+ *Dir[HOMEBREW_REPOSITORY/"Library/*"]
+ else
+ # Don't use ARGV.formulae as that will throw if the file doesn't parse
+ paths = ARGV.named.map do |name|
+ HOMEBREW_REPOSITORY/"Library/Formula/#{Formula.caniconical_name name}.rb"
+ end
+ unless ARGV.force?
+ paths.each do |path|
+ raise FormulaUnavailableError, path.basename('.rb').to_s unless path.file?
+ end
+ end
+ exec_editor *paths
+ end
+ end
+end
diff --git a/Library/Homebrew/cmd/home.rb b/Library/Homebrew/cmd/home.rb
new file mode 100644
index 000000000..a91607988
--- /dev/null
+++ b/Library/Homebrew/cmd/home.rb
@@ -0,0 +1,9 @@
+module Homebrew extend self
+ def home
+ if ARGV.named.empty?
+ exec "open", HOMEBREW_WWW
+ else
+ exec "open", *ARGV.formulae.map{ |f| f.homepage }
+ end
+ end
+end
diff --git a/Library/Homebrew/cmd/info.rb b/Library/Homebrew/cmd/info.rb
new file mode 100644
index 000000000..7f9767e07
--- /dev/null
+++ b/Library/Homebrew/cmd/info.rb
@@ -0,0 +1,92 @@
+require 'formula'
+
+module Homebrew extend self
+ def info
+ if ARGV.named.empty?
+ if ARGV.include? "--all"
+ Formula.each do |f|
+ info_formula f
+ puts '---'
+ end
+ else
+ puts "#{HOMEBREW_CELLAR.children.length} kegs, #{HOMEBREW_CELLAR.abv}"
+ end
+ elsif valid_url ARGV[0]
+ path = Pathname.new(ARGV.shift)
+ /(.*?)[-_.]?#{path.version}/.match path.basename
+ unless $1.to_s.empty?
+ name = $1
+ else
+ name = path.stem
+ end
+ puts "#{name} #{path.version}"
+ else
+ ARGV.formulae.each{ |f| info_formula f }
+ end
+ end
+
+ def github_info name
+ formula_name = Formula.path(name).basename
+ user = 'mxcl'
+ branch = 'master'
+
+ if system "/usr/bin/which -s git"
+ gh_user=`git config --global github.user 2>/dev/null`.chomp
+ /^\*\s*(.*)/.match(`git --work-tree=#{HOMEBREW_REPOSITORY} branch 2>/dev/null`)
+ unless $1.nil? || $1.empty? || gh_user.empty?
+ branch = $1.chomp
+ user = gh_user
+ end
+ end
+
+ "http://github.com/#{user}/homebrew/commits/#{branch}/Library/Formula/#{formula_name}"
+ end
+
+ def info_formula f
+ exec 'open', github_info(f.name) if ARGV.flag? '--github'
+
+ puts "#{f.name} #{f.version}"
+ puts f.homepage
+
+ puts "Depends on: #{f.deps*', '}" unless f.deps.empty?
+
+ rack = f.prefix.parent
+ if rack.directory?
+ kegs = rack.children
+ kegs.each do |keg|
+ next if keg.basename.to_s == '.DS_Store'
+ print "#{keg} (#{keg.abv})"
+ print " *" if f.installed_prefix == keg and kegs.length > 1
+ puts
+ end
+ else
+ puts "Not installed"
+ end
+
+ if f.caveats
+ puts
+ puts f.caveats
+ puts
+ end
+
+ history = github_info f.name
+ puts history if history
+
+ rescue FormulaUnavailableError
+ # check for DIY installation
+ d = HOMEBREW_PREFIX/name
+ if d.directory?
+ ohai "DIY Installation"
+ d.children.each{ |keg| puts "#{keg} (#{keg.abv})" }
+ else
+ raise "No such formula or keg"
+ end
+ end
+
+ private
+
+ def valid_url u
+ u[0..6] == 'http://' or u[0..7] == 'https://' or u[0..5] == 'ftp://'
+ end
+
+end
diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb
new file mode 100644
index 000000000..ed5fb6777
--- /dev/null
+++ b/Library/Homebrew/cmd/install.rb
@@ -0,0 +1,87 @@
+require 'formula_installer'
+require 'hardware'
+
+module Homebrew extend self
+ def install
+ brew_install
+ end
+end
+
+def brew_install
+ ############################################################ sanity checks
+ case Hardware.cpu_type when :ppc, :dunno
+ abort "Sorry, Homebrew does not support your computer's CPU architecture.\n"+
+ "For PPC support, see: http://github.com/sceaga/homebrew/tree/powerpc"
+ end
+
+ raise "Cannot write to #{HOMEBREW_CELLAR}" if HOMEBREW_CELLAR.exist? and not HOMEBREW_CELLAR.writable?
+ raise "Cannot write to #{HOMEBREW_PREFIX}" unless HOMEBREW_PREFIX.writable?
+
+ ################################################################# warnings
+ begin
+ if MACOS_VERSION >= 10.6
+ opoo "You should upgrade to Xcode 3.2.3" if llvm_build < RECOMMENDED_LLVM
+ else
+ opoo "You should upgrade to Xcode 3.1.4" if (gcc_40_build < RECOMMENDED_GCC_40) or (gcc_42_build < RECOMMENDED_GCC_42)
+ end
+ rescue
+ # the reason we don't abort is some formula don't require Xcode
+ # TODO allow formula to declare themselves as "not needing Xcode"
+ opoo "Xcode is not installed! Builds may fail!"
+ end
+
+ if macports_or_fink_installed?
+ opoo "It appears you have MacPorts or Fink installed."
+ puts "Software installed with MacPorts and Fink are known to cause problems."
+ puts "If you experience issues try uninstalling these tools."
+ end
+
+ ################################################################# install!
+ installer = FormulaInstaller.new
+ installer.install_deps = !ARGV.include?('--ignore-dependencies')
+
+ ARGV.formulae.each do |f|
+ if not f.installed? or ARGV.force?
+ installer.install f
+ else
+ puts "Formula already installed: #{f.prefix}"
+ end
+ end
+end
+
+def check_for_blacklisted_formula names
+ return if ARGV.force?
+
+ names.each do |name|
+ case name
+ when 'tex', 'tex-live', 'texlive' then abort <<-EOS.undent
+ Installing TeX from source is weird and gross, requires a lot of patches,
+ and only builds 32-bit (and thus can't use Homebrew deps on Snow Leopard.)
+
+ We recommend using a MacTeX distribution:
+ http://www.tug.org/mactex/
+ EOS
+
+ when 'mercurial', 'hg' then abort <<-EOS.undent
+ Mercurial can be install thusly:
+ brew install pip && pip install mercurial
+ EOS
+
+ when 'npm' then abort <<-EOS.undent
+ npm can be installed thusly by following the instructions at
+ http://npmjs.org/
+
+ To do it in one line, use this command:
+ curl http://npmjs.org/install.sh | sudo sh
+ EOS
+
+ when 'setuptools' then abort <<-EOS.undent
+ When working with a Homebrew-built Python, distribute is preferred
+ over setuptools, and can be used as the prerequisite for pip.
+
+ Install distribute using:
+ brew install distribute
+ EOS
+ end
+ end
+end
diff --git a/Library/Homebrew/cmd/link.rb b/Library/Homebrew/cmd/link.rb
new file mode 100644
index 000000000..5565309e2
--- /dev/null
+++ b/Library/Homebrew/cmd/link.rb
@@ -0,0 +1,8 @@
+module Homebrew extend self
+ def link
+ ARGV.kegs.each do |keg|
+ print "Linking #{keg}... "
+ puts "#{keg.link} links created"
+ end
+ end
+end
diff --git a/Library/Homebrew/cmd/list.rb b/Library/Homebrew/cmd/list.rb
new file mode 100644
index 000000000..8e35530fd
--- /dev/null
+++ b/Library/Homebrew/cmd/list.rb
@@ -0,0 +1,88 @@
+module Homebrew extend self
+ def list
+ if ARGV.flag? '--unbrewed'
+ dirs = HOMEBREW_PREFIX.children.select{ |pn| pn.directory? }.map{ |pn| pn.basename.to_s }
+ dirs -= %w[Library Cellar .git]
+ cd HOMEBREW_PREFIX
+ exec 'find', *dirs + %w[-type f ( ! -iname .ds_store ! -iname brew )]
+ elsif ARGV.flag? '--versions'
+ if ARGV.named.empty?
+ HOMEBREW_CELLAR.children.select{ |pn| pn.directory? }
+ else
+ ARGV.named.map{ |n| HOMEBREW_CELLAR/n }.select{ |pn| pn.exist? }
+ end.each do |d|
+ versions = d.children.select{ |pn| pn.directory? }.map{ |pn| pn.basename.to_s }
+ puts "#{d.basename} #{versions*' '}"
+ end
+ elsif ARGV.named.empty?
+ ENV['CLICOLOR'] = nil
+ exec 'ls', *ARGV.options_only << HOMEBREW_CELLAR if HOMEBREW_CELLAR.exist?
+ elsif ARGV.verbose? or not $stdout.tty?
+ exec "find", *ARGV.kegs + %w[-not -type d -print]
+ else
+ ARGV.kegs.each{ |keg| PrettyListing.new keg }
+ end
+ end
+end
+
+class PrettyListing
+ def initialize path
+ Pathname.new(path).children.sort{ |a,b| a.to_s.downcase <=> b.to_s.downcase }.each do |pn|
+ case pn.basename.to_s
+ when 'bin', 'sbin'
+ pn.find { |pnn| puts pnn unless pnn.directory? }
+ when 'lib'
+ print_dir pn do |pnn|
+ # dylibs have multiple symlinks and we don't care about them
+ (pnn.extname == '.dylib' or pnn.extname == '.pc') and not pnn.symlink?
+ end
+ else
+ if pn.directory?
+ if pn.symlink?
+ puts "#{pn} -> #{pn.readlink}"
+ else
+ print_dir pn
+ end
+ elsif not (FORMULA_META_FILES + ['.DS_Store']).include? pn.basename.to_s
+ puts pn
+ end
+ end
+ end
+ end
+
+ def print_dir root
+ dirs = []
+ remaining_root_files = []
+ other = ''
+
+ root.children.sort.each do |pn|
+ if pn.directory?
+ dirs << pn
+ elsif block_given? and yield pn
+ puts pn
+ other = 'other '
+ else
+ remaining_root_files << pn unless pn.basename.to_s == '.DS_Store'
+ end
+ end
+
+ dirs.each do |d|
+ files = []
+ d.find { |pn| files << pn unless pn.directory? }
+ print_remaining_files files, d
+ end
+
+ print_remaining_files remaining_root_files, root, other
+ end
+
+ def print_remaining_files files, root, other = ''
+ case files.length
+ when 0
+ # noop
+ when 1
+ puts files
+ else
+ puts "#{root}/ (#{files.length} #{other}files)"
+ end
+ end
+end
diff --git a/Library/Homebrew/cmd/log.rb b/Library/Homebrew/cmd/log.rb
new file mode 100644
index 000000000..ceb0c8e02
--- /dev/null
+++ b/Library/Homebrew/cmd/log.rb
@@ -0,0 +1,10 @@
+module Homebrew extend self
+ def log
+ cd HOMEBREW_REPOSITORY
+ if ARGV.named.empty?
+ exec "git", "log", *ARGV.options_only
+ else
+ exec "git", "log", *ARGV.formulae.map(&:path), *ARGV.options_only
+ end
+ end
+end
diff --git a/Library/Homebrew/cmd/outdated.rb b/Library/Homebrew/cmd/outdated.rb
new file mode 100644
index 000000000..37fba0f99
--- /dev/null
+++ b/Library/Homebrew/cmd/outdated.rb
@@ -0,0 +1,28 @@
+require 'formula'
+
+module Homebrew extend self
+ def outdated
+ outdated_brews.each do |keg, name, version|
+ if $stdout.tty? and not ARGV.flag? '--quiet'
+ versions = keg.cd{ Dir['*'] }.join(', ')
+ puts "#{name} (#{versions} < #{version})"
+ else
+ puts name
+ end
+ end
+ end
+
+ def outdated_brews
+ HOMEBREW_CELLAR.subdirs.map do |rack|
+ # Skip kegs with no versions installed
+ next unless rack.subdirs
+
+ # Skip HEAD formulae, consider them "evergreen"
+ next if rack.subdirs.map{ |keg| keg.basename.to_s }.include? "HEAD"
+
+ name = rack.basename.to_s
+ f = Formula.factory name rescue nil
+ [rack, name, f.version] if f and not f.installed?
+ end.compact
+ end
+end \ No newline at end of file
diff --git a/Library/Homebrew/cmd/prune.rb b/Library/Homebrew/cmd/prune.rb
new file mode 100644
index 000000000..ba4bbc8e5
--- /dev/null
+++ b/Library/Homebrew/cmd/prune.rb
@@ -0,0 +1,31 @@
+module Homebrew extend self
+ # $n and $d are used by the ObserverPathnameExtension to keep track of
+ # certain filesystem actions.
+
+ def prune
+ $n = 0
+ $d = 0
+ dirs = []
+
+ %w[bin sbin etc lib include share].map{ |d| HOMEBREW_PREFIX/d }.each do |path|
+ path.find do |path|
+ path.extend ObserverPathnameExtension
+ if path.symlink?
+ path.unlink unless path.resolved_path_exists?
+ elsif path.directory?
+ dirs << path
+ end
+ end
+ end
+
+ dirs.sort.reverse_each{ |d| d.rmdir_if_possible }
+
+ if $n == 0 and $d == 0
+ puts "Nothing pruned" if ARGV.verbose?
+ else
+ print "Pruned #{$n} symbolic links "
+ print "and #{$d} directories " if $d > 0
+ puts "from #{HOMEBREW_PREFIX}"
+ end
+ end
+end
diff --git a/Library/Homebrew/cmd/search.rb b/Library/Homebrew/cmd/search.rb
new file mode 100644
index 000000000..b6a0e971d
--- /dev/null
+++ b/Library/Homebrew/cmd/search.rb
@@ -0,0 +1,42 @@
+require "formula"
+
+module Homebrew extend self
+ def search
+ if ARGV.include? '--macports'
+ exec "open", "http://www.macports.org/ports.php?by=name&substr=#{ARGV.next}"
+ elsif ARGV.include? '--fink'
+ exec "open", "http://pdb.finkproject.org/pdb/browse.php?summary=#{ARGV.next}"
+ end
+
+ require 'cmd/install' # for blacklisted? function
+ blacklisted? ARGV.named do |msg, _|
+ abort msg
+ end unless ARGV.force?
+
+ puts_columns search_brews(ARGV.first)
+ end
+
+ def search_brews text
+ if text.to_s.empty?
+ Formula.names
+ else
+ rx = if text =~ %r{^/(.*)/$}
+ Regexp.new($1)
+ else
+ /.*#{Regexp.escape text}.*/i
+ end
+
+ aliases = Formula.aliases
+ results = (Formula.names+aliases).grep rx
+
+ # Filter out aliases when the full name was also found
+ results.reject do |alias_name|
+ if aliases.include? alias_name
+ resolved_name = (HOMEBREW_REPOSITORY/"Library/Aliases"/alias_name).readlink.basename('.rb').to_s
+ results.include? resolved_name
+ end
+ end
+ end
+ end
+
+end
diff --git a/Library/Homebrew/cmd/uninstall.rb b/Library/Homebrew/cmd/uninstall.rb
new file mode 100644
index 000000000..34de88130
--- /dev/null
+++ b/Library/Homebrew/cmd/uninstall.rb
@@ -0,0 +1,31 @@
+require 'keg'
+
+module Homebrew extend self
+ def uninstall
+ unless ARGV.force?
+ ARGV.kegs.each do |keg|
+ puts "Uninstalling #{keg}..."
+ keg.unlink
+ keg.uninstall
+ end
+ else
+ ARGV.formulae.each do |f|
+ rack = f.prefix.parent
+ if rack.directory?
+ puts "Uninstalling #{f}..."
+ rack.children do |keg|
+ if keg.directory?
+ keg = Keg.new(keg)
+ keg.unlink
+ keg.rmtree
+ end
+ end
+ rack.rmdir
+ end
+ end
+ end
+ rescue MultipleVersionsInstalledError => e
+ onoe e
+ puts "Use `brew remove --force #{e.name}` to remove all versions."
+ end
+end
diff --git a/Library/Homebrew/cmd/unlink.rb b/Library/Homebrew/cmd/unlink.rb
new file mode 100644
index 000000000..d4749ab76
--- /dev/null
+++ b/Library/Homebrew/cmd/unlink.rb
@@ -0,0 +1,8 @@
+module Homebrew extend self
+ def unlink
+ ARGV.kegs.each do |keg|
+ print "Unlinking #{keg}... "
+ puts "#{keg.unlink} links removed"
+ end
+ end
+end
diff --git a/Library/Homebrew/update.rb b/Library/Homebrew/cmd/update.rb
index 9e4fb90d9..32f144c8e 100644
--- a/Library/Homebrew/update.rb
+++ b/Library/Homebrew/cmd/update.rb
@@ -1,3 +1,16 @@
+module Homebrew extend self
+ def update
+ abort "Please `brew install git' first." unless system "/usr/bin/which -s git"
+
+ updater = RefreshBrew.new
+ if updater.update_from_masterbrew!
+ updater.report
+ else
+ puts "Already up-to-date."
+ end
+ end
+end
+
class RefreshBrew
REPOSITORY_URL = "http://github.com/mxcl/homebrew.git"
INIT_COMMAND = "git init"
diff --git a/Library/Homebrew/cmd/uses.rb b/Library/Homebrew/cmd/uses.rb
new file mode 100644
index 000000000..455b29b31
--- /dev/null
+++ b/Library/Homebrew/cmd/uses.rb
@@ -0,0 +1,25 @@
+require 'formula'
+
+# `brew uses foo bar` now returns formula that use both foo and bar
+# Rationale: If you want the union just run the command twice and
+# concatenate the results.
+# The intersection is harder to achieve with shell tools.
+
+module Homebrew extend self
+ def uses
+ uses = Formula.all.select do |f|
+ ARGV.formulae.all? do |ff|
+ # For each formula given, show which other formulas depend on it.
+ # We only go one level up, ie. direct dependencies.
+ f.deps.include? ff.name
+ end
+ end
+ if ARGV.include? "--installed"
+ uses = uses.select do |f|
+ keg = HOMEBREW_CELLAR/f
+ keg.directory? and not keg.subdirs.empty?
+ end
+ end
+ puts uses.sort
+ end
+end
diff --git a/Library/Homebrew/compatibility.rb b/Library/Homebrew/compatibility.rb
new file mode 100644
index 000000000..52f98416a
--- /dev/null
+++ b/Library/Homebrew/compatibility.rb
@@ -0,0 +1,47 @@
+
+# maybe never used by anyone, but alas it must continue to exist
+def versions_of(keg_name)
+ `/bin/ls #{HOMEBREW_CELLAR}/#{keg_name}`.collect { |version| version.strip }.reverse
+end
+
+def dump_config
+ require 'cmd/--config'
+ Homebrew.__config
+end
+
+def dump_build_env env
+ require 'cmd/--env'
+ Homebrew.dump_build_env env
+end
+
+def gcc_42_build
+ MacOS.gcc_42_build_version
+end
+
+alias :gcc_build :gcc_42_build
+
+def gcc_40_build
+ MacOS.gcc_40_build_version
+end
+
+def llvm_build
+ MacOS.llvm_build_version
+end
+
+def x11_installed?
+ MacOS.x11_installed?
+end
+
+def macports_or_fink_installed?
+ MacOS.macports_or_fink_installed?
+end
+
+def outdated_brews
+ require 'cmd/outdated'
+ Homebrew.outdated_brews
+end
+
+def search_brews text
+ require 'cmd/search'
+ Homebrew.search_brews text
+end
diff --git a/Library/Homebrew/exceptions.rb b/Library/Homebrew/exceptions.rb
new file mode 100644
index 000000000..73cda01e5
--- /dev/null
+++ b/Library/Homebrew/exceptions.rb
@@ -0,0 +1,99 @@
+
+class NotAKegError < RuntimeError
+end
+
+class FormulaUnavailableError < RuntimeError
+ attr :name
+ def initialize name
+ @name = name
+ super "No available formula for #{name}"
+ end
+end
+
+module Homebrew
+ class InstallationError < RuntimeError
+ attr :formula
+ def initialize formula
+ @formula = formula
+ end
+ def initialize formula, message
+ super message
+ @formula = formula
+ end
+ end
+end
+
+class FormulaAlreadyInstalledError < Homebrew::InstallationError
+ def message
+ "Formula already installed: #{formula}"
+ end
+end
+
+class FormulaInstallationAlreadyAttemptedError < Homebrew::InstallationError
+ def message
+ "Formula installation already attempted: #{formula}"
+ end
+end
+
+class UnsatisfiedExternalDependencyError < Homebrew::InstallationError
+ attr :type
+
+ def initialize formula, type
+ @type = type
+ @formula = formula
+ end
+
+ def message
+ <<-EOS.undent
+ Unsatisfied dependency: #{formula}
+ Homebrew does not provide #{type.to_s.capitalize} dependencies, #{tool} does:
+
+ #{command_line} #{formula}
+ EOS
+ end
+
+ private
+
+ def tool
+ case type
+ when :python then 'pip'
+ when :ruby, :jruby then 'rubygems'
+ when :perl then 'cpan'
+ end
+ end
+
+ def command_line
+ case type
+ when :python
+ "#{brew_pip}pip install"
+ when :ruby
+ "gem install"
+ when :perl
+ "cpan -i"
+ when :jruby
+ "jruby -S gem install"
+ end
+ end
+
+ def brew_pip
+ 'brew install pip && ' unless Formula.factory('pip').installed?
+ end
+end
+
+class BuildError < Homebrew::InstallationError
+ attr :exit_status
+ attr :command
+ attr :env
+
+ def initialize formula, cmd, args, es
+ @command = cmd
+ @env = ENV.to_hash
+ @exit_status = es.exitstatus rescue 1
+ args = args.map{ |arg| arg.gsub " ", "\\ " }.join(" ")
+ super formula, "Failed executing: #{command} #{args}"
+ end
+
+ def was_running_configure?
+ @command == './configure'
+ end
+end
diff --git a/Library/Homebrew/extend/ENV.rb b/Library/Homebrew/extend/ENV.rb
index 61fb3c2b3..a4e290d5f 100644
--- a/Library/Homebrew/extend/ENV.rb
+++ b/Library/Homebrew/extend/ENV.rb
@@ -152,7 +152,7 @@ module HomebrewEnvExtension
end
def x11
- opoo "You do not have X11 installed, this formula may not build." if not x11_installed?
+ opoo "You do not have X11 installed, this formula may not build." if not MacOS.x11_installed?
# There are some config scripts (e.g. freetype) here that should go in the path
prepend 'PATH', '/usr/X11/bin', ':'
diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb
index 0e3266351..78e438726 100644
--- a/Library/Homebrew/formula.rb
+++ b/Library/Homebrew/formula.rb
@@ -1,15 +1,6 @@
require 'download_strategy'
require 'fileutils'
-class FormulaUnavailableError <RuntimeError
- def initialize name
- @name = name
- super "No available formula for #{name}"
- end
-
- attr_reader :name
-end
-
class SoftwareSpecification
attr_reader :url, :specs, :using
@@ -223,6 +214,22 @@ class Formula
end
end
+ def == b
+ name == b.name
+ end
+ def eql? b
+ self == b and self.class.equal? b.class
+ end
+ def hash
+ name.hash
+ end
+ def <=> b
+ name <=> b.name
+ end
+ def to_s
+ name
+ end
+
# Standard parameters for CMake builds.
# Using Build Type "None" tells cmake to use our CFLAGS,etc. settings.
# Setting it to Release would ignore our flags.
@@ -266,15 +273,25 @@ class Formula
# an array of all Formula, instantiated
def self.all
- all = []
+ map{ |f| f }
+ end
+ def self.map
+ rv = []
+ each{ |f| rv << yield(f) }
+ rv
+ end
+ def self.each
names.each do |n|
begin
- all << Formula.factory(n)
+ yield Formula.factory(n)
rescue
# Don't let one broken formula break commands.
end
end
- return all
+ end
+
+ def inspect
+ name
end
def self.aliases
@@ -320,8 +337,9 @@ class Formula
install_type = :from_path
target_file = path.to_s
else
+ name = Formula.caniconical_name(name)
# For names, map to the path and then require
- require self.path(name)
+ require Formula.path(name)
install_type = :from_name
end
end
@@ -344,7 +362,7 @@ class Formula
end
def self.path name
- HOMEBREW_REPOSITORY+"Library/Formula/#{name.downcase}.rb"
+ HOMEBREW_REPOSITORY/"Library/Formula/#{name.downcase}.rb"
end
def deps
@@ -352,7 +370,20 @@ class Formula
end
def external_deps
- self.class.external_deps
+ self.class.external_deps or {}
+ end
+
+ # deps are in an installable order
+ # which means if a depends on b then b will be ordered before a in this list
+ def recursive_deps
+ Formula.expand_deps(self).flatten.uniq
+ end
+
+ def self.expand_deps f
+ f.deps.map do |dep|
+ dep = Formula.factory dep
+ expand_deps(dep) << dep
+ end
end
protected
@@ -381,11 +412,8 @@ protected
raise
end
end
- rescue SystemCallError
- # usually because exec could not be find the command that was requested
- raise
rescue
- raise BuildError.new(cmd, args, $?)
+ raise BuildError.new(self, cmd, args, $?)
end
private
diff --git a/Library/Homebrew/global.rb b/Library/Homebrew/global.rb
index 0555b1267..3cc1024e7 100644
--- a/Library/Homebrew/global.rb
+++ b/Library/Homebrew/global.rb
@@ -2,6 +2,8 @@ require 'extend/pathname'
require 'extend/ARGV'
require 'extend/string'
require 'utils'
+require 'exceptions'
+require 'compatibility'
ARGV.extend(HomebrewArgvExtension)
@@ -40,3 +42,11 @@ HOMEBREW_USER_AGENT = "Homebrew #{HOMEBREW_VERSION} (Ruby #{RUBY_VERSION}-#{RUBY
RECOMMENDED_LLVM = 2326
RECOMMENDED_GCC_40 = (MACOS_VERSION >= 10.6) ? 5494 : 5493
RECOMMENDED_GCC_42 = (MACOS_VERSION >= 10.6) ? 5664 : 5577
+
+require 'fileutils'
+module Homebrew extend self
+ include FileUtils
+end
+
+FORMULA_META_FILES = %w[README README.md ChangeLog COPYING LICENSE LICENCE COPYRIGHT AUTHORS]
+PLEASE_REPORT_BUG = "#{Tty.white}Please report this bug at #{Tty.em}\nhttps://github.com/mxcl/homebrew/wiki/new-issue#{Tty.reset}"
diff --git a/Library/Homebrew/install.rb b/Library/Homebrew/install.rb
index f3ca8d2bd..6b338ea83 100755
--- a/Library/Homebrew/install.rb
+++ b/Library/Homebrew/install.rb
@@ -30,7 +30,7 @@ at_exit do
require 'fileutils'
require 'hardware'
require 'keg'
- require 'brew.h.rb'
+ require 'compatibility'
ENV.extend(HomebrewEnvExtension)
ENV.setup_build_environment
@@ -121,7 +121,8 @@ def install f
ohai 'Finishing up' if ARGV.verbose?
begin
- clean f
+ require 'cleaner'
+ Cleaner.new f
rescue Exception => e
opoo "The cleaning step did not complete successfully"
puts "Still, the installation was successful, so we will link it into your prefix"
diff --git a/Library/Homebrew/keg.rb b/Library/Homebrew/keg.rb
index e278a5ce7..22bf40bc3 100644
--- a/Library/Homebrew/keg.rb
+++ b/Library/Homebrew/keg.rb
@@ -1,3 +1,5 @@
+require 'extend/pathname'
+
class Keg <Pathname
def initialize path
super path
@@ -5,8 +7,6 @@ class Keg <Pathname
raise "#{to_s} is not a directory" unless directory?
end
- class NotAKegError <RuntimeError; end
-
# if path is a file in a keg then this will return the containing Keg object
def self.for path
path = path.realpath
diff --git a/Library/Homebrew/test/test_ENV.rb b/Library/Homebrew/test/test_ENV.rb
index 1cd716dfd..da3a9d6af 100644
--- a/Library/Homebrew/test/test_ENV.rb
+++ b/Library/Homebrew/test/test_ENV.rb
@@ -1,6 +1,5 @@
require 'testing_env'
require 'utils'
-require 'brew.h'
require 'extend/ENV'
ENV.extend(HomebrewEnvExtension)
diff --git a/Library/Homebrew/test/test_bucket.rb b/Library/Homebrew/test/test_bucket.rb
index 8492b4929..086297dd2 100644
--- a/Library/Homebrew/test/test_bucket.rb
+++ b/Library/Homebrew/test/test_bucket.rb
@@ -5,7 +5,6 @@ ARGV.extend(HomebrewArgvExtension)
require 'test/testball'
require 'utils'
-require 'brew.h'
class MockFormula <Formula
def initialize url
@@ -79,19 +78,24 @@ class BeerTasting < Test::Unit::TestCase
# end
def test_brew_h
+ require 'cmd/info'
+ require 'cmd/prune'
+ require 'cleaner'
+
nostdout do
assert_nothing_raised do
f=TestBall.new
- make f.url
- info f
- clean f
- prune
+ Homebrew.info_formula f
+ Cleaner.new f
+ Homebrew.prune
#TODO test diy function too
end
end
end
def test_brew_cleanup
+ require 'cmd/cleanup'
+
f1=TestBall.new
f1.instance_eval { @version = "0.1" }
f2=TestBall.new
@@ -110,7 +114,7 @@ class BeerTasting < Test::Unit::TestCase
assert f3.installed?
nostdout do
- cleanup f3
+ Homebrew.cleanup_formula f3
end
assert !f1.installed?
@@ -175,4 +179,16 @@ class BeerTasting < Test::Unit::TestCase
assert_equal 'foo-0.1', foo1.stem
assert_equal '0.1', foo1.version
end
+
+ class MockMockFormula < Struct.new(:name); end
+
+ def test_formula_equality
+ f = MockFormula.new('http://example.com/test-0.1.tgz')
+ g = MockMockFormula.new('test')
+
+ assert f == f
+ assert f == g
+ assert f.eql? f
+ assert (not (f.eql? g))
+ end
end
diff --git a/Library/Homebrew/test/test_external_deps.rb b/Library/Homebrew/test/test_external_deps.rb
index 2b96e7678..30b3540d9 100644
--- a/Library/Homebrew/test/test_external_deps.rb
+++ b/Library/Homebrew/test/test_external_deps.rb
@@ -3,38 +3,12 @@ require 'testing_env'
require 'extend/ARGV' # needs to be after test/unit to avoid conflict with OptionsParser
ARGV.extend(HomebrewArgvExtension)
+require 'extend/string'
require 'test/testball'
require 'formula_installer'
require 'utils'
-# Custom formula installer that checks deps but does not
-# run the install code. We also override the external dep
-# install messages, so for instance the Python check doesnt
-# look for the pip formula (which isn't avaialble in test
-# mode.)
-class DontActuallyInstall < FormulaInstaller
- def install_private f ; end
-
- def pyerr dep
- "Python module install message."
- end
-
- def plerr dep
- "Perl module install message."
- end
-
- def rberr dep
- "Ruby module install message."
- end
-
- def jrberr dep
- "JRuby module install message."
- end
-end
-
-
-
class BadPerlBall <TestBall
depends_on "notapackage" => :perl
@@ -102,14 +76,14 @@ end
class ExternalDepsTests < Test::Unit::TestCase
def check_deps_fail f
- assert_raises(RuntimeError) do
- DontActuallyInstall.new.install f.new
+ assert_raises(UnsatisfiedExternalDependencyError) do
+ FormulaInstaller.check_external_deps f.new
end
end
def check_deps_pass f
assert_nothing_raised do
- DontActuallyInstall.new.install f.new
+ FormulaInstaller.check_external_deps f.new
end
end
diff --git a/Library/Homebrew/test/test_formula.rb b/Library/Homebrew/test/test_formula.rb
index aa545f6d4..fd3987168 100644
--- a/Library/Homebrew/test/test_formula.rb
+++ b/Library/Homebrew/test/test_formula.rb
@@ -5,7 +5,6 @@ ARGV.extend(HomebrewArgvExtension)
require 'test/testball'
require 'utils'
-require 'brew.h'
class MostlyAbstractFormula <Formula
diff --git a/Library/Homebrew/test/test_formula_install.rb b/Library/Homebrew/test/test_formula_install.rb
index db1a2b103..059d7656b 100644
--- a/Library/Homebrew/test/test_formula_install.rb
+++ b/Library/Homebrew/test/test_formula_install.rb
@@ -26,7 +26,7 @@ class ConfigureTests < Test::Unit::TestCase
f=ConfigureFails.new
begin
f.brew { f.install }
- rescue ExecutionError => e
+ rescue BuildError => e
assert e.was_running_configure?
end
end
diff --git a/Library/Homebrew/test/test_updater.rb b/Library/Homebrew/test/test_updater.rb
index 1d733560b..5659f9c67 100644
--- a/Library/Homebrew/test/test_updater.rb
+++ b/Library/Homebrew/test/test_updater.rb
@@ -7,7 +7,7 @@ ARGV.extend(HomebrewArgvExtension)
require 'formula'
require 'utils'
-require 'update'
+require 'cmd/update'
class RefreshBrewMock < RefreshBrew
def in_prefix_expect(expect, returns = '')
diff --git a/Library/Homebrew/test/testing_env.rb b/Library/Homebrew/test/testing_env.rb
index ffc8b3003..0933185bb 100644
--- a/Library/Homebrew/test/testing_env.rb
+++ b/Library/Homebrew/test/testing_env.rb
@@ -8,6 +8,7 @@ ABS__FILE__=File.expand_path(__FILE__)
$:.push(File.expand_path(__FILE__+'/../..'))
require 'extend/pathname'
+require 'exceptions'
# these are defined in global.rb, but we don't want to break our actual
# homebrew tree, and we do want to test everything :)
@@ -26,4 +27,9 @@ at_exit { HOMEBREW_PREFIX.parent.rmtree }
# Test fixtures and files can be found relative to this path
TEST_FOLDER = Pathname.new(ABS__FILE__).parent.realpath
+require 'fileutils'
+module Homebrew extend self
+ include FileUtils
+end
+
require 'test/unit' # must be after at_exit
diff --git a/Library/Homebrew/utils.rb b/Library/Homebrew/utils.rb
index de16df994..6dedf764b 100644
--- a/Library/Homebrew/utils.rb
+++ b/Library/Homebrew/utils.rb
@@ -1,38 +1,3 @@
-class ExecutionError <RuntimeError
- attr :exit_status
- attr :command
-
- def initialize cmd, args = [], es = nil
- @command = cmd
- super "Failure while executing: #{cmd} #{pretty(args)*' '}"
- @exit_status = es.exitstatus rescue 1
- end
-
- def was_running_configure?
- @command == './configure'
- end
-
- private
-
- def pretty args
- args.collect do |arg|
- if arg.to_s.include? ' '
- "'#{ arg.gsub "'", "\\'" }'"
- else
- arg
- end
- end
- end
-end
-
-class BuildError <ExecutionError
- attr :env
-
- def initialize cmd, args = [], es = nil
- super
- @env = ENV.to_hash
- end
-end
class Tty
class <<self
@@ -112,7 +77,10 @@ end
# Kernel.system but with exceptions
def safe_system cmd, *args
- raise ExecutionError.new(cmd, args, $?) unless Homebrew.system(cmd, *args)
+ unless Homebrew.system cmd, *args
+ args = args.map{ |arg| arg.gsub " ", "\\ " } * " "
+ raise "Failure while executing: #{cmd} #{args}"
+ end
end
# prints no output
@@ -263,28 +231,97 @@ def nostdout
end
end
-def dump_build_env env
- puts "\"--use-llvm\" was specified" if ARGV.include? '--use-llvm'
+module MacOS extend self
+ def gcc_42_build_version
+ `/usr/bin/gcc-4.2 -v 2>&1` =~ /build (\d{4,})/
+ if $1
+ $1.to_i
+ elsif system "/usr/bin/which gcc"
+ # Xcode 3.0 didn't come with gcc-4.2
+ # We can't change the above regex to use gcc because the version numbers
+ # are different and thus, not useful.
+ # FIXME I bet you 20 quid this causes a side effect — magic values tend to
+ 401
+ else
+ nil
+ end
+ end
- %w[ CC CXX LD ].each do |k|
- value = env[k]
- if value
- results = value
- if File.exists? value and File.symlink? value
- target = Pathname.new(value)
- results += " => #{target.realpath}"
- end
- puts "#{k}: #{results}"
+ def gcc_40_build_version
+ `/usr/bin/gcc-4.0 -v 2>&1` =~ /build (\d{4,})/
+ if $1
+ $1.to_i
+ else
+ nil
end
end
- %w[ CFLAGS CXXFLAGS CPPFLAGS LDFLAGS MACOSX_DEPLOYMENT_TARGET MAKEFLAGS PKG_CONFIG_PATH
- HOMEBREW_DEBUG HOMEBREW_VERBOSE HOMEBREW_USE_LLVM HOMEBREW_SVN ].each do |k|
- value = env[k]
- puts "#{k}: #{value}" if value
+ def llvm_build_version
+ if MACOS_VERSION >= 10.6
+ xcode_path = `/usr/bin/xcode-select -print-path`.chomp
+ return nil if xcode_path.empty?
+ `#{xcode_path}/usr/bin/llvm-gcc -v 2>&1` =~ /LLVM build (\d{4,})/
+ $1.to_i
+ end
end
-end
def x11_installed?
Pathname.new('/usr/X11/lib/libpng.dylib').exist?
-end \ No newline at end of file
+end
+
+ def macports_or_fink_installed?
+ # See these issues for some history:
+ # http://github.com/mxcl/homebrew/issues/#issue/13
+ # http://github.com/mxcl/homebrew/issues/#issue/41
+ # http://github.com/mxcl/homebrew/issues/#issue/48
+
+ %w[port fink].each do |ponk|
+ path = `/usr/bin/which -s #{ponk}`
+ return ponk unless path.empty?
+ end
+
+ # we do the above check because macports can be relocated and fink may be
+ # able to be relocated in the future. This following check is because if
+ # fink and macports are not in the PATH but are still installed it can
+ # *still* break the build -- because some build scripts hardcode these paths:
+ %w[/sw/bin/fink /opt/local/bin/port].each do |ponk|
+ return ponk if File.exist? ponk
+ end
+
+ # finally, sometimes people make their MacPorts or Fink read-only so they
+ # can quickly test Homebrew out, but still in theory obey the README's
+ # advise to rename the root directory. This doesn't work, many build scripts
+ # error out when they try to read from these now unreadable directories.
+ %w[/sw /opt/local].each do |path|
+ path = Pathname.new(path)
+ return path if path.exist? and not path.readable?
+ end
+
+ false
+ end
+end
+
+module GitHub extend self
+ def issues_for_formula name
+ # bit basic as depends on the issue at github having the exact name of the
+ # formula in it. Which for stuff like objective-caml is unlikely. So we
+ # really should search for aliases too.
+
+ name = f.name if Formula === name
+
+ require 'open-uri'
+ require 'yaml'
+
+ issues = []
+
+ open "http://github.com/api/v2/yaml/issues/search/mxcl/homebrew/open/#{name}" do |f|
+ YAML::load(f.read)['issues'].each do |issue|
+ issues << 'http://github.com/mxcl/homebrew/issues/#issue/%s' % issue['number']
+ end
+ end
+
+ issues
+ rescue
+ []
+ end
+end
diff --git a/bin/brew b/bin/brew
index 4ec64f0a1..645e933e4 100755
--- a/bin/brew
+++ b/bin/brew
@@ -38,313 +38,48 @@ if MACOS_VERSION < 10.5
abort "Homebrew requires Leopard or higher. For Tiger support, see:\nhttp://github.com/sceaga/homebrew/tree/tiger"
end
-def dump_config
- require 'hardware'
- sha = `cd #{HOMEBREW_REPOSITORY} && git rev-parse --verify HEAD 2> /dev/null`.chomp
- sha = "(none)" if sha.empty?
- bits = Hardware.bits
- cores = Hardware.cores_as_words
- kernel_arch = `uname -m`.chomp
- system_ruby = Pathname.new("/usr/bin/ruby")
-
- llvm, llvm_msg = _compiler_recommendation llvm_build, RECOMMENDED_LLVM
- gcc_42, gcc_42_msg = _compiler_recommendation gcc_42_build, RECOMMENDED_GCC_42
- gcc_40, gcc_40_msg = _compiler_recommendation gcc_40_build, RECOMMENDED_GCC_40
- xcode = xcode_version || "?"
-
- puts <<-EOS
-HOMEBREW_VERSION: #{HOMEBREW_VERSION}
-HEAD: #{sha}
-HOMEBREW_PREFIX: #{HOMEBREW_PREFIX}
-HOMEBREW_CELLAR: #{HOMEBREW_CELLAR}
-HOMEBREW_REPOSITORY: #{HOMEBREW_REPOSITORY}
-HOMEBREW_LIBRARY_PATH: #{HOMEBREW_LIBRARY_PATH}
-Hardware: #{cores}-core #{bits}-bit #{Hardware.intel_family}
-OS X: #{MACOS_FULL_VERSION}
-Kernel Architecture: #{kernel_arch}
-Ruby: #{RUBY_VERSION}-#{RUBY_PATCHLEVEL}
-/usr/bin/ruby => #{system_ruby.realpath}
-Xcode: #{xcode}
-GCC-4.0: #{gcc_40 ? "build #{gcc_40}" : "N/A"} #{gcc_42_msg}
-GCC-4.2: #{gcc_42 ? "build #{gcc_42}" : "N/A"} #{gcc_40_msg}
-LLVM: #{llvm ? "build #{llvm}" : "N/A" } #{llvm_msg}
-MacPorts or Fink? #{macports_or_fink_installed?}
-X11 installed? #{x11_installed?}
-EOS
+def require? path
+ require path.to_s.chomp
+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
end
begin
- require 'brew.h'
-
- case arg = ARGV.shift
- when '--cache'
- if ARGV.named.empty?
- puts HOMEBREW_CACHE
- else
- puts ARGV.formulae.collect {|f| f.cached_download}
- end
- when '--prefix'
- if ARGV.named.empty?
- puts HOMEBREW_PREFIX
- else
- puts ARGV.formulae.collect {|f| f.prefix}
- end
- when '--repository'
- puts HOMEBREW_REPOSITORY
- when '--cellar'
- if ARGV.named.empty?
- puts HOMEBREW_CELLAR
- else
- puts ARGV.formulae.collect {|f| HOMEBREW_CELLAR+f.name}
- end
- when '--config'
- dump_config
- when '--env'
- require 'hardware'
- require 'extend/ENV'
- ENV.extend(HomebrewEnvExtension)
- ENV.setup_build_environment
- dump_build_env ENV
-
- when 'home', 'homepage'
- if ARGV.named.empty?
- exec "open", HOMEBREW_WWW
- else
- exec "open", *ARGV.formulae.collect {|f| f.homepage}
- end
-
- when 'ls', 'list'
- if ARGV.flag? '--unbrewed'
- dirs = HOMEBREW_PREFIX.children.select { |pn| pn.directory? }.collect { |pn| pn.basename.to_s }
- dirs -= ['Library', 'Cellar', '.git']
- Dir.chdir HOMEBREW_PREFIX
- exec 'find', *dirs + %w[-type f ( ! -iname .ds_store ! -iname brew )]
- elsif ARGV.flag? '--versions'
- if ARGV.named.empty?
- to_list = HOMEBREW_CELLAR.children.select { |pn| pn.directory? }
- else
- to_list = ARGV.named.collect { |n| HOMEBREW_CELLAR+n }.select { |pn| pn.exist? }
- end
- to_list.each do |d|
- versions = d.children.select { |pn| pn.directory? }.collect { |pn| pn.basename.to_s }
- puts "#{d.basename} #{versions *' '}"
- end
- elsif ARGV.named.empty?
- ENV['CLICOLOR']=nil
- exec 'ls', *ARGV.options_only<<HOMEBREW_CELLAR if HOMEBREW_CELLAR.exist?
- elsif ARGV.verbose? or not $stdout.tty?
- exec "find", *ARGV.kegs+%w[-not -type d -print]
- else
- ARGV.kegs.each { |keg| PrettyListing.new keg }
- end
-
- when 'search', '-S'
- if ARGV.include? '--macports'
- exec "open", "http://www.macports.org/ports.php?by=name&substr=#{ARGV.next}"
- elsif ARGV.include? '--fink'
- exec "open", "http://pdb.finkproject.org/pdb/browse.php?summary=#{ARGV.next}"
- end
-
- check_for_blacklisted_formula(ARGV.named)
- puts_columns search_brews(ARGV.first)
-
- when 'edit'
- if ARGV.named.empty?
- # EDITOR isn't a good fit here, we need a GUI client that actually has
- # a UI for projects, so apologies if this wasn't what you expected,
- # please improve it! :)
- exec 'mate', *Dir["#{HOMEBREW_REPOSITORY}/Library/*"]<<
- "#{HOMEBREW_REPOSITORY}/bin/brew"<<
- "#{HOMEBREW_REPOSITORY}/README.md"
- else
- require 'formula'
- # Don't use ARGV.formulae as that will throw if the file doesn't parse
- paths = ARGV.named.collect do |name|
- path = Formula.path(Formula.resolve_alias(name))
- unless File.exist? path
- raise FormulaUnavailableError, name
- else
- path
- end
- end
- exec_editor(*paths)
- end
-
- when 'up', 'update'
- abort "Please `brew install git' first." unless system "/usr/bin/which -s git"
-
- require 'update'
- updater = RefreshBrew.new
- unless updater.update_from_masterbrew!
- puts "Already up-to-date."
- else
- updater.report
- end
-
- when 'ln', 'link'
- ARGV.kegs.each {|keg| puts "#{keg.link} links created for #{keg}"}
-
- when 'unlink'
- ARGV.kegs.each {|keg| puts "#{keg.unlink} links removed for #{keg}"}
-
- when 'rm', 'uninstall', 'remove'
- if ARGV.flag? "--force"
- require 'formula'
- ARGV.formulae.each do |f|
- formula_cellar = f.prefix.parent
- next unless File.exist? formula_cellar
- puts "Uninstalling #{f.name}..."
- formula_cellar.children do |k|
- keg = Keg.new(k)
- keg.unlink
- end
-
- formula_cellar.rmtree
- end
- else
- begin
- ARGV.kegs.each do |keg|
- puts "Uninstalling #{keg}..."
- keg.unlink
- keg.uninstall
- end
- rescue MultipleVersionsInstalledError => e
- onoe e
- puts "Use `brew remove --force #{e.name}` to remove all versions."
- end
- end
-
- when 'prune'
- prune
-
- when 'create'
- if ARGV.include? '--macports'
- exec "open", "http://www.macports.org/ports.php?by=name&substr=#{ARGV.next}"
- elsif ARGV.include? '--fink'
- exec "open", "http://pdb.finkproject.org/pdb/browse.php?summary=#{ARGV.next}"
- elsif ARGV.named.empty?
- raise UsageError
- else
- exec_editor(*ARGV.named.collect {|name| make name})
- end
-
- when 'diy', 'configure'
- puts diy
-
- when 'info', 'abv'
- if ARGV.named.empty?
- if ARGV.include? "--all"
- require 'formula'
- Formula.all.each do |f|
- info f
- puts '---'
- end
- else
- puts `ls #{HOMEBREW_CELLAR} | wc -l`.strip+" kegs, "+HOMEBREW_CELLAR.abv
- end
- elsif ARGV[0][0..6] == 'http://' or ARGV[0][0..7] == 'https://' or ARGV[0][0..5] == 'ftp://'
- path = Pathname.new(ARGV.shift)
- /(.*?)[-_.]?#{path.version}/.match path.basename
- unless $1.to_s.empty?
- name = $1
- else
- name = path.stem
- end
- puts "#{name} #{path.version}"
- else
- ARGV.formulae.each{ |f| info f }
- end
-
- when 'cleanup'
- if ARGV.named.empty?
- require 'formula'
- HOMEBREW_CELLAR.children.each do |rack|
- begin
- cleanup(rack.basename.to_s) if rack.directory?
- rescue FormulaUnavailableError => e
- opoo "Formula not found for #{e.name}"
- end
- end
- prune # seems like a good time to do some additional cleanup
- else
- ARGV.named.each { |name| cleanup name}
- end
-
- when 'install'
- check_for_blacklisted_formula(ARGV.named)
- brew_install
-
- when 'log'
- Dir.chdir HOMEBREW_REPOSITORY
- args = ARGV.options_only
- args += ARGV.formulae.map{ |formula| formula.path } unless ARGV.named.empty?
- exec "git", "log", *args
-
- # For each formula given, show which other formulas depend on it.
- # We only go one level up, ie. direct dependencies.
- when 'uses'
- uses = ARGV.formulae.map{ |f| Formula.all.select{ |ff| ff.deps.include? f.name }.map{|f| f.name} }.flatten.uniq
- if ARGV.include? "--installed"
- uses = uses.select { |f| f = HOMEBREW_CELLAR+f; f.directory? and not f.subdirs.empty? }
- end
- puts uses.sort
-
- when 'deps'
- if ARGV.include?('--all')
- require 'formula'
- Formula.all.each do |f|
- puts "#{f.name}:#{f.deps.join(' ')}"
- end
- elsif ARGV.include?("-1") or ARGV.include?("--1")
- puts ARGV.formulae.map {|f| f.deps or []}.flatten.uniq.sort
- else
- require 'formula_installer'
- puts ARGV.formulae.map {|f| FormulaInstaller.expand_deps(f).map {|f| f.name} }.flatten.uniq.sort
- end
-
- when 'cat'
- Dir.chdir HOMEBREW_REPOSITORY
- exec "cat", ARGV.formulae.first.path, *ARGV.options_only
-
- when 'outdated'
- outdated_brews.each do |keg, name, version|
- if $stdout.tty? and not ARGV.flag? '--quiet'
- versions = keg.cd{ Dir['*'] }.join(', ')
- puts "#{name} (#{versions} < #{version})"
- else
- puts name
- end
+ aliases = {'ls' => :list,
+ 'homepage' => :home,
+ '-S' => :search,
+ 'up' => :update,
+ 'ln' => :link,
+ 'rm' => :uninstall,
+ 'remove' => :uninstall,
+ 'configure' => :diy,
+ 'abv' => :info,
+ 'dr' => :doctor,
+ '--repo' => '--repository'}
+
+ cmd = ARGV.shift
+ cmd = aliases[cmd] if aliases[cmd]
+
+ # Add example external commands to PATH before checking.
+ ENV['PATH'] += ":#{HOMEBREW_REPOSITORY}/Library/Contributions/examples"
+
+ if system "/usr/bin/which -s brew-#{cmd}"
+ %w[CACHE CELLAR LIBRARY_PATH PREFIX REPOSITORY].each do |e|
+ ENV["HOMEBREW_#{e}"] = eval "HOMEBREW_#{e}"
end
-
- when 'doctor', 'dr'
- require 'brew_doctor'
- brew_doctor
-
+ exec "brew-#{cmd}", *ARGV
+ elsif require? `/usr/bin/which brew-#{cmd}.rb`
+ exit 0
+ elsif require? HOMEBREW_REPOSITORY/"Library/Homebrew/cmd"/cmd
+ Homebrew.send cmd.to_s.gsub('-', '_')
else
- # Add example external commands to PATH before checking.
- ENV['PATH'] += ":#{HOMEBREW_REPOSITORY}/Library/Contributions/examples"
-
- # Check for an external shell command
- if system "/usr/bin/which -s brew-#{arg}"
- # Add some Homebrew vars to the ENV
- %w(CACHE CELLAR LIBRARY_PATH PREFIX REPOSITORY).each do |e|
- ENV["HOMEBREW_#{e}"] = eval("HOMEBREW_#{e}")
- end
- exec("brew-#{arg}", *ARGV)
- end
-
- # Check for an external ruby command
- external_rb = `/usr/bin/which brew-#{arg}.rb`.chomp
- unless external_rb.empty?
- require external_rb
- exit 0
- end
-
# Check for git commands
- if %w(branch checkout pull push rebase reset).include? arg
- onoe "Unknown command '#{arg}' (did you mean 'git #{arg}'?)"
+ if %w[branch checkout pull push rebase reset].include? cmd
+ onoe "Unknown command: #{cmd} (did you mean `git #{cmd}'?)"
else
- onoe "Unknown command '#{arg}'"
+ onoe "Unknown command: #{cmd}"
end
end
@@ -362,24 +97,28 @@ rescue Interrupt => e
puts # seemingly a newline is typical
exit 130
rescue BuildError => e
+ require 'cmd/--config'
+ require 'cmd/--env'
+
e.backtrace[1] =~ %r{Library/Formula/(.+)\.rb:(\d+)}
formula_name = $1
error_line = $2
+
puts "Exit status: #{e.exit_status}"
puts
puts "http://github.com/mxcl/homebrew/blob/master/Library/Formula/#{formula_name}.rb#L#{error_line}"
puts
ohai "Environment"
- dump_config
+ puts Homebrew.config_s
puts
ohai "Build Flags"
- dump_build_env e.env
+ Homebrew.dump_build_env e.env
onoe e
puts PLEASE_REPORT_BUG
# this feature can be slow (depends on network conditions and if github is up)
# so ideally we'd show feedback, eg. "checking for existing issues..." and
# then replace that string with the following when the github api returns
- issues = issues_for_formula(formula_name)
+ issues = GitHub.issues_for_formula formula_name
puts "These existing issues may help you:", *issues unless issues.empty?
if e.was_running_configure?
puts "It looks like an autotools configure failed."