2010-11-09 12:57:41 +00:00
|
|
|
require 'exceptions'
|
2009-10-26 18:13:38 +00:00
|
|
|
require 'formula'
|
|
|
|
require 'set'
|
|
|
|
|
|
|
|
class FormulaInstaller
|
2010-11-09 12:57:41 +00:00
|
|
|
attr :ignore_deps, true
|
2009-10-26 18:13:38 +00:00
|
|
|
|
2010-11-09 12:57:41 +00:00
|
|
|
def initialize f
|
|
|
|
@f = f
|
2009-10-26 18:13:38 +00:00
|
|
|
end
|
|
|
|
|
2010-11-09 12:57:41 +00:00
|
|
|
# raises Homebrew::InstallationErrors in the event of install failures
|
|
|
|
def go
|
|
|
|
if @f.installed? and not ARGV.force?
|
|
|
|
raise FormulaAlreadyInstalledError, @f
|
2011-03-09 21:01:23 -08:00
|
|
|
end
|
|
|
|
|
|
|
|
unless ignore_deps
|
2011-04-06 12:22:28 -07:00
|
|
|
needed_deps = @f.recursive_deps.reject {|d| d.installed?}
|
|
|
|
unless needed_deps.empty?
|
|
|
|
puts "Also installing dependencies: "+needed_deps*", "
|
|
|
|
needed_deps.each do |dep|
|
|
|
|
FormulaInstaller.install_formula dep
|
|
|
|
end
|
2010-11-09 12:57:41 +00:00
|
|
|
end
|
2011-02-20 12:20:07 -05:00
|
|
|
begin
|
|
|
|
FormulaInstaller.check_external_deps @f
|
|
|
|
rescue UnsatisfiedExternalDependencyError => e
|
|
|
|
onoe e.message
|
|
|
|
exit! 1
|
|
|
|
end
|
2010-04-08 14:50:06 -07:00
|
|
|
end
|
2011-03-09 21:01:23 -08:00
|
|
|
FormulaInstaller.install_formula @f
|
2010-01-13 09:00:24 +00:00
|
|
|
end
|
|
|
|
|
2010-11-09 12:57:41 +00:00
|
|
|
def self.check_external_deps f
|
|
|
|
[:ruby, :python, :perl, :jruby].each do |type|
|
|
|
|
f.external_deps[type].each do |dep|
|
|
|
|
unless quiet_system(*external_dep_check(dep, type))
|
|
|
|
raise UnsatisfiedExternalDependencyError.new(dep, type)
|
|
|
|
end
|
|
|
|
end if f.external_deps[type]
|
2010-02-09 11:30:16 -08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-11-09 12:57:41 +00:00
|
|
|
def self.external_dep_check dep, type
|
|
|
|
case type
|
|
|
|
when :python then %W{/usr/bin/env python -c import\ #{dep}}
|
|
|
|
when :jruby then %W{/usr/bin/env jruby -rubygems -e require\ '#{dep}'}
|
|
|
|
when :ruby then %W{/usr/bin/env ruby -rubygems -e require\ '#{dep}'}
|
|
|
|
when :perl then %W{/usr/bin/env perl -e use\ #{dep}}
|
2010-02-09 11:30:16 -08:00
|
|
|
end
|
2009-10-26 18:13:38 +00:00
|
|
|
end
|
2010-07-20 21:03:25 -07:00
|
|
|
|
2009-10-26 18:13:38 +00:00
|
|
|
private
|
|
|
|
|
2010-11-09 12:57:41 +00:00
|
|
|
def self.install_formula f
|
|
|
|
@attempted ||= Set.new
|
|
|
|
raise FormulaInstallationAlreadyAttemptedError, f if @attempted.include? f
|
|
|
|
@attempted << f
|
2009-10-26 18:13:38 +00:00
|
|
|
|
|
|
|
# 1. formulae can modify ENV, so we must ensure that each
|
2010-11-09 12:57:41 +00:00
|
|
|
# installation has a pristine ENV when it starts, forking now is
|
2009-10-26 18:13:38 +00:00
|
|
|
# the easiest way to do this
|
|
|
|
# 2. formulae have access to __END__ the only way to allow this is
|
|
|
|
# to make the formula script the executed script
|
|
|
|
read, write = IO.pipe
|
|
|
|
# I'm guessing this is not a good way to do this, but I'm no UNIX guru
|
|
|
|
ENV['HOMEBREW_ERROR_PIPE'] = write.to_i.to_s
|
|
|
|
|
2010-11-09 12:57:41 +00:00
|
|
|
fork do
|
|
|
|
begin
|
|
|
|
read.close
|
|
|
|
exec '/usr/bin/nice',
|
|
|
|
'/usr/bin/ruby',
|
|
|
|
'-I', Pathname.new(__FILE__).dirname,
|
|
|
|
'-rinstall',
|
|
|
|
'--',
|
2011-06-21 06:57:07 -07:00
|
|
|
f.path,
|
2010-11-09 12:57:41 +00:00
|
|
|
*ARGV.options_only
|
|
|
|
rescue Exception => e
|
|
|
|
Marshal.dump(e, write)
|
2009-10-26 18:13:38 +00:00
|
|
|
write.close
|
2010-11-09 12:57:41 +00:00
|
|
|
exit! 1
|
2009-10-26 18:13:38 +00:00
|
|
|
end
|
|
|
|
end
|
2010-11-09 12:57:41 +00:00
|
|
|
|
|
|
|
ignore_interrupts do # the fork will receive the interrupt and marshall it back
|
|
|
|
write.close
|
|
|
|
Process.wait
|
|
|
|
data = read.read
|
|
|
|
raise Marshal.load(data) unless data.nil? or data.empty?
|
|
|
|
raise "Suspicious installation failure" unless $?.success?
|
|
|
|
end
|
2009-10-26 18:13:38 +00:00
|
|
|
end
|
|
|
|
end
|