From d1f754c02e5ef36de70ac3cb7ad7669a90ec9295 Mon Sep 17 00:00:00 2001 From: Jack Nagel Date: Wed, 24 Oct 2012 18:17:43 -0500 Subject: Allow requirements to record tags To allow depends_on :x11 => :optional and friends to work as expected, make requirements record any tags and add special handling to the X11Dependency to record both a minimum version and additional tags. Signed-off-by: Jack Nagel --- Library/Homebrew/dependencies.rb | 65 ++++++++---- Library/Homebrew/requirements.rb | 10 +- Library/Homebrew/test/test_comparableset.rb | 1 + Library/Homebrew/test/test_dependencies.rb | 36 +++++++ Library/Homebrew/test/test_external_deps.rb | 96 ----------------- Library/Homebrew/test/test_requirements.rb | 154 ++++++++++++++++++++++++++++ 6 files changed, 244 insertions(+), 118 deletions(-) create mode 100644 Library/Homebrew/test/test_dependencies.rb delete mode 100644 Library/Homebrew/test/test_external_deps.rb create mode 100644 Library/Homebrew/test/test_requirements.rb (limited to 'Library') diff --git a/Library/Homebrew/dependencies.rb b/Library/Homebrew/dependencies.rb index 16d2768f2..352688839 100644 --- a/Library/Homebrew/dependencies.rb +++ b/Library/Homebrew/dependencies.rb @@ -61,17 +61,17 @@ private case spec when :autoconf, :automake, :bsdmake, :libtool # Xcode no longer provides autotools or some other build tools - Dependency.new(spec.to_s) unless MacOS::Xcode.provides_autotools? + Dependency.new(spec.to_s, tag) unless MacOS::Xcode.provides_autotools? when :libpng, :freetype, :pixman, :fontconfig, :cairo if MacOS.version >= :mountain_lion - Dependency.new(spec.to_s) + Dependency.new(spec.to_s, tag) else X11Dependency.new(tag) end when :x11 X11Dependency.new(tag) when :xcode - XCodeDependency.new + XcodeDependency.new(tag) else raise "Unsupported special dependency #{spec}" end @@ -82,47 +82,76 @@ end # A list of formula dependencies. class Dependencies < Array - def include? dependency_name - self.any?{|d| d.name == dependency_name} + def <<(o) + super(o) unless include? o + end +end + +module Dependable + RESERVED_TAGS = [:build, :optional, :recommended] + + def build? + tags.include? :build + end + + def optional? + tags.include? :optional + end + + def recommended? + tags.include? :recommended + end + + def options + tags.reject { |tag| RESERVED_TAGS.include? tag }.map { |tag| '--'+tag.to_s } end end # A dependency on another Homebrew formula. class Dependency + include Dependable + attr_reader :name, :tags - def initialize name, tags=nil + def initialize(name, *tags) @name = name - @tags = case tags - when Array then tags.each {|s| s.to_s} - when nil then [] - else [tags.to_s] - end + @tags = [tags].flatten.compact + end + + def hash + @name.hash end def to_s @name end - def ==(other_dep) - @name == other_dep.to_s + def ==(other) + @name == other.to_s end - def <=>(other_dep) - @name <=> other_dep.to_s + def <=>(other) + @name <=> other.to_s end - def options - @tags.select{|p|p.start_with? '--'} + def eql?(other) + other.is_a? self.class and hash == other.hash end end - # A base class for non-formula requirements needed by formulae. # A "fatal" requirement is one that will fail the build if it is not present. # By default, Requirements are non-fatal. class Requirement + include Dependable + + attr_reader :tags + + def initialize(*tags) + @tags = tags.flatten.compact + end + # Should return true if this requirement is met. def satisfied?; false; end # Should return true if not meeting this requirement should fail the build. diff --git a/Library/Homebrew/requirements.rb b/Library/Homebrew/requirements.rb index b7cc68a7c..00c161296 100644 --- a/Library/Homebrew/requirements.rb +++ b/Library/Homebrew/requirements.rb @@ -53,8 +53,10 @@ class X11Dependency < Requirement include Comparable attr_reader :min_version - def initialize min_version=nil - @min_version = min_version + def initialize(*tags) + tags.flatten! + @min_version = tags.shift if /(\d\.)+\d/ === tags.first + super end def fatal?; true; end @@ -193,7 +195,7 @@ class ConflictRequirement < Requirement end end -class XCodeDependency < Requirement +class XcodeDependency < Requirement def fatal?; true; end def satisfied? @@ -201,7 +203,7 @@ class XCodeDependency < Requirement end def message; <<-EOS.undent - A full installation of XCode.app is required to compile this software. + A full installation of Xcode.app is required to compile this software. Installing just the Command Line Tools is not sufficent. EOS end diff --git a/Library/Homebrew/test/test_comparableset.rb b/Library/Homebrew/test/test_comparableset.rb index d39ad51d6..39f9b6f32 100644 --- a/Library/Homebrew/test/test_comparableset.rb +++ b/Library/Homebrew/test/test_comparableset.rb @@ -1,5 +1,6 @@ require 'testing_env' require 'extend/set' +require 'dependencies' class ComparableSetTests < Test::Unit::TestCase def setup diff --git a/Library/Homebrew/test/test_dependencies.rb b/Library/Homebrew/test/test_dependencies.rb new file mode 100644 index 000000000..4758aad0a --- /dev/null +++ b/Library/Homebrew/test/test_dependencies.rb @@ -0,0 +1,36 @@ +require 'testing_env' +require 'test/testball' +require 'dependencies' + +class DependencyCollector + def find_dependency(name) + deps.find { |dep| dep.name == name } + end +end + +class DependencyTests < Test::Unit::TestCase + def setup + @d = DependencyCollector.new + end + + def test_dependency_creation + @d.add 'foo' => :build + @d.add 'bar' => ['--universal', :optional] + assert_not_nil @d.find_dependency('foo') + assert_equal 2, @d.find_dependency('bar').tags.length + end + + def test_dependency_tags + assert Dependency.new('foo', :build).build? + assert Dependency.new('foo', [:build, :optional]).optional? + assert Dependency.new('foo', [:universal]).options.include? '--universal' + assert_empty Dependency.new('foo').tags + end + + def test_no_duplicate_dependencies + @d.add 'foo' + @d.add 'foo' => :build + assert_equal 1, @d.deps.length + assert_empty @d.find_dependency('foo').tags + end +end diff --git a/Library/Homebrew/test/test_external_deps.rb b/Library/Homebrew/test/test_external_deps.rb deleted file mode 100644 index b4ca0f6e6..000000000 --- a/Library/Homebrew/test/test_external_deps.rb +++ /dev/null @@ -1,96 +0,0 @@ -require 'testing_env' -require 'extend/string' -require 'test/testball' -require 'formula_installer' - - -class ExternalDepsTests < Test::Unit::TestCase - def check_deps_fail specs - d = DependencyCollector.new - specs.each do |key, value| - d.add key => value - end - - # Should have found a dep - assert d.requirements.size == 1 - - d.requirements do |req| - assert !d.satisfied? - end - end - - def check_deps_pass specs - d = DependencyCollector.new - specs.each do |key, value| - d.add key => value - end - - # Should have found a dep - assert d.requirements.size == 1 - - d.requirements do |req| - assert d.satisfied? - end - end - - - def test_bad_perl_deps - check_deps_fail "notapackage" => :perl - end - - def test_good_perl_deps - check_deps_pass "ENV" => :perl - end - - def test_bad_python_deps - check_deps_fail "notapackage" => :python - end - - def test_good_python_deps - check_deps_pass "datetime" => :python - end - - def test_bad_ruby_deps - check_deps_fail "notapackage" => :ruby - end - - def test_good_ruby_deps - check_deps_pass "date" => :ruby - end - - # Only run these next two tests if jruby is installed. - def test_bad_jruby_deps - check_deps_fail "notapackage" => :jruby if which('jruby') - end - - def test_good_jruby_deps - check_deps_pass "date" => :jruby if which('jruby') - end - - # Only run these next two tests if rubinius is installed. - def test_bad_rubinius_deps - check_deps_fail "notapackage" => :rbx if which('rbx') - end - - def test_good_rubinius_deps - check_deps_pass "date" => :rbx if which('rbx') - end - - # Only run these next two tests if chicken scheme is installed. - def test_bad_chicken_deps - check_deps_fail "notapackage" => :chicken if which('csc') - end - - def test_good_chicken_deps - check_deps_pass "extras" => :chicken if which('csc') - end - - # Only run these next two tests if node.js is installed. - def test_bad_node_deps - check_deps_fail "notapackage" => :node if which('node') - end - - def test_good_node_deps - check_deps_pass "util" => :node if which('node') - end -end diff --git a/Library/Homebrew/test/test_requirements.rb b/Library/Homebrew/test/test_requirements.rb new file mode 100644 index 000000000..c8a8e1ba8 --- /dev/null +++ b/Library/Homebrew/test/test_requirements.rb @@ -0,0 +1,154 @@ +require 'testing_env' +require 'test/testball' +require 'dependencies' + +class DependencyCollector + def find_requirement(klass) + requirements.find do |req| + klass === req + end + end +end + +class RequirementTests < Test::Unit::TestCase + def setup + @d = DependencyCollector.new + end + + def test_requirement_creation + @d.add :x11 + assert_not_nil @d.find_requirement(X11Dependency) + end + + + def test_no_duplicate_requirements + 2.times { @d.add :x11 } + assert_equal 1, @d.requirements.length + end +end + +class RequirementTagTests < Test::Unit::TestCase + def setup + @d = DependencyCollector.new + end + + def test_requirement_tags + @d.add :x11 => '2.5.1' + @d.add :xcode => :build + assert_empty @d.find_requirement(X11Dependency).tags + assert @d.find_requirement(XcodeDependency).build? + end + + def test_x11_no_tag + @d.add :x11 + assert_empty @d.find_requirement(X11Dependency).tags + end + + def test_x11_min_version + @d.add :x11 => '2.5.1' + assert_equal '2.5.1', @d.find_requirement(X11Dependency).min_version + end + + def test_x11_tag + @d.add :x11 => :optional + assert @d.find_requirement(X11Dependency).optional? + end + + def test_x11_min_version_and_tag + @d.add :x11 => ['2.5.1', :optional] + dep = @d.find_requirement(X11Dependency) + assert_equal '2.5.1', dep.min_version + assert dep.optional? + end +end + +class ExternalDepsTests < Test::Unit::TestCase + def check_deps_fail specs + d = DependencyCollector.new + specs.each do |key, value| + d.add key => value + end + + # Should have found a dep + assert d.requirements.size == 1 + + d.requirements do |req| + assert !d.satisfied? + end + end + + def check_deps_pass specs + d = DependencyCollector.new + specs.each do |key, value| + d.add key => value + end + + # Should have found a dep + assert d.requirements.size == 1 + + d.requirements do |req| + assert d.satisfied? + end + end + + + def test_bad_perl_deps + check_deps_fail "notapackage" => :perl + end + + def test_good_perl_deps + check_deps_pass "ENV" => :perl + end + + def test_bad_python_deps + check_deps_fail "notapackage" => :python + end + + def test_good_python_deps + check_deps_pass "datetime" => :python + end + + def test_bad_ruby_deps + check_deps_fail "notapackage" => :ruby + end + + def test_good_ruby_deps + check_deps_pass "date" => :ruby + end + + # Only run these next two tests if jruby is installed. + def test_bad_jruby_deps + check_deps_fail "notapackage" => :jruby if which('jruby') + end + + def test_good_jruby_deps + check_deps_pass "date" => :jruby if which('jruby') + end + + # Only run these next two tests if rubinius is installed. + def test_bad_rubinius_deps + check_deps_fail "notapackage" => :rbx if which('rbx') + end + + def test_good_rubinius_deps + check_deps_pass "date" => :rbx if which('rbx') + end + + # Only run these next two tests if chicken scheme is installed. + def test_bad_chicken_deps + check_deps_fail "notapackage" => :chicken if which('csc') + end + + def test_good_chicken_deps + check_deps_pass "extras" => :chicken if which('csc') + end + + # Only run these next two tests if node.js is installed. + def test_bad_node_deps + check_deps_fail "notapackage" => :node if which('node') + end + + def test_good_node_deps + check_deps_pass "util" => :node if which('node') + end +end -- cgit v1.2.3