
Kernel#system special-cases the first argument, so you have to make the first argument the entire command to be invoked, and subsequent arguments the actual arguments to that command. In order to use the user's interpreter, the first argument must be "/usr/bin/env <name>". Signed-off-by: Adam Vandenberg <flangy@gmail.com>
116 lines
2.9 KiB
Ruby
116 lines
2.9 KiB
Ruby
require 'formula'
|
|
require 'set'
|
|
|
|
class FormulaInstaller
|
|
@@attempted = Set.new
|
|
|
|
def initialize
|
|
@install_deps = true
|
|
end
|
|
|
|
attr_writer :install_deps
|
|
|
|
def expand_deps f
|
|
deps = []
|
|
f.deps.collect do |dep|
|
|
dep = Formula.factory dep
|
|
deps += expand_deps dep
|
|
deps << dep
|
|
end
|
|
deps
|
|
end
|
|
|
|
def pyerr dep
|
|
brew_pip = ' brew install pip &&' unless Formula.factory('pip').installed?
|
|
<<-EOS
|
|
Unsatisfied dependency, #{dep}
|
|
Homebrew does not provide formula for Python dependencies, pip does:
|
|
|
|
#{brew_pip} pip install #{dep}
|
|
EOS
|
|
end
|
|
def plerr dep; <<-EOS
|
|
Unsatisfied dependency, #{dep}
|
|
Homebrew does not provide formula for Perl dependencies, cpan does:
|
|
|
|
cpan -i #{dep}
|
|
EOS
|
|
end
|
|
def rberr dep; <<-EOS
|
|
Unsatisfied dependency "#{dep}"
|
|
Homebrew does not provide formulae for Ruby dependencies, rubygems does:
|
|
|
|
gem install #{dep}
|
|
EOS
|
|
end
|
|
|
|
def check_external_deps f
|
|
return unless f.external_deps
|
|
|
|
f.external_deps[:python].each do |dep|
|
|
raise pyerr(dep) unless quiet_system "/usr/bin/env", "python", "-c", "import #{dep}"
|
|
end
|
|
f.external_deps[:perl].each do |dep|
|
|
raise plerr(dep) unless quiet_system "/usr/bin/env", "perl", "-e", "use '#{dep}'"
|
|
end
|
|
f.external_deps[:ruby].each do |dep|
|
|
raise rberr(dep) unless quiet_system "/usr/bin/env", "ruby", "-rubygems", "-e", "require '#{dep}'"
|
|
end
|
|
end
|
|
|
|
def check_formula_deps f
|
|
expand_deps(f).each do |dep|
|
|
begin
|
|
install_private dep unless dep.installed?
|
|
rescue
|
|
#TODO continue if this is an optional dep
|
|
raise
|
|
end
|
|
end
|
|
end
|
|
|
|
def install f
|
|
if @install_deps
|
|
check_external_deps f
|
|
check_formula_deps f
|
|
end
|
|
install_private f
|
|
end
|
|
|
|
private
|
|
|
|
def install_private f
|
|
return if @@attempted.include? f.name
|
|
@@attempted << f.name
|
|
|
|
# 1. formulae can modify ENV, so we must ensure that each
|
|
# installation has a pristine ENV when it starts, forking now is
|
|
# 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
|
|
|
|
begin #watch_out_for_spill do #disabled temporarily, see Issue #124
|
|
fork do
|
|
begin
|
|
read.close
|
|
exec '/usr/bin/nice', '/usr/bin/ruby', '-I', File.dirname(__FILE__), '-rinstall', f.path, '--', *ARGV.options
|
|
rescue => e
|
|
Marshal.dump(e, write)
|
|
write.close
|
|
exit! 1
|
|
end
|
|
end
|
|
ignore_interrupts do # because child proc will get it 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
|
|
end
|
|
end
|
|
end
|