aboutsummaryrefslogtreecommitdiffstats
path: root/Library/Homebrew/cmd
diff options
context:
space:
mode:
authorMax Howell2010-09-11 20:22:54 +0100
committerAdam Vandenberg2011-03-12 11:55:02 -0800
commit768910283a40afc2f76ef196d1464f0bbb2349cd (patch)
tree0befe8fb3c3d8e967a34a29b11b6d85ecbfcbc9b /Library/Homebrew/cmd
parent97f654701d17c8605632a0d77570a2d9c6893ddf (diff)
downloadbrew-768910283a40afc2f76ef196d1464f0bbb2349cd.tar.bz2
Refactor the brew command into one file per command
The code was sucking. To the extent that maintenance was hard. It's a lot easier to work with code that is sensibly split at sensible boundaries. So now it is more like that. But the refactor is minimal. Because we don't want you to have more merge hell than absolutely necessary. If you merge you will need to pay attention to brew.h.rb (as it is deleted) and bin/brew (as command logic is gone). It will be painful, but you will just have to help git out by moving any changes around manually. Note compatibility.rb. It ensures that any function renames or removals don't break anything. We're pretty serious about backwards compatibility. And that's because we encourage you to hack around with the innards. And we couldn't do that if we would then just make stuff disappear behind your back.
Diffstat (limited to 'Library/Homebrew/cmd')
-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.rb633
-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.rb159
-rw-r--r--Library/Homebrew/cmd/uses.rb25
26 files changed, 1660 insertions, 0 deletions
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/cmd/doctor.rb b/Library/Homebrew/cmd/doctor.rb
new file mode 100644
index 000000000..bad3a5dc0
--- /dev/null
+++ b/Library/Homebrew/cmd/doctor.rb
@@ -0,0 +1,633 @@
+class Volumes
+ def initialize
+ @volumes = []
+ raw_mounts=`mount`
+ raw_mounts.split("\n").each do |line|
+ case line
+ when /^(.+) on (\S+) \(/
+ @volumes << [$1, $2]
+ end
+ end
+ # Sort volumes by longest path prefix first
+ @volumes.sort! {|a,b| b[1].length <=> a[1].length}
+ end
+
+ def which path
+ @volumes.each_index do |i|
+ vol = @volumes[i]
+ return i if is_prefix?(vol[1], path)
+ end
+
+ return -1
+ end
+end
+
+
+def is_prefix? prefix, longer_string
+ p = prefix.to_s
+ longer_string.to_s[0,p.length] == p
+end
+
+# Installing MacGPG2 interferes with Homebrew in a big way
+# http://sourceforge.net/projects/macgpg2/files/
+def check_for_macgpg2
+ if File.exist? "/Applications/start-gpg-agent.app" or
+ File.exist? "/Library/Receipts/libiconv1.pkg"
+ puts <<-EOS.undent
+ If you have installed MacGPG2 via the package installer, several other
+ checks in this script will turn up problems, such as stray .dylibs in
+ /usr/local and permissions issues with share and man in /usr/local/.
+
+ EOS
+ end
+end
+
+def check_for_stray_dylibs
+ unbrewed_dylibs = Dir['/usr/local/lib/*.dylib'].select { |f| File.file? f and not File.symlink? f }
+
+ # Dylibs which are generally OK should be added to this list,
+ # with a short description of the software they come with.
+ white_list = {
+ "libfuse.2.dylib" => "MacFuse",
+ "libfuse_ino64.2.dylib" => "MacFuse"
+ }
+
+ bad_dylibs = unbrewed_dylibs.reject {|d| white_list.key? File.basename(d) }
+ return if bad_dylibs.empty?
+
+ opoo "Unbrewed dylibs were found in /usr/local/lib"
+ puts <<-EOS.undent
+ You have unbrewed dylibs in /usr/local/lib. If you didn't put them there on purpose,
+ they could cause problems when building Homebrew formulae.
+
+ Unexpected dylibs (delete if they are no longer needed):
+ EOS
+ puts *bad_dylibs.collect { |f| " #{f}" }
+ puts
+end
+
+def check_for_x11
+ unless x11_installed?
+ opoo "X11 not installed."
+ puts <<-EOS.undent
+ You don't have X11 installed as part of your Xcode installation.
+ This isn't required for all formulae, but is expected by some.
+
+ EOS
+ end
+end
+
+def check_for_nonstandard_x11
+ return unless File.exists? '/usr/X11'
+ x11 = Pathname.new('/usr/X11')
+ if x11.symlink?
+ puts <<-EOS.undent
+ "/usr/X11" was found, but it is a symlink to:
+ #{x11.resolved_path}
+
+ Homebrew's X11 support has only be tested with Apple's X11.
+ In particular, "XQuartz" and "XDarwin" are not known to be compatible.
+
+ EOS
+ end
+end
+
+def check_for_other_package_managers
+ if macports_or_fink_installed?
+ puts <<-EOS.undent
+ You have Macports or Fink installed. This can cause trouble.
+ You don't have to uninstall them, but you may like to try temporarily
+ moving them away, eg.
+
+ sudo mv /opt/local ~/macports
+
+ EOS
+ end
+end
+
+def check_gcc_versions
+ gcc_42 = gcc_42_build
+ gcc_40 = gcc_40_build
+
+ if gcc_42 == nil
+ puts <<-EOS.undent
+ We couldn't detect gcc 4.2.x. Some formulae require this compiler.
+
+ EOS
+ elsif gcc_42 < RECOMMENDED_GCC_42
+ puts <<-EOS.undent
+ Your gcc 4.2.x version is older than the recommended version. It may be advisable
+ to upgrade to the latest release of Xcode.
+
+ EOS
+ end
+
+ if gcc_40 == nil
+ puts <<-EOS.undent
+ We couldn't detect gcc 4.0.x. Some formulae require this compiler.
+
+ EOS
+ elsif gcc_40 < RECOMMENDED_GCC_40
+ puts <<-EOS.undent
+ Your gcc 4.0.x version is older than the recommended version. It may be advisable
+ to upgrade to the latest release of Xcode.
+
+ EOS
+ end
+end
+
+def check_cc_symlink
+ which_cc = Pathname.new('/usr/bin/cc').realpath.basename.to_s
+ if which_cc == "llvm-gcc-4.2"
+ puts <<-EOS.undent
+ You changed your cc to symlink to llvm.
+ This bypasses LLVM checks, and some formulae may mysteriously fail to work.
+ You may want to change /usr/bin/cc to point back at gcc.
+
+ To force Homebrew to use LLVM, you can set the "HOMEBREW_LLVM" environmental
+ variable, or pass "--use-llvm" to "brew install".
+
+ EOS
+ end
+end
+
+def __check_subdir_access base
+ target = HOMEBREW_PREFIX+base
+ return unless target.exist?
+
+ cant_read = []
+
+ target.find do |d|
+ next unless d.directory?
+ cant_read << d unless d.writable?
+ end
+
+ cant_read.sort!
+ if cant_read.length > 0
+ puts <<-EOS.undent
+ Some folders in #{target} aren't writable.
+ This can happen if you "sudo make install" software that isn't managed
+ by Homebrew. If a brew tries to add locale information to one of these
+ folders, then the install will fail during the link step.
+ You should probably `chown` them:
+
+ EOS
+ puts *cant_read.collect { |f| " #{f}" }
+ puts
+ end
+end
+
+def check_access_share_locale
+ __check_subdir_access 'share/locale'
+end
+
+def check_access_share_man
+ __check_subdir_access 'share/man'
+end
+
+def check_access_pkgconfig
+ # If PREFIX/lib/pkgconfig already exists, "sudo make install" of
+ # non-brew installed software may cause installation failures.
+ pkgconfig = HOMEBREW_PREFIX+'lib/pkgconfig'
+ return unless pkgconfig.exist?
+
+ unless pkgconfig.writable?
+ puts <<-EOS.undent
+ #{pkgconfig} isn't writable.
+ This can happen if you "sudo make install" software that isn't managed
+ by Homebrew. If a brew tries to write a .pc file to this folder, the
+ install will fail during the link step.
+
+ You should probably `chown` #{pkgconfig}
+
+ EOS
+ end
+end
+
+def check_access_include
+ # Installing MySQL manually (for instance) can chown include to root.
+ include_folder = HOMEBREW_PREFIX+'include'
+ return unless include_folder.exist?
+
+ unless include_folder.writable?
+ puts <<-EOS.undent
+ #{include_folder} isn't writable.
+ This can happen if you "sudo make install" software that isn't managed
+ by Homebrew. If a brew tries to write a header file to this folder, the
+ install will fail during the link step.
+
+ You should probably `chown` #{include_folder}
+
+ EOS
+ end
+end
+
+def check_access_etc
+ etc_folder = HOMEBREW_PREFIX+'etc'
+ return unless etc_folder.exist?
+
+ unless etc_folder.writable?
+ puts <<-EOS.undent
+ #{etc_folder} isn't writable.
+ This can happen if you "sudo make install" software that isn't managed
+ by Homebrew. If a brew tries to write a file to this folder, the install
+ will fail during the link step.
+
+ You should probably `chown` #{etc_folder}
+
+ EOS
+ end
+end
+
+def check_usr_bin_ruby
+ if /^1\.9/.match RUBY_VERSION
+ puts <<-EOS.undent
+ Ruby version #{RUBY_VERSION} is unsupported.
+ Homebrew is developed and tested on Ruby 1.8.x, and may not work correctly
+ on Ruby 1.9.x. Patches are accepted as long as they don't break on 1.8.x.
+
+ EOS
+ end
+end
+
+def check_homebrew_prefix
+ unless HOMEBREW_PREFIX.to_s == '/usr/local'
+ puts <<-EOS.undent
+ You can install Homebrew anywhere you want, but some brews may only work
+ correctly if you install to /usr/local.
+
+ EOS
+ end
+end
+
+def check_user_path
+ seen_prefix_bin = false
+ seen_prefix_sbin = false
+ seen_usr_bin = false
+
+ paths = ENV['PATH'].split(':').collect{|p| File.expand_path p}
+
+ paths.each do |p|
+ if p == '/usr/bin'
+ seen_usr_bin = true
+ unless seen_prefix_bin
+ puts <<-EOS.undent
+ /usr/bin is in your PATH before Homebrew's bin. This means that system-
+ provided programs will be used before Homebrew-provided ones. This is an
+ issue if you install, for instance, Python.
+
+ Consider editing your .bashrc to put:
+ #{HOMEBREW_PREFIX}/bin
+ ahead of /usr/bin in your $PATH.
+
+ EOS
+ end
+ end
+
+ seen_prefix_bin = true if p == "#{HOMEBREW_PREFIX}/bin"
+ seen_prefix_sbin = true if p == "#{HOMEBREW_PREFIX}/sbin"
+ end
+
+ unless seen_prefix_bin
+ puts <<-EOS.undent
+ Homebrew's bin was not found in your path. Some brews depend
+ on other brews that install tools to bin.
+
+ You should edit your .bashrc to add:
+ #{HOMEBREW_PREFIX}/bin
+ to $PATH.
+
+ EOS
+ end
+
+ unless seen_prefix_sbin
+ puts <<-EOS.undent
+ Some brews install binaries to sbin instead of bin, but Homebrew's
+ sbin was not found in your path.
+
+ Consider editing your .bashrc to add:
+ #{HOMEBREW_PREFIX}/sbin
+ to $PATH.
+
+ EOS
+ end
+end
+
+def check_which_pkg_config
+ binary = `/usr/bin/which pkg-config`.chomp
+ return if binary.empty?
+
+ unless binary == "#{HOMEBREW_PREFIX}/bin/pkg-config"
+ puts <<-EOS.undent
+ You have a non-brew 'pkg-config' in your PATH:
+ #{binary}
+
+ `./configure` may have problems finding brew-installed packages using
+ this other pkg-config.
+
+ EOS
+ end
+end
+
+def check_pkg_config_paths
+ binary = `/usr/bin/which pkg-config`.chomp
+ return if binary.empty?
+
+ # Use the debug output to determine which paths are searched
+ pkg_config_paths = []
+
+ debug_output = `pkg-config --debug 2>&1`
+ debug_output.split("\n").each do |line|
+ line =~ /Scanning directory '(.*)'/
+ pkg_config_paths << $1 if $1
+ end
+
+ # Check that all expected paths are being searched
+ unless pkg_config_paths.include? "/usr/X11/lib/pkgconfig"
+ puts <<-EOS.undent
+ Your pkg-config is not checking "/usr/X11/lib/pkgconfig" for packages.
+ Earlier versions of the pkg-config formula did not add this path
+ to the search path, which means that other formula may not be able
+ to find certain dependencies.
+
+ To resolve this issue, re-brew pkg-config with:
+ brew rm pkg-config && brew install pkg-config
+
+ EOS
+ end
+end
+
+def check_for_gettext
+ if %w[lib/libgettextlib.dylib
+ lib/libintl.dylib
+ include/libintl.h ].any? { |f| File.exist? "#{HOMEBREW_PREFIX}/#{f}" }
+ puts <<-EOS.undent
+ gettext was detected in your PREFIX.
+
+ The gettext provided by Homebrew is "keg-only", meaning it does not
+ get linked into your PREFIX by default.
+
+ If you `brew link gettext` then a large number of brews that don't
+ otherwise have a `depends_on 'gettext'` will pick up gettext anyway
+ during the `./configure` step.
+
+ If you have a non-Homebrew provided gettext, other problems will happen
+ especially if it wasn't compiled with the proper architectures.
+
+ EOS
+ end
+end
+
+def check_for_iconv
+ if %w[lib/libiconv.dylib
+ include/iconv.h ].any? { |f| File.exist? "#{HOMEBREW_PREFIX}/#{f}" }
+ puts <<-EOS.undent
+ libiconv was detected in your PREFIX.
+
+ Homebrew doesn't provide a libiconv formula, and expects to link against
+ the system version in /usr/lib.
+
+ If you have a non-Homebrew provided libiconv, many formulae will fail
+ to compile or link, especially if it wasn't compiled with the proper
+ architectures.
+
+ EOS
+ end
+end
+
+def check_for_config_scripts
+ real_cellar = HOMEBREW_CELLAR.realpath
+
+ config_scripts = []
+
+ paths = ENV['PATH'].split(':').collect{|p| File.expand_path p}
+ paths.each do |p|
+ next if ['/usr/bin', '/usr/sbin', '/usr/X11/bin', "#{HOMEBREW_PREFIX}/bin", "#{HOMEBREW_PREFIX}/sbin"].include? p
+ next if p =~ %r[^(#{real_cellar.to_s}|#{HOMEBREW_CELLAR.to_s})]
+
+ configs = Dir["#{p}/*-config"]
+ # puts "#{p}\n #{configs * ' '}" unless configs.empty?
+ config_scripts << [p, configs.collect {|p| File.basename(p)}] unless configs.empty?
+ end
+
+ unless config_scripts.empty?
+ puts <<-EOS.undent
+ Some "config" scripts were found in your path, but not in system or Homebrew folders.
+
+ `./configure` scripts often look for *-config scripts to determine if software packages
+ are installed, and what additional flags to use when compiling and linking.
+
+ Having additional scripts in your path can confuse software installed via Homebrew if
+ the config script overrides a system or Homebrew provided script of the same name.
+
+ EOS
+
+ config_scripts.each do |pair|
+ puts pair[0]
+ puts " " + pair[1] * " "
+ end
+ puts
+ end
+end
+
+def check_for_dyld_vars
+ if ENV['DYLD_LIBRARY_PATH']
+ puts <<-EOS.undent
+ Setting DYLD_LIBARY_PATH can break dynamic linking.
+ You should probably unset it.
+
+ EOS
+ end
+end
+
+def check_for_symlinked_cellar
+ if HOMEBREW_CELLAR.symlink?
+ puts <<-EOS.undent
+ Symlinked Cellars can cause problems.
+ Your Homebrew Cellar is a symlink: #{HOMEBREW_CELLAR}
+ which resolves to: #{HOMEBREW_CELLAR.realpath}
+
+ The recommended Homebrew installations are either:
+ (A) Have Cellar be a real folder inside of your HOMEBREW_PREFIX
+ (B) Symlink "bin/brew" into your prefix, but don't symlink "Cellar".
+
+ Older installations of Homebrew may have created a symlinked Cellar, but this can
+ cause problems when two formula install to locations that are mapped on top of each
+ other during the linking step.
+
+ EOS
+ end
+end
+
+def check_for_multiple_volumes
+ volumes = Volumes.new
+
+ # Find the volumes for the TMP folder & HOMEBREW_CELLAR
+ real_cellar = HOMEBREW_CELLAR.realpath
+
+ tmp_prefix = ENV['HOMEBREW_TEMP'] || '/tmp'
+ tmp=Pathname.new `/usr/bin/mktemp -d #{tmp_prefix}/homebrew-brew-doctor-XXXX`.strip
+ real_temp = tmp.realpath.parent
+
+ where_cellar = volumes.which real_cellar
+ where_temp = volumes.which real_temp
+
+ unless where_cellar == where_temp
+ puts <<-EOS.undent
+ Your Cellar & TEMP folders are on different volumes.
+
+ OS X won't move relative symlinks across volumes unless the target file
+ already exists.
+
+ Brews known to be affected by this are Git and Narwhal.
+
+ You should set the "HOMEBREW_TEMP" environmental variable to a suitable
+ folder on the same volume as your Cellar.
+
+ EOS
+ end
+end
+
+def check_for_git
+ git = `/usr/bin/which git`.chomp
+ if git.empty?
+ puts <<-EOS.undent
+ "Git" was not found in your path.
+
+ Homebrew uses Git for several internal functions, and some formulae
+ use Git checkouts instead of stable tarballs.
+
+ You may want to do:
+ brew install git
+
+ EOS
+ end
+end
+
+def check_for_autoconf
+ which_autoconf = `/usr/bin/which autoconf`.chomp
+ unless (which_autoconf == '/usr/bin/autoconf' or which_autoconf == '/Developer/usr/bin/autoconf')
+ puts <<-EOS.undent
+ You have an "autoconf" in your path blocking the system version at:
+ #{which_autoconf}
+
+ Custom autoconf in general and autoconf 2.66 in particular has issues
+ and will cause some Homebrew formulae to fail.
+
+ EOS
+ end
+end
+
+def __check_linked_brew f
+ links_found = []
+
+ Pathname.new(f.prefix).find do |src|
+ dst=HOMEBREW_PREFIX+src.relative_path_from(f.prefix)
+ next unless dst.symlink?
+
+ dst_points_to = dst.realpath()
+ next unless dst_points_to.to_s == src.to_s
+
+ if src.directory?
+ Find.prune
+ else
+ links_found << dst
+ end
+ end
+
+ return links_found
+end
+
+def check_for_linked_kegonly_brews
+ require 'formula'
+
+ warnings = Hash.new
+
+ Formula.all.each do |f|
+ next unless f.keg_only? and f.installed?
+ links = __check_linked_brew f
+ warnings[f.name] = links unless links.empty?
+ end
+
+ unless warnings.empty?
+ puts <<-EOS.undent
+ Some keg-only formula are linked into the Cellar.
+
+ Linking a keg-only formula, such as gettext, into the cellar with
+ `brew link f` will cause other formulae to detect them during the
+ `./configure` step. This may cause problems when compiling those
+ other formulae.
+
+ Binaries provided by keg-only formulae may override system binaries
+ with other strange results.
+
+ You may wish to `brew unlink` these brews:
+ EOS
+
+ puts *warnings.keys.collect { |f| " #{f}" }
+ end
+end
+
+def check_for_other_vars
+ target_var = ENV['MACOSX_DEPLOYMENT_TARGET']
+ return if target_var.nil? or target_var.empty?
+
+ unless target_var == MACOS_VERSION.to_s
+ puts <<-EOS.undent
+ $MACOSX_DEPLOYMENT_TARGET was set to #{target_var}
+ This is used by Fink, but having it set to a value different from the
+ current system version (#{MACOS_VERSION}) can cause problems, compiling
+ Git for instance, and should probably be removed.
+
+ EOS
+ end
+end
+
+module Homebrew extend self
+def doctor
+ read, write = IO.pipe
+
+ if fork == nil
+ read.close
+ $stdout.reopen write
+
+ check_usr_bin_ruby
+ check_homebrew_prefix
+ check_for_macgpg2
+ check_for_stray_dylibs
+ check_gcc_versions
+ check_cc_symlink
+ check_for_other_package_managers
+ check_for_x11
+ check_for_nonstandard_x11
+ check_access_share_locale
+ check_access_share_man
+ check_access_include
+ check_access_etc
+ check_user_path
+ check_which_pkg_config
+ check_pkg_config_paths
+ check_access_pkgconfig
+ check_for_gettext
+ check_for_config_scripts
+ check_for_dyld_vars
+ check_for_other_vars
+ check_for_symlinked_cellar
+ check_for_multiple_volumes
+ check_for_git
+ check_for_autoconf
+ check_for_linked_kegonly_brews
+
+ exit! 0
+ else
+ write.close
+
+ unless (out = read.read).chomp.empty?
+ puts out
+ else
+ puts "Your OS X is ripe for brewing."
+ puts "Any troubles you may be experiencing are likely purely psychosomatic."
+ 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/cmd/update.rb b/Library/Homebrew/cmd/update.rb
new file mode 100644
index 000000000..32f144c8e
--- /dev/null
+++ b/Library/Homebrew/cmd/update.rb
@@ -0,0 +1,159 @@
+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"
+ CHECKOUT_COMMAND = "git checkout -q master"
+ UPDATE_COMMAND = "git pull #{REPOSITORY_URL} master"
+ REVISION_COMMAND = "git log -l -1 --pretty=format:%H 2> /dev/null"
+ GIT_UP_TO_DATE = "Already up-to-date."
+
+ formula_regexp = 'Library/Formula/(.+?)\.rb'
+ ADDED_FORMULA = %r{^\s+create mode \d+ #{formula_regexp}$}
+ UPDATED_FORMULA = %r{^\s+#{formula_regexp}\s}
+ DELETED_FORMULA = %r{^\s+delete mode \d+ #{formula_regexp}$}
+
+ example_regexp = 'Library/Contributions/examples/([^.\s]+).*'
+ ADDED_EXAMPLE = %r{^\s+create mode \d+ #{example_regexp}$}
+ UPDATED_EXAMPLE = %r{^\s+#{example_regexp}}
+ DELETED_EXAMPLE = %r{^\s+delete mode \d+ #{example_regexp}$}
+
+ attr_reader :added_formulae, :updated_formulae, :deleted_formulae, :initial_revision
+ attr_reader :added_examples, :updated_examples, :deleted_examples
+
+ def initialize
+ @added_formulae, @updated_formulae, @deleted_formulae = [], [], []
+ @added_examples, @updated_examples, @deleted_examples = [], [], []
+ @initial_revision = self.current_revision
+ end
+
+ # Performs an update of the homebrew source. Returns +true+ if a newer
+ # version was available, +false+ if already up-to-date.
+ def update_from_masterbrew!
+ output = ''
+ HOMEBREW_REPOSITORY.cd do
+ if File.directory? '.git'
+ safe_system CHECKOUT_COMMAND
+ else
+ safe_system INIT_COMMAND
+ end
+ output = execute(UPDATE_COMMAND)
+ end
+
+ output.split("\n").reverse.each do |line|
+ case line
+ when ADDED_FORMULA
+ @added_formulae << $1
+ when DELETED_FORMULA
+ @deleted_formulae << $1
+ when UPDATED_FORMULA
+ @updated_formulae << $1 unless @added_formulae.include?($1) or @deleted_formulae.include?($1)
+ when ADDED_EXAMPLE
+ @added_examples << $1
+ when DELETED_EXAMPLE
+ @deleted_examples << $1
+ when UPDATED_EXAMPLE
+ @updated_examples << $1 unless @added_examples.include?($1) or @deleted_examples.include?($1)
+ end
+ end
+ @added_formulae.sort!
+ @updated_formulae.sort!
+ @deleted_formulae.sort!
+ @added_examples.sort!
+ @updated_examples.sort!
+ @deleted_examples.sort!
+
+ output.strip != GIT_UP_TO_DATE
+ end
+
+ def pending_formulae_changes?
+ !@updated_formulae.empty?
+ end
+
+ def pending_new_formulae?
+ !@added_formulae.empty?
+ end
+
+ def deleted_formulae?
+ !@deleted_formulae.empty?
+ end
+
+ def pending_examples_changes?
+ !@updated_examples.empty?
+ end
+
+ def pending_new_examples?
+ !@added_examples.empty?
+ end
+
+ def deleted_examples?
+ !@deleted_examples.empty?
+ end
+
+ def current_revision
+ HOMEBREW_REPOSITORY.cd { execute(REVISION_COMMAND).strip }
+ rescue
+ 'TAIL'
+ end
+
+ def report
+ puts "Updated Homebrew from #{initial_revision[0,8]} to #{current_revision[0,8]}."
+ ## New Formulae
+ if pending_new_formulae?
+ ohai "The following formulae are new:"
+ puts_columns added_formulae
+ end
+ ## Deleted Formulae
+ if deleted_formulae?
+ ohai "The following formulae were removed:"
+ puts_columns deleted_formulae
+ end
+ ## Updated Formulae
+ if pending_formulae_changes?
+ ohai "The following formulae were updated:"
+ puts_columns updated_formulae
+ else
+ puts "No formulae were updated."
+ end
+ ## New examples
+ if pending_new_examples?
+ ohai "The following external commands are new:"
+ puts_columns added_examples
+ end
+ ## Deleted examples
+ if deleted_examples?
+ ohai "The following external commands were removed:"
+ puts_columns deleted_examples
+ end
+ ## Updated Formulae
+ if pending_examples_changes?
+ ohai "The following external commands were updated:"
+ puts_columns updated_examples
+ else
+ puts "No external commands were updated."
+ end
+ end
+
+ private
+
+ def execute(cmd)
+ out = `#{cmd}`
+ if $? && !$?.success?
+ puts out
+ raise "Failed while executing #{cmd}"
+ end
+ ohai(cmd, out) if ARGV.verbose?
+ out
+ end
+end
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