From 0a31190fdca5fd8619263e66212d74d4c2f56a74 Mon Sep 17 00:00:00 2001 From: Max Howell Date: Mon, 7 Sep 2009 01:06:08 +0100 Subject: [PATCH] Dependency resolution Specify dependencies in your formula's deps function. You can return an Array, String or Hash, eg: def deps { :optional => 'libogg', :required => %w[flac sdl], :recommended => 'cmake' } end Note currently the Hash is flattened and qualifications are ignored. If you only return an Array or String, the qualification is assumed to be :required. Other packaging systems have problems when it comes to packages requiring a specific version of a package, or some patches that may not work well with other software. With Homebrew we have some options: 1. If the formula is vanilla but an older version we can cherry-pick the old version and install it in the Cellar in parallel, but just not symlink it into /usr/local while forcing the formula that depends on it to link to that one and not any other versions of it. 2. If the dependency requires patches then we shouldn't install this for use by any other tools, (I guess this needs to be decided on a per-situation basis). It can be installed into the parent formula's prefix, and not symlinked into /usr/local. In this case the dependency's Formula derivation should be saved in the parent formula's file (check git or flac for an example of this). Both the above can be done currently with hacks, so I'll flesh out a proper way sometime this week. --- Library/Homebrew/brew.h.rb | 27 +++++++++++++++++++++++++++ Library/Homebrew/formula.rb | 2 +- Library/Homebrew/unittest.rb | 23 +++++++++++++++-------- bin/brew | 31 ++++++++++++++++--------------- 4 files changed, 59 insertions(+), 24 deletions(-) diff --git a/Library/Homebrew/brew.h.rb b/Library/Homebrew/brew.h.rb index 8b3939968d..496e7afc06 100644 --- a/Library/Homebrew/brew.h.rb +++ b/Library/Homebrew/brew.h.rb @@ -144,6 +144,33 @@ def clean f end +# NOTE this is ugly code, and inefficient too, and can have infinite cycles +# I have no time currently to improve it, feel free to submit a more elegant +# solution. Thanks! --mxcl +def expand_deps fae + deps = [] + fae.each do |f| + case f.deps + when String, Array + f.deps.each do |name| + f = Formula.factory name + deps << expand_deps(f) if f.deps # hideous inefficient + deps << f + end + when Hash + # TODO implement optional and recommended + names = [] + f.deps.each_value {|v| names << v} + ff=names.flatten.collect {|name| Formula.factory name} + deps << expand_deps(ff) + end + deps << f + end + # TODO much more efficient to use a set and not recurse stuff already done + return deps.flatten.uniq +end + + def install f f.brew do if ARGV.flag? '--interactive' diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index 7faabbae6c..9c5123545b 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -123,7 +123,7 @@ class Formula def brew validate_variable :name validate_variable :version - + stage do begin patch diff --git a/Library/Homebrew/unittest.rb b/Library/Homebrew/unittest.rb index ae8b0c1bc3..2738755e46 100755 --- a/Library/Homebrew/unittest.rb +++ b/Library/Homebrew/unittest.rb @@ -41,7 +41,8 @@ class MostlyAbstractFormula 0 + ARGV.shift + end end end ARGV.extend ExtendArgvPlusYeast @@ -347,8 +352,9 @@ class BeerTasting 1 - opoo message - else - puts message # if only one is being installed a warning looks severe - end - next + fae = ARGV.formulae.reject do |f| + if f.installed? and not ARGV.force? + message = "Formula already installed: #{f.prefix}" + if ARGV.formulae.count > 1 + opoo message + else + puts message # if only one is being installed a warning looks severe end + true + end + end + fae=expand_deps ARGV.formulae + + require 'beer_events' + + watch_out_for_spill do + fae.each do |f| # we need to ensure a pristine ENV for each process or the formula # will start with the ENV from the previous build pid=fork @@ -162,9 +166,6 @@ begin when 'unlink' ARGV.kegs.each {|keg| puts "#{keg.unlink} links removed for #{keg}"} - when 'unlink' - ARGV.kegs.each {|keg| puts "#{keg.unlink} links removed for #{keg}"} - when 'rm', 'uninstall', 'remove' ARGV.kegs.each do |keg| puts "Uninstalling #{keg}..."