diff options
author | Bundlerbot <bot@bundler.io> | 2020-01-16 09:53:03 +0000 |
---|---|---|
committer | Bundlerbot <bot@bundler.io> | 2020-01-16 09:53:03 +0000 |
commit | d852b30b66165dbb88682f72a8929568af7e7c57 (patch) | |
tree | 7283342f31444b20580aedfbc64679bd1ab00a2e /lib/bundler/resolver/spec_group.rb | |
parent | 14fb40d464562e2f12cf78a8713f6597cc682b00 (diff) | |
parent | e96b6b36146c3fab3a956dddb79c79822ebbb5ab (diff) | |
download | bundler-d852b30b66165dbb88682f72a8929568af7e7c57.tar.gz |
Merge #7522
7522: Improve platform specific gem resolution r=deivid-rodriguez a=kou
### What was the end-user problem that led to this PR?
Platform specific gems aren't resolved when platform specific gems are conflicted.
For example, in the following situation, foo-1.0.0-x64-mingw32 that requires bar<1 is conflicted because there is no bar<1. Without this change, Bundler raises a conflict error. But users can use foo-1.0.0 (no x64-mingw32) in this situation. With this change, Bundler resolves to foo-1.0.0 (no x64-mingw32).
```ruby
@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"
````
See also #6247. This change includes the specs that were added in #6247.
### What was your diagnosis of the problem?
Not platform specific gem (foo-1.0.0 in the above case) isn't tried to be resolved when platform specific gem (foo-1.0.0-x64-mingw32 in the above case) is available.
### What is your fix for the problem, implemented in this PR?
In this PR, not platform specific gem (foo-1.0.0 in the above case) is also tried to be resolved even when platform specific gem (foo-1.0.0-x64-mingw32 in the above case) is available. Priority is "platform specific gem" -> "not platform specific gem". So platform specific gem is usable, platform specific gem is used. Not platform specific gem is used as fallback.
`search_for` represents this. Here is the `search_for` specification:
https://github.com/bundler/bundler/blob/master/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb#L11-L13
> Search for the specifications that match the given dependency. The specifications in the returned array will be considered in reverse order, so the latest version ought to be last.
## Why did you choose this fix out of the possible options?
I choose this fix because this is based on Molinillo's specification.
Co-authored-by: Lars Kanis <lars@greiz-reinsdorf.de>
Co-authored-by: Samuel Giddins <segiddins@segiddins.me>
Co-authored-by: Sutou Kouhei <kou@clear-code.com>
Diffstat (limited to 'lib/bundler/resolver/spec_group.rb')
-rw-r--r-- | lib/bundler/resolver/spec_group.rb | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/lib/bundler/resolver/spec_group.rb b/lib/bundler/resolver/spec_group.rb index e5772eed81..d5d12f7a2d 100644 --- a/lib/bundler/resolver/spec_group.rb +++ b/lib/bundler/resolver/spec_group.rb @@ -9,6 +9,7 @@ module Bundler 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 @@ -28,7 +29,7 @@ module Bundler lazy_spec = LazySpecification.new(name, version, s.platform, source) lazy_spec.dependencies.replace s.dependencies lazy_spec - end.compact + end.compact.uniq end def activate_platform!(platform) @@ -37,13 +38,25 @@ module Bundler @activated_platforms << platform end + def copy_for(platform) + copied_sg = self.class.new(@all_specs) + copied_sg.ignores_bundler_dependencies = @ignores_bundler_dependencies + return nil unless copied_sg.for?(platform) + copied_sg.activate_platform!(platform) + copied_sg + end + + def spec_for(platform) + @specs[platform] + end + def for?(platform) - spec = @specs[platform] - !spec.nil? + !spec_for(platform).nil? end def to_s - @to_s ||= "#{name} (#{version})" + activated_platforms_string = sorted_activated_platforms.join(", ") + "#{name} (#{version}) (#{activated_platforms_string})" end def dependencies_for_activated_platforms @@ -58,6 +71,7 @@ module Bundler return unless other.is_a?(SpecGroup) name == other.name && version == other.version && + sorted_activated_platforms == other.sorted_activated_platforms && source == other.source end @@ -65,11 +79,18 @@ module Bundler return unless other.is_a?(SpecGroup) name.eql?(other.name) && version.eql?(other.version) && + sorted_activated_platforms.eql?(other.sorted_activated_platforms) && source.eql?(other.source) end def hash - to_s.hash ^ source.hash + name.hash ^ version.hash ^ sorted_activated_platforms.hash ^ source.hash + end + + protected + + def sorted_activated_platforms + @activated_platforms.sort_by(&:to_s) end private |