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/Homebrew/formula.rb | 315 +++++++++++++++++++++++--------------------- 1 file changed, 166 insertions(+), 149 deletions(-) (limited to 'Library/Homebrew/formula.rb') 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 <