diff --git a/Library/Homebrew/dependencies.rb b/Library/Homebrew/dependencies.rb index 5d5b5ab0d9..7c2ff7d1b0 100644 --- a/Library/Homebrew/dependencies.rb +++ b/Library/Homebrew/dependencies.rb @@ -21,7 +21,7 @@ class DependencyCollector def initialize @deps = Dependencies.new - @requirements = Set.new + @requirements = ComparableSet.new end def add spec @@ -196,6 +196,9 @@ end # This requirement is used to require an X11 implementation, # optionally with a minimum version number. class X11Dependency < Requirement + include Comparable + attr_reader :min_version + def initialize min_version=nil @min_version = min_version end @@ -217,9 +220,20 @@ class X11Dependency < Requirement ENV.x11 end - def hash - "X11".hash + def <=> other + unless other.is_a? X11Dependency + raise TypeError, "expected X11Dependency" + end + + if other.min_version.nil? + 1 + elsif @min_version.nil? + -1 + else + @min_version <=> other.min_version + end end + end diff --git a/Library/Homebrew/extend/set.rb b/Library/Homebrew/extend/set.rb new file mode 100644 index 0000000000..b45b85de96 --- /dev/null +++ b/Library/Homebrew/extend/set.rb @@ -0,0 +1,24 @@ +require 'set' + +class ComparableSet < Set + def add new + # smileys only + return super new unless new.respond_to? :> + + objs = find_all { |o| o.class == new.class } + objs.each do |o| + return self if o > new + delete o + end + super new + end + + alias_method :<<, :add + + # Set#merge bypasses enumerating the set's contents, + # so the subclassed #add would never be called + def merge enum + enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable" + enum.each { |o| add(o) } + end +end diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index d23aeea714..8f63cd705d 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -6,6 +6,7 @@ require 'bottles' require 'patches' require 'compilers' require 'build_environment' +require 'extend/set' class Formula @@ -455,9 +456,9 @@ class Formula end def recursive_requirements - reqs = recursive_deps.map { |dep| dep.requirements }.to_set - reqs << requirements - reqs.flatten + reqs = ComparableSet.new + recursive_deps.each { |dep| reqs.merge dep.requirements } + reqs.merge requirements end def to_hash diff --git a/Library/Homebrew/test/test_comparableset.rb b/Library/Homebrew/test/test_comparableset.rb new file mode 100644 index 0000000000..d39ad51d6d --- /dev/null +++ b/Library/Homebrew/test/test_comparableset.rb @@ -0,0 +1,40 @@ +require 'testing_env' +require 'extend/set' + +class ComparableSetTests < Test::Unit::TestCase + def setup + @set = ComparableSet.new + end + + def test_merging_multiple_dependencies + @set << X11Dependency.new + @set << X11Dependency.new + assert_equal @set.count, 1 + @set << Requirement.new + assert_equal @set.count, 2 + end + + def test_comparison_prefers_larger + @set << X11Dependency.new + @set << X11Dependency.new('2.6') + assert_equal @set.count, 1 + assert_equal @set.to_a, [X11Dependency.new('2.6')] + end + + def test_comparison_does_not_merge_smaller + @set << X11Dependency.new('2.6') + @set << X11Dependency.new + assert_equal @set.count, 1 + assert_equal @set.to_a, [X11Dependency.new('2.6')] + end + + def test_merging_sets + @set << X11Dependency.new + @set << Requirement.new + reqs = Set.new [X11Dependency.new('2.6'), Requirement.new] + @set.merge reqs + + assert_equal @set.count, 2 + assert_equal @set.find {|r| r.is_a? X11Dependency}, X11Dependency.new('2.6') + end +end