From 2c563a51fb74bc80fb4f4802fbc07d5311edd750 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Tue, 8 Sep 2020 15:18:13 +0200 Subject: [PATCH] Merge pull request #3889 from toy/sort-dependency-requirements Sort requirements in Gem::Requirement to succeed comparison with different order (cherry picked from commit a45280924ba1e9ab5b76dccf612cb958a5b6db6e) --- bundler/lib/bundler/rubygems_ext.rb | 29 +++++++++++++++++++ bundler/spec/install/gemfile/platform_spec.rb | 29 +++++++++++++++++++ lib/rubygems/requirement.rb | 8 +++-- test/rubygems/test_gem_requirement.rb | 2 ++ 4 files changed, 66 insertions(+), 2 deletions(-) diff --git a/bundler/lib/bundler/rubygems_ext.rb b/bundler/lib/bundler/rubygems_ext.rb index 1d3bdc5565be..82816d24fab2 100644 --- a/bundler/lib/bundler/rubygems_ext.rb +++ b/bundler/lib/bundler/rubygems_ext.rb @@ -129,6 +129,35 @@ def to_lock end end + # comparison is done order independently since rubygems 3.2.0.rc.2 + unless Gem::Requirement.new("> 1", "< 2") == Gem::Requirement.new("< 2", "> 1") + class Requirement + module OrderIndependentComparison + def ==(other) + if _requirements_sorted? && other._requirements_sorted? + super + else + _with_sorted_requirements == other._with_sorted_requirements + end + end + + protected + + def _requirements_sorted? + return @_are_requirements_sorted if defined?(@_are_requirements_sorted) + strings = as_list + @_are_requirements_sorted = strings == strings.sort + end + + def _with_sorted_requirements + @_with_sorted_requirements ||= _requirements_sorted? ? self : self.class.new(as_list.sort) + end + end + + prepend OrderIndependentComparison + end + end + class Platform JAVA = Gem::Platform.new("java") unless defined?(JAVA) MSWIN = Gem::Platform.new("mswin32") unless defined?(MSWIN) diff --git a/bundler/spec/install/gemfile/platform_spec.rb b/bundler/spec/install/gemfile/platform_spec.rb index e468ac70eb12..41b95481cbca 100644 --- a/bundler/spec/install/gemfile/platform_spec.rb +++ b/bundler/spec/install/gemfile/platform_spec.rb @@ -281,6 +281,35 @@ expect(the_bundle).not_to include_gem "CFPropertyList" end + it "works with gems with platform-specific dependency having different requirements order" do + simulate_platform x64_mac + + update_repo2 do + build_gem "fspath", "3" + build_gem "image_optim_pack", "1.2.3" do |s| + s.add_runtime_dependency "fspath", ">= 2.1", "< 4" + end + build_gem "image_optim_pack", "1.2.3" do |s| + s.platform = "universal-darwin" + s.add_runtime_dependency "fspath", "< 4", ">= 2.1" + end + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + G + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + + gem "image_optim_pack" + G + + expect(err).not_to include "Unable to use the platform-specific" + + expect(the_bundle).to include_gem "image_optim_pack 1.2.3 universal-darwin" + end + it "fetches gems again after changing the version of Ruby" do gemfile <<-G source "#{file_uri_for(gem_repo1)}" diff --git a/lib/rubygems/requirement.rb b/lib/rubygems/requirement.rb index d9d7c2fbad97..a2a5c7bca112 100644 --- a/lib/rubygems/requirement.rb +++ b/lib/rubygems/requirement.rb @@ -270,7 +270,7 @@ def ==(other) # :nodoc: return unless Gem::Requirement === other # An == check is always necessary - return false unless requirements == other.requirements + return false unless _sorted_requirements == other._sorted_requirements # An == check is sufficient unless any requirements use ~> return true unless _tilde_requirements.any? @@ -282,8 +282,12 @@ def ==(other) # :nodoc: protected + def _sorted_requirements + @_sorted_requirements ||= requirements.sort_by(&:to_s) + end + def _tilde_requirements - requirements.select {|r| r.first == "~>" } + @_tilde_requirements ||= _sorted_requirements.select {|r| r.first == "~>" } end private diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index af9d8077010c..20127a1e1533 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -22,6 +22,8 @@ def test_equals2 refute_requirement_equal "~> 1.3", "~> 1.3.0" refute_requirement_equal "~> 1.3.0", "~> 1.3" + assert_requirement_equal ["> 2", "~> 1.3", "~> 1.3.1"], ["~> 1.3.1", "~> 1.3", "> 2"] + assert_requirement_equal ["> 2", "~> 1.3"], ["> 2.0", "~> 1.3"] assert_requirement_equal ["> 2.0", "~> 1.3"], ["> 2", "~> 1.3"]