aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Howell2009-09-18 19:16:39 +0100
committerMax Howell2009-09-21 18:27:48 +0100
commit77dd27e8e6e9e2f31fc8ca90bb6d63399922d013 (patch)
tree95da1d90b212516c0e725fca444af4625d4e97f5
parenta793e3040513f72a5108944a8c3ee1cbfb37ebb2 (diff)
downloadbrew-77dd27e8e6e9e2f31fc8ca90bb6d63399922d013.tar.bz2
Dependency resolution with fancy syntax
Is it a DSL? No. But people call it that apparently. To add a dependency: class Doe <Formula depends_on 'ray' depends_on 'mee' => :optional depends_on 'far' => :recommended depends_on Sew.new end Sew would be a formula you have defined in this Formula file. This is useful, eg. see Python's formula. Formula specified in this fashion cannot be linked into the HOMEBREW_PREFIX, they are considered private libraries. This allows you to create custom installations that are very specific to your formula. More features to come, like specifying versions
-rw-r--r--Library/Homebrew/brew.h.rb27
-rw-r--r--Library/Homebrew/formula.rb33
-rwxr-xr-xbin/brew23
3 files changed, 47 insertions, 36 deletions
diff --git a/Library/Homebrew/brew.h.rb b/Library/Homebrew/brew.h.rb
index 875f61be0..0d977ae95 100644
--- a/Library/Homebrew/brew.h.rb
+++ b/Library/Homebrew/brew.h.rb
@@ -144,31 +144,12 @@ 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
+def expand_deps ff
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 unless f.installed?
- 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
+ ff.deps.collect do |f|
+ deps += expand_deps(Formula.factory(f))
end
-
- # TODO much more efficient to use a set and not recurse stuff already done
- return deps.flatten.uniq
+ deps << ff
end
diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb
index 9c5123545..a4bebdd2b 100644
--- a/Library/Homebrew/formula.rb
+++ b/Library/Homebrew/formula.rb
@@ -114,8 +114,6 @@ class Formula
# :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
@@ -157,6 +155,7 @@ class Formula
end
def self.factory name
+ return name if name.kind_of? Formula
require self.path(name)
return eval(self.class(name)).new(name)
rescue LoadError
@@ -167,6 +166,10 @@ class Formula
HOMEBREW_PREFIX+'Library'+'Formula'+"#{name.downcase}.rb"
end
+ def deps
+ self.class.deps or []
+ end
+
protected
# Pretty titles the command and buffers stdout/stderr
# Throws if there's an error
@@ -280,9 +283,31 @@ private
end
class <<self
- attr_reader :url, :version, :homepage, :head
+ attr_reader :url, :version, :homepage, :head, :deps
attr_reader *CHECKSUM_TYPES
- end
+
+ def depends_on name, *args
+ @deps ||= []
+
+ case name
+ when String
+ # noop
+ when Hash
+ name = name.keys.first # indeed, we only support one mapping
+ when Symbol
+ name = name.to_s
+ when Formula
+ @deps << name
+ return # we trust formula dev to not dupe their own instantiations
+ else
+ raise "Unsupported type #{name.class}"
+ end
+
+ # we get duplicates because every new fork of this process repeats this
+ # step for some reason I am not sure about
+ @deps << name unless @deps.include? name
+ end
+ end
end
# see ack.rb for an example usage
diff --git a/bin/brew b/bin/brew
index bf3a449c2..722544615 100755
--- a/bin/brew
+++ b/bin/brew
@@ -38,6 +38,7 @@ unless system "which -s gcc-4.2" and $?.success?
abort "Sorry, Homebrew requires gcc 4.2, which is provided by Xcode 3.1"
end
+
begin
case ARGV.shift
when '--prefix' then puts HOMEBREW_PREFIX
@@ -104,7 +105,7 @@ begin
unless system "which #{ENV['CC'] or 'cc'} &> /dev/null" and $?.success?
raise "We cannot find a c compiler, have you installed the latest Xcode?"
end
- fae = ARGV.formulae.reject do |f|
+ formulae = ARGV.formulae.reject do |f|
if f.installed?
message = "Formula already installed: #{f.prefix}"
if ARGV.formulae.count > 1
@@ -115,20 +116,24 @@ begin
true
end
end
- exit 0 if fae.empty?
+ exit 0 if formulae.empty?
else
- fae=ARGV.formulae
+ formulae = ARGV.formulae
end
- # the resulting order will be optimal for super-deps and deps
- fae=expand_deps fae
+ deps = []
+ formulae.each { |f| deps += expand_deps f }
+ formulae = deps.reject { |f| f.installed? }
- require 'beer_events'
+ require 'set'
+ done = Set.new
+ 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
+ formulae.each do |f|
+ next if done.include? f.class
+ done << f.class
+
pid=fork
if pid.nil?
exec __FILE__, "install-just-one", f.name, *ARGV.options