From 760c083c0c0c9934e4118b4669c8c8dfd0a3587d Mon Sep 17 00:00:00 2001 From: Max Howell Date: Mon, 10 Aug 2009 16:48:30 +0100 Subject: Refactor Large refactor to Formula, mostly improving reliability and error handling but also layout and readability. General improvements so testing can be more complete. Patches are automatically downloaded and applied for Formula that return a list of urls from Formula::patches. Split out the brew command logic to facilitate testing. Facility from Adam Vandenberg to allow selective cleaning of files, added because Python doesn't work when stripped. --- Library/Contributions/brew_bash_completion.sh | 2 +- Library/Homebrew/brew.h.rb | 238 ++++++++++++++++++ Library/Homebrew/env.rb | 25 -- Library/Homebrew/formula.rb | 315 ++++++++++++----------- Library/Homebrew/keg.rb | 163 +++--------- Library/Homebrew/pathname+yeast.rb | 54 ++++ Library/Homebrew/unittest.rb | 60 ++++- Library/Homebrew/utils.rb | 21 +- README | 5 +- bin/brew | 349 +++++++------------------- 10 files changed, 659 insertions(+), 573 deletions(-) create mode 100644 Library/Homebrew/brew.h.rb delete mode 100644 Library/Homebrew/env.rb diff --git a/Library/Contributions/brew_bash_completion.sh b/Library/Contributions/brew_bash_completion.sh index dd18faa03..f33204d36 100644 --- a/Library/Contributions/brew_bash_completion.sh +++ b/Library/Contributions/brew_bash_completion.sh @@ -35,7 +35,7 @@ _brew_to_completion() ;; # Commands that take an existing brew... - abv|info|list|link|ls|ln|rm|uninstall) + abv|info|list|link|ls|ln|rm|remove|uninstall) cellar_contents=`ls ${brew_base}/Cellar/` COMPREPLY=( $(compgen -W "${cellar_contents}" -- ${cur}) ) return 0 diff --git a/Library/Homebrew/brew.h.rb b/Library/Homebrew/brew.h.rb new file mode 100644 index 000000000..3dee3ec2d --- /dev/null +++ b/Library/Homebrew/brew.h.rb @@ -0,0 +1,238 @@ +# Copyright 2009 Max Howell +# +# This file is part of Homebrew. +# +# Homebrew is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Homebrew is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Homebrew. If not, see . + +def make url + require 'formula' + + path=Pathname.new url + + /(.*?)[-_.]?#{path.version}/.match path.basename + raise "Couldn't parse name from #{url}" if $1.nil? or $1.empty? + + path=Formula.path $1 + raise "#{path} already exists" if path.exist? + + template=<<-EOS + require 'brewkit' + + class #{Formula.class $1} 1 + puts + end + else + puts "Not installed" + end + + if f.caveats + puts + puts f.caveats + puts + end + + puts 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 clean f + Cleaner.new f + # remove empty directories TODO Rubyize! + `perl -MFile::Find -e"finddepth(sub{rmdir},'#{f.prefix}')"` +end + + +def install f + f.brew do + if ARGV.flag? '--interactive' + ohai "Entering interactive mode" + puts "Type `exit' to return and finalize the installation" + puts "Install to this prefix: #{f.prefix}" + interactive_shell + elsif ARGV.include? '--help' + system './configure --help' + exit $? + else + f.prefix.mkpath + f.install + %w[README ChangeLog COPYING LICENSE COPYRIGHT AUTHORS].each do |file| + f.prefix.install file if File.file? file + end + end + end +end + + +def prune + $n=0 + $d=0 + + dirs=Array.new + paths=%w[bin 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< 0 + puts "from #{HOMEBREW_PREFIX}" + end +end + + +################################################################ class Cleaner +class Cleaner + def initialize f + @f=f + [f.bin, f.lib].each {|d| clean_dir d} + end + +private + def strip path, args='' + return if @f.skip_clean? path + puts "strip #{path}" if ARGV.verbose? + path.chmod 0644 # so we can strip + unless path.stat.nlink > 1 + `strip #{args} #{path}` + else + # strip unlinks the file and recreates it, thus breaking hard links! + # is this expected behaviour? patch does it too… still,mktm this fixes it + tmp=`mktemp -t #{path.basename}`.strip + `strip #{args} -o #{tmp} #{path}` + `cat #{tmp} > #{path}` + File.unlink tmp + end + end + + def clean_file path + perms=0444 + case `file -h #{path}` + when /Mach-O dynamically linked shared library/ + strip path, '-SxX' + when /Mach-O [^ ]* ?executable/ + strip path + perms=0544 + when /script text executable/ + perms=0544 + end + path.chmod perms + end + + def clean_dir d + d.find do |path| + if not path.file? + next + elsif path.extname == '.la' and not @f.skip_clean? path + # *.la files are stupid + path.unlink + else + clean_file path + end + end + end +end diff --git a/Library/Homebrew/env.rb b/Library/Homebrew/env.rb deleted file mode 100644 index 3710aa793..000000000 --- a/Library/Homebrew/env.rb +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2009 Max Howell -# -# This file is part of Homebrew. -# -# Homebrew is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Homebrew is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Homebrew. If not, see . - -require 'pathname+yeast' -require 'utils' - -# TODO if whoami == root then use /Library/Caches/Homebrew instead -HOMEBREW_VERSION='0.3' -HOMEBREW_CACHE=Pathname.new("~/Library/Caches/Homebrew").expand_path -HOMEBREW_PREFIX=Pathname.new(__FILE__).dirname.parent.parent.cleanpath -HOMEBREW_CELLAR=HOMEBREW_PREFIX+'Cellar' diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index 4f02e2077..f01798eba 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -15,30 +15,31 @@ # You should have received a copy of the GNU General Public License # along with Homebrew. If not, see . -require 'utils' -class BuildError e + raise unless ARGV.debug? + onoe e.inspect + puts e.backtrace + ohai "Rescuing build..." + puts "Type `exit' and Homebrew will attempt to finalize the installation" + puts "If nothing is installed to #{prefix}, then Homebrew will abort" + interactive_shell + end + end end - + +protected # Pretty titles the command and buffers stdout/stderr # Throws if there's an error - def system cmd - ohai cmd - if ARGV.include? '--verbose' - Kernel.system cmd + def system cmd, *args + full="#{cmd} #{args*' '}".strip + ohai full + if ARGV.verbose? + safe_system cmd, *args else out='' - IO.popen "#{cmd} 2>&1" do |f| + # TODO write a ruby extension that does a good popen :P + IO.popen "#{full} 2>&1" do |f| until f.eof? out+=f.gets end end - puts out unless $? == 0 + unless $? == 0 + puts out + raise + end end + rescue + raise BuildError.new(cmd, args) + end - raise BuildError.new(cmd) unless $? == 0 +private + def mktemp + tmp=Pathname.new `mktemp -dt #{File.basename @url}`.strip + raise if not tmp.directory? or $? != 0 + begin + wd=Dir.pwd + Dir.chdir tmp + yield + ensure + Dir.chdir wd + tmp.rmtree + end end - # we don't have a std_autotools variant because autotools is a lot less - # consistent and the standard parameters are more memorable - # really Homebrew should determine what works inside brew() then - # we could add --disable-dependency-tracking when it will work - def std_cmake_parameters - # The None part makes cmake use the environment's CFLAGS etc. settings - "-DCMAKE_INSTALL_PREFIX='#{prefix}' -DCMAKE_BUILD_TYPE=None" + # Kernel.system but with exceptions + def safe_system cmd, *args + puts "#{cmd} #{args*' '}" if ARGV.verbose? + # stderr is shown, so hopefully that will explain the problem + raise ExecutionError.new(cmd, args) unless Kernel.system cmd, *args and $? == 0 end - + + def curl url, *args + safe_system 'curl', '-f#LA', HOMEBREW_USER_AGENT, url, *args + end + def verify_download_integrity fn require 'digest' type='MD5' @@ -110,7 +165,7 @@ public supplied=eval "@#{type.downcase}" hash=eval("Digest::#{type}").hexdigest(fn.read) - if supplied + if supplied and not supplied.empty? raise "#{type} mismatch: #{hash}" unless supplied.upcase == hash.upcase else opoo "Cannot verify package integrity" @@ -119,91 +174,69 @@ public end end - # yields self with current working directory set to the uncompressed tarball - def brew - ohai "Downloading #{@url}" - HOMEBREW_CACHE.mkpath - Dir.chdir HOMEBREW_CACHE do - tmp=nil - tgz=Pathname.new(fetch()).realpath - begin - verify_download_integrity tgz - - # we make an additional subdirectory so know exactly what we are - # recursively deleting later - # we use mktemp rather than appsupport/blah because some build scripts - # can't handle being built in a directory with spaces in it :P - tmp=`mktemp -dt #{File.basename @url}`.strip - Dir.chdir tmp do - Dir.chdir uncompress(tgz) do - yield self - end - end - rescue Interrupt, RuntimeError - if ARGV.include? '--debug' - # debug mode allows the packager to intercept a failed build and - # investigate the problems - puts "Rescued build at: #{tmp}" - exit! 1 - else - raise - end - ensure - FileUtils.rm_rf tmp if tmp - end + def patch + unless patches.empty? + ohai "Patching" + ff=(1..patches.length).collect {|n| '%03d-homebrew.patch'%n} + curl *patches+ff.collect {|f|"-o#{f}"} + ff.each {|f| safe_system 'patch', '-p0', '-i', f} end end + + class <. +# +class Keg 1 - @path=kids[0] - @name=formula - @version=@path.basename - end + def uninstall + chmod_R 0777 # ensure we have permission to delete + rmtree + parent.rmdir_if_possible end - def clean - # TODO unset write permission more - %w[bin lib].each {|d| (Pathname.new(path)+d).find do |path| - if not path.file? - next - elsif path.extname == '.la' - # .la files are stupid - path.unlink - else - fo=`file -h #{path}` - args=nil - perms=0444 - if fo =~ /Mach-O dynamically linked shared library/ - args='-SxX' - elsif fo =~ /Mach-O [^ ]* ?executable/ - args='' # use strip defaults - perms=0544 - elsif fo =~ /script text executable/ - perms=0544 - end - if args - puts "Stripping: #{path}" if ARGV.include? '--verbose' - path.chmod 0644 # so we can strip - unless path.stat.nlink > 1 - `strip #{args} #{path}` - else - # strip unlinks the file and recreates it, thus breaking hard links! - # is this expected behaviour? patch does it too… still,mktm this fixes it - tmp=`mktemp -t #{path.basename}`.strip - `strip -o #{tmp} #{path}` - `cat #{tmp} > #{path}` - File.unlink tmp - end - end - path.chmod perms - end - end} + def link + $n=0 + $d=0 - # remove empty directories TODO Rubyize! - `perl -MFile::Find -e"finddepth(sub{rmdir},'#{path}')"` - end + mkpaths=(1..9).collect {|x| "man/man#{x}"} <<'man'<<'doc'<<'locale'<<'info'<<'aclocal' - def rm - # don't rmtree shit if we aren't positive about our location! - raise "Bad stuff!" unless path.parent.parent == HOMEBREW_CELLAR + # yeah indeed, you have to force anything you need in the main tree into + # these dirs REMEMBER that *NOT* everything needs to be in the main tree + link_dir('etc') {:mkpath} + link_dir('bin') {:link} + link_dir('lib') {|path| :mkpath if %w[pkgconfig php].include? path.to_s} + link_dir('include') {:link} + link_dir('share') {|path| :mkpath if mkpaths.include? path.to_s} - if path.directory? - FileUtils.chmod_R 0777, path # ensure we have permission to delete - path.rmtree # HOMEBREW_CELLAR/foo/1.2.0 - path.parent.rmdir if path.parent.children.length == 0 # HOMEBREW_CELLAR/foo - end + return $n+$d end private - def __symlink_relative_to from, to - tod=to.dirname - tod.mkpath - Dir.chdir(tod) do - #TODO use Ruby function so we get exceptions - #NOTE Ruby functions are fucked up! - `ln -sf "#{from.relative_path_from tod}"` - @n+=1 - end - end - - # symlinks a directory recursively into our FHS tree - def __ln start - start=path+start - return unless start.directory? - - root=Pathname.new HOMEBREW_PREFIX - start.find do |from| - next if from == start + # symlinks the contents of self+foo recursively into /usr/local/foo + def link_dir foo + root=self+foo - prune=false + root.find do |src| + next if src == root - relative_path=from.relative_path_from path - to=root+relative_path + dst=HOMEBREW_PREFIX+src.relative_path_from(self) + dst.extend ObserverPathnameExtension - if from.file? - __symlink_relative_to from, to - elsif from.directory? + if src.file? + dst.make_relative_symlink src + elsif src.directory? # no need to put .app bundles in the path, the user can just use # spotlight, or the open command and actual mac apps use an equivalent - Find.prune if from.extname.to_s == '.app' + Find.prune if src.extname.to_s == '.app' - branch=from.relative_path_from start - - case yield branch when :skip - Find.prune - when :mkpath - to.mkpath - @n+=1 - else - __symlink_relative_to from, to - Find.prune + case yield src.relative_path_from(root) + when :skip then Find.prune + when :mkpath then dst.mkpath + else dst.make_relative_symlink src; Find.prune end end end end - -public - def ln - # yeah indeed, you have to force anything you need in the main tree into - # these dirs REMEMBER that *NOT* everything needs to be in the main tree - # TODO consider using hardlinks - @n=0 - - __ln('etc') {:mkpath} - __ln('bin') {:link} - __ln('lib') {|path| :mkpath if ['pkgconfig','php'].include? path.to_s} - __ln('include') {:link} - - mkpaths=(1..9).collect {|x| "man/man#{x}"} <<'man'<<'doc'<<'locale'<<'info'<<'aclocal' - __ln('share') {|path| :mkpath if mkpaths.include? path.to_s} - - return @n - end -end \ No newline at end of file +end diff --git a/Library/Homebrew/pathname+yeast.rb b/Library/Homebrew/pathname+yeast.rb index 67a21cfc2..43c07c5ab 100644 --- a/Library/Homebrew/pathname+yeast.rb +++ b/Library/Homebrew/pathname+yeast.rb @@ -68,6 +68,24 @@ class Pathname return File.basename(to_s, extname) end + # I don't trust the children.length == 0 check particularly, not to mention + # it is slow to enumerate the whole directory just to see if it is empty, + # instead rely on good ol' libc and the filesystem + def rmdir_if_possible + rmdir + rescue SystemCallError => e + raise unless e.errno == Errno::ENOTEMPTY::Errno + end + + def chmod_R perms + require 'fileutils' + FileUtils.chmod_R perms, to_s + end + + def abv + `find #{to_s} -type f | wc -l`.strip+' files, '+`du -hd0 #{to_s} | cut -d"\t" -f1`.strip + end + def version # eg. boost_1_39_0 /((\d+_)+\d+)$/.match stem @@ -100,3 +118,39 @@ class Pathname end end end + +# sets $n and $d so you can observe creation of stuff +module ObserverPathnameExtension + def unlink + super + puts "rm #{to_s}" if ARGV.verbose? + $n+=1 + end + def rmdir + super + puts "rmdir #{to_s}" if ARGV.verbose? + $d+=1 + end + def resolved_path_exists? + (dirname+readlink).exist? + end + def mkpath + super + puts "mkpath #{to_s}" if ARGV.verbose? + $d+=1 + end + def make_relative_symlink src + dirname.mkpath + Dir.chdir dirname do + # TODO use Ruby function so we get exceptions + # NOTE Ruby functions may work, but I had a lot of problems + rv=system 'ln', '-sf', src.relative_path_from(dirname) + raise "Could not create symlink #{to_s}" unless rv and $? == 0 + puts "ln #{to_s}" if ARGV.verbose? + $n+=1 + end + end +end + +$n=0 +$d=0 diff --git a/Library/Homebrew/unittest.rb b/Library/Homebrew/unittest.rb index 878b05ab9..1bee7b3a6 100755 --- a/Library/Homebrew/unittest.rb +++ b/Library/Homebrew/unittest.rb @@ -1,9 +1,8 @@ #!/usr/bin/ruby $:.unshift File.dirname(__FILE__) +require 'pathname+yeast' require 'formula' require 'keg' -require 'pathname+yeast' -require 'stringio' require 'utils' # these are defined in env.rb usually, but we don't want to break our actual @@ -17,6 +16,7 @@ HOMEBREW_CELLAR.mkpath raise "HOMEBREW_CELLAR couldn't be created!" unless HOMEBREW_CELLAR.directory? at_exit { HOMEBREW_PREFIX.parent.rmtree } require 'test/unit' # must be after at_exit +require 'ARGV+yeast' # needs to be after test/unit to avoid conflict with OptionsParser class MockFormula #{path}` - assert_not_nil Formula.create(FOOBAR) + assert_not_nil Formula.factory(FOOBAR) end def test_cant_override_brew assert_raises(RuntimeError) { TestBallOverrideBrew.new } end + + def test_abstract_formula + f=MostlyAbstractFormula.new + assert_nil f.name + assert_raises(RuntimeError) { f.prefix } + nostdout { assert_raises(ExecutionError) { f.brew } } + end end diff --git a/Library/Homebrew/utils.rb b/Library/Homebrew/utils.rb index 112c6b6b6..bb64c3851 100644 --- a/Library/Homebrew/utils.rb +++ b/Library/Homebrew/utils.rb @@ -22,5 +22,24 @@ end # shows a warning in delicious pink def opoo warning - puts "WARNING \033[1;35m#{warning}\033[0;0m" + puts "\033[1;35m==>\033[0;0;1m Warning\033[0;0m: #{warning}" +end + +def onoe error + puts "\033[1;31m==>\033[0;0;1m Error\033[0;0m: #{error}" +end + +def pretty_duration s + return "#{(s*1000).to_i} milliseconds" if s < 3 + return "#{s.to_i} seconds" if s < 10*60 + return "#{(s/60).to_i} minutes" +end + +def interactive_shell + pid=fork + if pid.nil? + exec ENV['SHELL'] + else + Process.wait pid + end end diff --git a/README b/README index a79b4f17f..e981eda09 100644 --- a/README +++ b/README @@ -53,7 +53,10 @@ Here's why you may prefer Homebrew to the alternatives: We optimise for Leopard Intel, binaries are stripped, compile flags tweaked. Nobody wants crappy, slow software. Apart from MacPorts and Fink. -8. Integration with existing OS X technologies +8. Making the most of OS X + Homebrew knows how many cores you have thanks to RubyCocoa, so it makes + sure when it builds it uses all of them, (unless you don't want it to of + course). Homebrew integrates with Ruby gems, CPAN and Python disttools. These tools exist already and do the job great. We don't reinvent the wheel, we just improve it by making these tools install with more management options. diff --git a/bin/brew b/bin/brew index 6af4460ac..d4162986a 100755 --- a/bin/brew +++ b/bin/brew @@ -1,306 +1,135 @@ #!/usr/bin/ruby -$:.unshift __FILE__+'/../../Library/Homebrew' -require 'env' -require 'find' - -PRISTINE_ARGV=ARGV.dup +$:.unshift ENV['RUBYLIB']=File.expand_path(__FILE__+'/../../Library/Homebrew') + +require 'pathname+yeast' +require 'ARGV+yeast' +require 'utils' +require 'brew.h' + +# TODO if whoami == root then use /Library/Caches/Homebrew instead +HOMEBREW_CACHE=Pathname.new("~/Library/Caches/Homebrew").expand_path +HOMEBREW_PREFIX=Pathname.new(__FILE__).dirname.parent.cleanpath +HOMEBREW_CELLAR=HOMEBREW_PREFIX+'Cellar' +HOMEBREW_VERSION='0.4' +HOMEBREW_WWW='http://bit.ly/Homebrew' HOMEBREW_USER_AGENT="Homebrew #{HOMEBREW_VERSION} (Ruby #{VERSION}; Mac OS X 10.5 Leopard)" -# often causes Ruby to throw exception ffs -Dir.chdir '/' unless File.directory? ENV['PWD'] - -######################################################################## funcs -# remove symlinks that no longer point to files -def prune - n=0 - dirs=Array.new - HOMEBREW_PREFIX.find do |path| - if path.directory? - name=path.relative_path_from(HOMEBREW_PREFIX).to_s - if name == '.git' or name == 'Cellar' or name == 'Library' - Find.prune - else - dirs< brew #{PRISTINE_ARGV.join ' '} wget" if args.empty? - return args -end - -def extract_kegs - require 'keg' - kegs=extract_named_args.collect {|name| Keg.new name} - return kegs -end - -def abv keg=nil - path=keg ? keg.path : HOMEBREW_CELLAR - if path.directory? - `find #{path} -type f | wc -l`.strip+' files, '+`du -hd0 #{path} | cut -d"\t" -f1`.strip - else - '' - end -end - -def install formula - require 'keg' - - beginning = Time.now - - formula.brew do - if ARGV.include? '--interactive' - ohai "Entering interactive mode" - puts "Type `exit' to return and finalize the installation" - puts "Install to this prefix: #{formula.prefix}" - pid=fork - if pid.nil? - exec 'bash' - else - Process.wait pid - end - elsif ARGV.include? '--help' - ohai './configure --help' - puts `./configure --help` - exit - else - formula.prefix.mkpath - formula.install - %w[README ChangeLog COPYING LICENSE COPYRIGHT AUTHORS].each do |file| - formula.prefix.install file if File.file? file - end - end - end - - raise "Nothing was installed to #{formula.prefix}" unless formula.installed? - - ohai 'Finishing up' - keg=Keg.new formula - keg.clean - keg.ln - if formula.caveats - ohai "Caveats" - puts formula.caveats - ohai "Summary" - end - puts "#{keg.path}: "+abv(keg)+", built in #{pretty_duration Time.now-beginning}" -rescue Exception - formula.prefix.rmtree if formula.prefix.directory? - raise -end - -def mk url, mode='make' - require 'formula' - path=Pathname.new(url) - - /(.*?)[-_.]?#{path.version}/.match path.basename - raise "Couldn't parse name from #{url}" if $1.nil? or $1.empty? - - path=Formula.path $1 - raise "#{path} already exists!" if File.exist? path - - f=File.new path, 'w' - f.puts "require 'brewkit'" - f.puts - f.puts "class #{Formula.class $1} #{f.prefix}" if f.installed? unless ARGV.include? '--force' - install f + require 'keg' + ARGV.formulae.each do |f| + raise "#{f.name} is already installed" if f.installed? unless ARGV.force? + start_time=Time.now + begin + install f + if f.caveats + ohai "Caveats" + puts f.caveats + puts + end + ohai 'Finishing up' + clean f + raise "Nothing was installed to #{f.prefix}" unless f.installed? + Keg.new(f.prefix).link + rescue + f.prefix.rmtree if f.prefix.directory? + raise + end + puts "#{f.prefix}: "+f.prefix.abv+", built in #{pretty_duration Time.now-start_time}" end when 'ln', 'link' - n=0 - (kegs=extract_kegs).each do |keg| - n+=nn=keg.ln - puts "Created #{nn} links for #{keg.name}" if kegs.length > 1 - end - puts "Created #{n} links" + 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' - extract_kegs.each do |keg| - puts "Removing #{keg.name}..." - keg.rm + when 'rm', 'uninstall', 'remove' + ARGV.kegs.each do |keg| + puts "Uninstalling #{keg}..." + keg.uninstall end - print "Pruning #{prefix}/..." - puts " #{prune} symbolic links pruned" + prune + + when 'up', 'update' + puts "Reserved command" when 'prune' - puts "Pruned #{prune} symbolic links" + prune when 'mk', 'make' - mode = "make" - if ARGV.length > 0 - if ARGV[0] == '--cmake' - ARGV.shift - mode = "cmake" - end - end - - paths=ARGV.collect {|arg| mk arg, mode} - if paths.empty? - raise "Invalid URL" - elsif Kernel.system "which mate > /dev/null" and $? == 0 - paths=paths.collect {|path| path.to_s.gsub " ", "\\ "} - exec "mate #{paths.join ' '}" + if ARGV.include? '--macports' + exec "open", "http://www.macports.org/ports.php?by=name&substr=#{ARGV.next}" else - puts paths.join("\n") + exec "mate", *ARGV.named.collect {|name| make name} end when 'info', 'abv' - if ARGV.empty? - puts `ls #{HOMEBREW_CELLAR} | wc -l`.strip+" kegs, "+abv + if ARGV.named.empty? + puts `ls #{HOMEBREW_CELLAR} | wc -l`.strip+" kegs, "+HOMEBREW_CELLAR.abv elsif ARGV[0][0..6] == 'http://' puts Pathname.new(ARGV.shift).version else - require 'formula' - #TODO show outdated status and that - frm=Formula.create(extract_named_args[0]) - puts "#{frm.name} #{frm.version}" - puts frm.homepage - if frm.installed? - require 'keg' - keg=Keg.new frm - puts "#{abv keg} (installed to #{keg.path})" - end - if frm.caveats - ohai 'Caveats' - puts frm.caveats - end + ARGV.named.each {|name| info name} end else - puts usage + puts ARGV.usage end -rescue StandardError, Interrupt => e - if ARGV.include? '--verbose' or ENV['HOMEBREW_DEBUG'] - raise - elsif e.kind_of? Interrupt - puts # seeimgly a newline is typical - exit 130 - elsif e.kind_of? StandardError and not e.kind_of? NameError - puts "\033[1;31mError\033[0;0m: #{e}" - exit 1 +rescue SystemExit + ohai "Kernel.exit" if ARGV.verbose? +rescue Interrupt => e + puts # seemingly a newline is typical + exit 130 +rescue SystemCallError, RuntimeError => e + if ARGV.verbose? or ARGV.debug? + onoe e.inspect + puts e.backtrace else - raise + onoe e end + exit 1 +rescue Exception => e + onoe "Homebrew has failed you :(" + puts "Please report this bug at: #{HOMEBREW_WWW}" + puts "Please include this backtrace:" + ohai e.inspect + puts e.backtrace end -- cgit v1.2.3