diff options
| author | Max Howell | 2009-10-26 18:13:38 +0000 |
|---|---|---|
| committer | Max Howell | 2009-11-07 18:22:28 +0000 |
| commit | 794a55a72b78acf4c5866f20ff39e6fcc759e439 (patch) | |
| tree | 308fc3d74fdfac5514519b33193dad6aaffc5a5d /Library/Homebrew | |
| parent | e046e1e64094547f7d84f60a03360c3c84ba7d2c (diff) | |
| download | brew-794a55a72b78acf4c5866f20ff39e6fcc759e439.tar.bz2 | |
brew install improvements
Couldn't make this atomic, apologies.
Fixes a few things, like deps failing to build not aborting the install.
--force now works properly again.
Overall more robust code. I went back over it all and gave it a lot of
thought.
Cleaner separation of logic. Less code in brew, now the only code there is
ARGV handling, and basic sanity checks.
Not extending ARGV or ENV in global now as that would propagate to other tools
or utilities you may write.
Diffstat (limited to 'Library/Homebrew')
| -rw-r--r-- | Library/Homebrew/formula_installer.rb | 79 | ||||
| -rwxr-xr-x | Library/Homebrew/install.rb | 70 |
2 files changed, 113 insertions, 36 deletions
diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb new file mode 100644 index 000000000..326d8ed51 --- /dev/null +++ b/Library/Homebrew/formula_installer.rb @@ -0,0 +1,79 @@ +require 'beer_events' +require 'formula' +require 'set' + +def ignore_interrupts + std_trap = trap("INT") {} + yield +ensure + trap("INT", std_trap) +end + +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 install 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 if @install_deps + + 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 + + watch_out_for_spill do + fork do + begin + read.close + exec '/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 + 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 diff --git a/Library/Homebrew/install.rb b/Library/Homebrew/install.rb index a27cd2e4f..3c7ca6c90 100755 --- a/Library/Homebrew/install.rb +++ b/Library/Homebrew/install.rb @@ -3,19 +3,9 @@ BREW_FILE = `which brew`.strip require 'global' -require 'brew.h' -require 'extend/ENV' -require 'fileutils' -require 'formula' -require 'hardware' -require 'keg' - - -show_summary_heading = false - def text_for_keg_only_formula f if f.keg_only? == :provided_by_osx - rationale = "This because the formula is already provided by OS X." + rationale = "This is because the formula is already provided by OS X." elsif f.keg_only?.kind_of? String rationale = "The formula provides the following rationale:\n\n#{f.keg_only?.chomp}" else @@ -29,16 +19,41 @@ Generally there are no consequences of this for you, however if you build your own software and it requires this formula, you may want to run this command to link it into the Homebrew prefix: - brew link #{f.name} -EOS + brew link #{f.name} + EOS end +# I like this little at all, but see no alternative seeing as the formula +# rb file has to be the running script to allow it to use __END__ and DATA +at_exit do + begin + require 'extend/ENV' + require 'fileutils' + require 'hardware' + require 'keg' + require 'brew.h.rb' + + ENV.extend(HomebrewEnvExtension) + ENV.setup_build_environment + + install(Formula.factory($0)) + rescue Exception => e + if ENV['HOMEBREW_ERROR_PIPE'] + pipe = IO.new(ENV['HOMEBREW_ERROR_PIPE'].to_i, 'w') + Marshal.dump(e, pipe) + pipe.close + exit! 1 + else + onoe e + puts e.backtrace + exit! 2 + end + end +end def install f - # we deliberately only do this when install is run, although it may be the wrong decision… - ENV.extend(HomebrewEnvExtension) - ENV.setup_build_environment - + show_summary_heading = false + f.deps.each do |dep| dep = Formula.factory dep if dep.keg_only? @@ -51,7 +66,7 @@ def install f if ARGV.verbose? ohai "Build Environment" - %w[PATH CFLAGS LDFLAGS CPPFLAGS MAKEFLAGS CC CXX MACOSX_DEPLOYMENT_TARGET].each do |env| + %w[PATH CFLAGS LDFLAGS CPPFLAGS MAKEFLAGS CC CXX MACOSX_DEPLOYMENT_TARGET PKG_CONFIG_PATH].each do |env| puts "#{env}: #{ENV[env]}" unless ENV[env].to_s.empty? end end @@ -93,7 +108,7 @@ def install f end ohai 'Finishing up' if ARGV.verbose? - + begin clean f rescue Exception => e @@ -138,21 +153,4 @@ def install f print "#{f.prefix}: #{f.prefix.abv}" print ", built in #{pretty_duration build_time}" if build_time puts - -rescue Exception => e - if ENV['HOMEBREW_ERROR_PIPE'] - pipe = IO.new(ENV['HOMEBREW_ERROR_PIPE'].to_i, 'w') - Marshal.dump(e, pipe) - pipe.close - exit! 1 - else - onoe e - puts e.backtrace - exit! 2 - end end - - -# I like this little at all, but see no alternative seeing as the formula -# rb file has to be the running script to allow it to use __END__ and DATA -at_exit { install(Formula.factory($0)) } |
