# 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 . class ExecutionError 0 rescue return false end def prefix raise "Invalid @name" if @name.nil? or @name.empty? raise "Invalid @version" if @version.nil? or @version.empty? HOMEBREW_CELLAR+@name+@version end def path Formula.path name end attr_reader :url, :version, :url, :homepage, :name def bin; prefix+'bin' end def sbin; prefix+'sbin' end def doc; prefix+'share'+'doc'+name end def lib; prefix+'lib' end def man; prefix+'share'+'man' end def man1; man+'man1' end def info; prefix+'share'+'info' end def include; prefix+'include' end # tell the user about any caveats regarding this package def caveats; nil end # patches are automatically applied after extracting the tarball # return an array of strings, or if you need a patch level other than -p0 # return a Hash eg. # { # :p0 => ['http://foo.com/patch1', 'http://foo.com/patch2'], # :p1 => 'http://bar.com/patch2', # :p2 => ['http://moo.com/patch5', 'http://moo.com/patch6'] # } def patches; [] end # reimplement and specify dependencies def deps; end # sometimes the clean process breaks things, return true to skip anything def skip_clean? path; false end # yields self with current working directory set to the uncompressed tarball def brew ohai "Downloading #{@url}" tgz=HOMEBREW_CACHE+File.basename(@url) unless tgz.exist? HOMEBREW_CACHE.mkpath curl @url, '-o', tgz else puts "File already downloaded and cached" end verify_download_integrity tgz mktemp do Dir.chdir uncompress(tgz) begin patch yield self rescue Interrupt, RuntimeError, SystemCallError => 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 raise "Non-zero exit status, installation aborted" if $? != 0 end end end protected # Pretty titles the command and buffers stdout/stderr # Throws if there's an error def system cmd, *args full="#{cmd} #{args*' '}".strip ohai full if ARGV.verbose? safe_system cmd, *args else out='' # 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 unless $? == 0 puts out raise end end rescue raise BuildError.new(cmd, args) end 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 # Kernel.system but with exceptions def safe_system cmd, *args puts "#{cmd} #{args*' '}" if ARGV.verbose? execd=Kernel.system cmd, *args # somehow Ruby doesn't handle the CTRL-C from another process -- WTF!? raise Interrupt, cmd if $?.termsig == 2 raise ExecutionError.new(cmd, args) unless execd 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' type='SHA1' if @sha1 supplied=eval "@#{type.downcase}" hash=eval("Digest::#{type}").hexdigest(fn.read) if supplied and not supplied.empty? raise "#{type} mismatch: #{hash}" unless supplied.upcase == hash.upcase else opoo "Cannot verify package integrity" puts "The formula did not provide a download checksum" puts "For your reference the #{type} is: #{hash}" end end def patch return if patches.empty? ohai "Patching" if patches.kind_of? Hash patch_args=[] curl_args=[] n=0 patches.each do |arg, urls| urls.each do |url| dst='%03d-homebrew.patch' % n+=1 curl_args<