summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSutou Kouhei <kou@clear-code.com>2019-12-30 06:36:42 +0900
committerSutou Kouhei <kou@clear-code.com>2020-01-15 06:27:03 +0900
commit22857e2d63b700077b33398b0ae86201d06ebc79 (patch)
treea3af1895e0b43f5af5c2f432c01716966a8542fe
parent121305c0655dde7de600e62150f053c07d3dade5 (diff)
downloadbundler-22857e2d63b700077b33398b0ae86201d06ebc79.tar.gz
Improve platform specific gem resolution
It resolves #6247. This changes includes the patches that add (RSpec) specs for this situation in #6247. If there is a platform specific gem but it can't be resolved available version, Bundler reports an error. For example, @index = build_index do gem "bar", "1.0.0" gem "foo", "1.0.0" gem "foo", "1.0.0", "x64-mingw32" do dep "bar", "< 1" end end dep "foo" platforms "x64-mingw32" raises an error because foo-1.0.0-x64-mingw32 requires bar<1 but there isn't bar<1. With this change, foo-1.0.0 (no x64-mingw32) is used as fallback. Because foo-1.0.0 doesn't depend on bar<1.
-rw-r--r--lib/bundler/resolver.rb20
-rw-r--r--lib/bundler/resolver/spec_group.rb9
-rw-r--r--spec/resolver/platform_spec.rb11
3 files changed, 34 insertions, 6 deletions
diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb
index c7caf01c7d..9753efd088 100644
--- a/lib/bundler/resolver.rb
+++ b/lib/bundler/resolver.rb
@@ -146,7 +146,21 @@ module Bundler
@gem_version_promoter.sort_versions(dependency, spec_groups)
end
end
- search.select {|sg| sg.for?(platform) }.each {|sg| sg.activate_platform!(platform) }
+ selected_sgs = []
+ search.each do |sg|
+ next unless sg.for?(platform)
+ sg.activate_platform!(platform)
+ if sg.spec(platform).platform != Gem::Platform::RUBY
+ sg_ruby = SpecGroup.new(sg.all_specs)
+ sg_ruby.ignores_bundler_dependencies = sg.ignores_bundler_dependencies
+ if sg_ruby.for?(Gem::Platform::RUBY)
+ sg_ruby.activate_platform!(Gem::Platform::RUBY)
+ selected_sgs << sg_ruby
+ end
+ end
+ selected_sgs << sg
+ end
+ selected_sgs
end
def index_for(dependency)
@@ -183,9 +197,7 @@ module Bundler
end
def requirement_satisfied_by?(requirement, activated, spec)
- return false unless requirement.matches_spec?(spec) || spec.source.is_a?(Source::Gemspec)
- spec.activate_platform!(requirement.__platform) if !@platforms || @platforms.include?(requirement.__platform)
- true
+ requirement.matches_spec?(spec) || spec.source.is_a?(Source::Gemspec)
end
def relevant_sources_for_vertex(vertex)
diff --git a/lib/bundler/resolver/spec_group.rb b/lib/bundler/resolver/spec_group.rb
index e5772eed81..f79797a3ca 100644
--- a/lib/bundler/resolver/spec_group.rb
+++ b/lib/bundler/resolver/spec_group.rb
@@ -5,10 +5,12 @@ module Bundler
class SpecGroup
include GemHelpers
+ attr_reader :all_specs
attr_accessor :name, :version, :source
attr_accessor :ignores_bundler_dependencies
def initialize(all_specs)
+ @all_specs = all_specs
raise ArgumentError, "cannot initialize with an empty value" unless exemplary_spec = all_specs.first
@name = exemplary_spec.name
@version = exemplary_spec.version
@@ -37,9 +39,12 @@ module Bundler
@activated_platforms << platform
end
+ def spec(platform)
+ @specs[platform]
+ end
+
def for?(platform)
- spec = @specs[platform]
- !spec.nil?
+ !spec(platform).nil?
end
def to_s
diff --git a/spec/resolver/platform_spec.rb b/spec/resolver/platform_spec.rb
index 223320fe7b..9a97a2c67c 100644
--- a/spec/resolver/platform_spec.rb
+++ b/spec/resolver/platform_spec.rb
@@ -54,6 +54,17 @@ RSpec.describe "Resolving platform craziness" do
should_resolve_as %w[foo-1.0.0]
end
+ it "prefers the platform specific gem to the ruby version" do
+ @index = build_index do
+ gem "foo", "1.0.0"
+ gem "foo", "1.0.0", "x64-mingw32"
+ end
+ dep "foo"
+ platforms "x64-mingw32"
+
+ should_resolve_as %w[foo-1.0.0-x64-mingw32]
+ end
+
it "takes the latest ruby gem if the platform specific gem doesn't match the required_ruby_version" do
@index = build_index do
gem "foo", "1.0.0"