diff options
Diffstat (limited to 'spec/bundler/resolver')
| -rw-r--r-- | spec/bundler/resolver/basic_spec.rb | 280 | ||||
| -rw-r--r-- | spec/bundler/resolver/platform_spec.rb | 354 |
2 files changed, 560 insertions, 74 deletions
diff --git a/spec/bundler/resolver/basic_spec.rb b/spec/bundler/resolver/basic_spec.rb index 9e93847ab5..185df1b1c7 100644 --- a/spec/bundler/resolver/basic_spec.rb +++ b/spec/bundler/resolver/basic_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe "Resolving" do before :each do @@ -7,33 +6,47 @@ RSpec.describe "Resolving" do end it "resolves a single gem" do - dep "rack" + dep "myrack" - should_resolve_as %w(rack-1.1) + should_resolve_as %w[myrack-1.1] end it "resolves a gem with dependencies" do dep "actionpack" - should_resolve_as %w(actionpack-2.3.5 activesupport-2.3.5 rack-1.0) + should_resolve_as %w[actionpack-2.3.5 activesupport-2.3.5 myrack-1.0] end it "resolves a conflicting index" do @index = a_conflict_index dep "my_app" - should_resolve_as %w(activemodel-3.2.11 builder-3.0.4 grape-0.2.6 my_app-1.0.0) + should_resolve_as %w[activemodel-3.2.11 builder-3.0.4 grape-0.2.6 my_app-1.0.0] end it "resolves a complex conflicting index" do @index = a_complex_conflict_index dep "my_app" - should_resolve_as %w(a-1.4.0 b-0.3.5 c-3.2 d-0.9.8 my_app-1.1.0) + should_resolve_as %w[a-1.4.0 b-0.3.5 c-3.2 d-0.9.8 my_app-1.1.0] end it "resolves a index with conflict on child" do @index = index_with_conflict_on_child dep "chef_app" - should_resolve_as %w(berkshelf-2.0.7 chef-10.26 chef_app-1.0.0 json-1.7.7) + should_resolve_as %w[berkshelf-2.0.7 chef-10.26 chef_app-1.0.0 json-1.7.7] + end + + it "prefers explicitly requested dependencies when resolving an index which would otherwise be ambiguous" do + @index = an_ambiguous_index + dep "a" + dep "b" + should_resolve_as %w[a-1.0.0 b-2.0.0 c-1.0.0 d-1.0.0] + end + + it "prefers non-prerelease resolutions in sort order" do + @index = optional_prereleases_index + dep "a" + dep "b" + should_resolve_as %w[a-1.0.0 b-1.5.0] end it "resolves a index with root level conflict on child" do @@ -42,20 +55,70 @@ RSpec.describe "Resolving" do dep "activesupport", "~> 3.0" dep "activerecord", "~> 3.0" dep "builder", "~> 2.1.2" - should_resolve_as %w(activesupport-3.0.5 i18n-0.4.2 builder-2.1.2 activerecord-3.0.5 activemodel-3.0.5) + should_resolve_as %w[activesupport-3.0.5 i18n-0.4.2 builder-2.1.2 activerecord-3.0.5 activemodel-3.0.5] + end + + it "resolves a gem specified with a pre-release version" do + dep "activesupport", "~> 3.0.0.beta" + dep "activemerchant" + should_resolve_as %w[activemerchant-2.3.5 activesupport-3.0.0.beta1] + end + + it "doesn't select a pre-release if not specified in the Gemfile" do + dep "activesupport" + dep "reform" + should_resolve_as %w[reform-1.0.0 activesupport-2.3.5] + end + + it "doesn't select a pre-release for sub-dependencies" do + dep "reform" + should_resolve_as %w[reform-1.0.0 activesupport-2.3.5] + end + + it "selects a pre-release for sub-dependencies if it's the only option" do + dep "need-pre" + should_resolve_as %w[need-pre-1.0.0 activesupport-3.0.0.beta1] + end + + it "selects a pre-release if it's specified in the Gemfile" do + dep "activesupport", "= 3.0.0.beta" + dep "actionpack" + + should_resolve_as %w[activesupport-3.0.0.beta actionpack-3.0.0.beta myrack-1.1 myrack-mount-0.6] + end + + it "prefers non-pre-releases when doing conservative updates" do + @index = build_index do + gem "mail", "2.7.0" + gem "mail", "2.7.1.rc1" + gem "RubyGems\0", Gem::VERSION + end + dep "mail" + @locked = locked ["mail", "2.7.0"] + @base = locked + should_conservative_resolve_and_include [:patch], [], ["mail-2.7.0"] end it "raises an exception if a child dependency is not resolved" do - @index = a_unresovable_child_index + @index = a_unresolvable_child_index dep "chef_app_error" expect do resolve - end.to raise_error(Bundler::VersionConflict) + end.to raise_error(Bundler::SolveFailure) + end + + it "does not try to re-resolve including prereleases if gems involved don't have prereleases" do + @index = a_unresolvable_child_index + dep "chef_app_error" + expect(Bundler.ui).not_to receive(:debug).with("Retrying resolution...", any_args) + expect do + resolve + end.to raise_error(Bundler::SolveFailure) end it "raises an exception with the minimal set of conflicting dependencies" do @index = build_index do - %w(0.9 1.0 2.0).each {|v| gem("a", v) } + %w[0.9 1.0 2.0].each {|v| gem("a", v) } gem("b", "1.0") { dep "a", ">= 2" } gem("c", "1.0") { dep "a", "< 1" } end @@ -64,14 +127,15 @@ RSpec.describe "Resolving" do dep "c" expect do resolve - end.to raise_error(Bundler::VersionConflict, <<-E.strip) -Bundler could not find compatible versions for gem "a": - In Gemfile: - b was resolved to 1.0, which depends on - a (>= 2) - - c was resolved to 1.0, which depends on - a (< 1) + end.to raise_error(Bundler::SolveFailure, <<~E.strip) + Could not find compatible versions + + Because every version of c depends on a < 1 + and every version of b depends on a >= 2, + every version of c is incompatible with b >= 0. + So, because Gemfile depends on b >= 0 + and Gemfile depends on c >= 0, + version solving has failed. E end @@ -80,7 +144,7 @@ Bundler could not find compatible versions for gem "a": dep "circular_app" expect do - resolve + Bundler::SpecSet.new(resolve).sort end.to raise_error(Bundler::CyclicDependencyError, /please remove either gem 'bar' or gem 'foo'/i) end @@ -88,14 +152,14 @@ Bundler could not find compatible versions for gem "a": it "should install the latest possible version of a direct requirement with no constraints given" do @index = a_complicated_index dep "foo" - should_resolve_and_include %w(foo-3.0.5) + should_resolve_and_include %w[foo-3.0.5] end # Issue #3459 it "should install the latest possible version of a direct requirement with constraints given" do @index = a_complicated_index dep "foo", ">= 3.0.0" - should_resolve_and_include %w(foo-3.0.5) + should_resolve_and_include %w[foo-3.0.5] end it "takes into account required_ruby_version" do @@ -115,17 +179,12 @@ Bundler could not find compatible versions for gem "a": s.required_ruby_version = "~> 2.0.0" end - gem "ruby\0", "1.8.7" + gem "Ruby\0", "1.8.7" end dep "foo" - dep "ruby\0", "1.8.7" + dep "Ruby\0", "1.8.7" - deps = [] - @deps.each do |d| - deps << Bundler::DepProxy.new(d, "ruby") - end - - should_resolve_and_include %w(foo-1.0.0 bar-1.0.0), [{}, []] + should_resolve_and_include %w[foo-1.0.0 bar-1.0.0] end context "conservative" do @@ -139,7 +198,7 @@ Bundler could not find compatible versions for gem "a": gem("foo", "1.5.0") { dep "bar", "~> 2.1" } gem("foo", "1.5.1") { dep "bar", "~> 3.0" } gem("foo", "2.0.0") { dep "bar", "~> 3.0" } - gem "bar", %w(2.0.3 2.0.4 2.0.5 2.1.0 2.1.1 3.0.0) + gem "bar", %w[2.0.3 2.0.4 2.0.5 2.1.0 2.1.1 3.0.0] end dep "foo" @@ -147,23 +206,23 @@ Bundler could not find compatible versions for gem "a": @base = Bundler::SpecSet.new([]) # locked represents versions in lockfile - @locked = locked(%w(foo 1.4.3), %w(bar 2.0.3)) + @locked = locked(%w[foo 1.4.3], %w[bar 2.0.3]) end it "resolves all gems to latest patch" do # strict is not set, so bar goes up a minor version due to dependency from foo 1.4.5 - should_conservative_resolve_and_include :patch, [], %w(foo-1.4.5 bar-2.1.1) + should_conservative_resolve_and_include :patch, true, %w[foo-1.4.5 bar-2.1.1] end it "resolves all gems to latest patch strict" do # strict is set, so foo can only go up to 1.4.4 to avoid bar going up a minor version, and bar can go up to 2.0.5 - should_conservative_resolve_and_include [:patch, :strict], [], %w(foo-1.4.4 bar-2.0.5) + should_conservative_resolve_and_include [:patch, :strict], true, %w[foo-1.4.4 bar-2.0.5] end it "resolves foo only to latest patch - same dependency case" do - @locked = locked(%w(foo 1.3.7), %w(bar 2.0.3)) + @locked = locked(%w[foo 1.3.7], %w[bar 2.0.3]) # bar is locked, and the lock holds here because the dependency on bar doesn't change on the matching foo version. - should_conservative_resolve_and_include :patch, ["foo"], %w(foo-1.3.8 bar-2.0.3) + should_conservative_resolve_and_include :patch, ["foo"], %w[foo-1.3.8 bar-2.0.3] end it "resolves foo only to latest patch - changing dependency not declared case" do @@ -172,45 +231,45 @@ Bundler could not find compatible versions for gem "a": # dependencies and since the dependency of the selected foo gem changes, the latest matching # dependency of "bar", "~> 2.1" -- bar-2.1.1 -- is selected. This is not a bug and follows # the long-standing documented Conservative Updating behavior of bundle install. - # http://bundler.io/v1.12/man/bundle-install.1.html#CONSERVATIVE-UPDATING - should_conservative_resolve_and_include :patch, ["foo"], %w(foo-1.4.5 bar-2.1.1) + # https://bundler.io/v1.12/man/bundle-install.1.html#CONSERVATIVE-UPDATING + should_conservative_resolve_and_include :patch, ["foo"], %w[foo-1.4.5 bar-2.1.1] end it "resolves foo only to latest patch - changing dependency declared case" do # bar is locked AND a declared dependency in the Gemfile, so it will not move, and therefore # foo can only move up to 1.4.4. - @base << build_spec("bar", "2.0.3").first - should_conservative_resolve_and_include :patch, ["foo"], %w(foo-1.4.4 bar-2.0.3) + @base = Bundler::SpecSet.new([Bundler::LazySpecification.new("bar", Gem::Version.new("2.0.3"), nil)]) + should_conservative_resolve_and_include :patch, ["foo"], %w[foo-1.4.4 bar-2.0.3] end it "resolves foo only to latest patch strict" do # adding strict helps solve the possibly unexpected behavior of bar changing in the prior test case, # because no versions will be returned for bar ~> 2.1, so the engine falls back to ~> 2.0 (turn on # debugging to see this happen). - should_conservative_resolve_and_include [:patch, :strict], ["foo"], %w(foo-1.4.4 bar-2.0.3) + should_conservative_resolve_and_include [:patch, :strict], ["foo"], %w[foo-1.4.4 bar-2.0.3] end it "resolves bar only to latest patch" do # bar is locked, so foo can only go up to 1.4.4 - should_conservative_resolve_and_include :patch, ["bar"], %w(foo-1.4.3 bar-2.0.5) + should_conservative_resolve_and_include :patch, ["bar"], %w[foo-1.4.3 bar-2.0.5] end it "resolves all gems to latest minor" do # strict is not set, so bar goes up a major version due to dependency from foo 1.4.5 - should_conservative_resolve_and_include :minor, [], %w(foo-1.5.1 bar-3.0.0) + should_conservative_resolve_and_include :minor, true, %w[foo-1.5.1 bar-3.0.0] end it "resolves all gems to latest minor strict" do # strict is set, so foo can only go up to 1.5.0 to avoid bar going up a major version - should_conservative_resolve_and_include [:minor, :strict], [], %w(foo-1.5.0 bar-2.1.1) + should_conservative_resolve_and_include [:minor, :strict], true, %w[foo-1.5.0 bar-2.1.1] end it "resolves all gems to latest major" do - should_conservative_resolve_and_include :major, [], %w(foo-2.0.0 bar-3.0.0) + should_conservative_resolve_and_include :major, true, %w[foo-2.0.0 bar-3.0.0] end it "resolves all gems to latest major strict" do - should_conservative_resolve_and_include [:major, :strict], [], %w(foo-2.0.0 bar-3.0.0) + should_conservative_resolve_and_include [:major, :strict], true, %w[foo-2.0.0 bar-3.0.0] end # Why would this happen in real life? If bar 2.2 has a bug that the author of foo wants to bypass @@ -221,7 +280,7 @@ Bundler could not find compatible versions for gem "a": gem("foo", "1.4.3") { dep "bar", "~> 2.2" } gem("foo", "1.4.4") { dep "bar", "~> 2.1.0" } gem("foo", "1.5.0") { dep "bar", "~> 2.0.0" } - gem "bar", %w(2.0.5 2.1.1 2.2.3) + gem "bar", %w[2.0.5 2.1.1 2.2.3] end dep "foo" @@ -229,30 +288,135 @@ Bundler could not find compatible versions for gem "a": @base = Bundler::SpecSet.new([]) # locked represents versions in lockfile - @locked = locked(%w(foo 1.4.3), %w(bar 2.2.3)) + @locked = locked(%w[foo 1.4.3], %w[bar 2.2.3]) end it "could revert to a previous version level patch" do - should_conservative_resolve_and_include :patch, [], %w(foo-1.4.4 bar-2.1.1) + should_conservative_resolve_and_include :patch, true, %w[foo-1.4.4 bar-2.1.1] end it "cannot revert to a previous version in strict mode level patch" do - # the strict option removes the version required to match, so a version conflict results - expect do - should_conservative_resolve_and_include [:patch, :strict], [], %w(foo-1.4.3 bar-2.1.1) - end.to raise_error Bundler::VersionConflict, /#{Regexp.escape("Could not find gem 'bar (~> 2.1.0)'")}/ + # fall back to the locked resolution since strict means we can't regress either version + should_conservative_resolve_and_include [:patch, :strict], true, %w[foo-1.4.3 bar-2.2.3] end it "could revert to a previous version level minor" do - should_conservative_resolve_and_include :minor, [], %w(foo-1.5.0 bar-2.0.5) + should_conservative_resolve_and_include :minor, true, %w[foo-1.5.0 bar-2.0.5] end it "cannot revert to a previous version in strict mode level minor" do - # the strict option removes the version required to match, so a version conflict results - expect do - should_conservative_resolve_and_include [:minor, :strict], [], %w(foo-1.4.3 bar-2.1.1) - end.to raise_error Bundler::VersionConflict, /#{Regexp.escape("Could not find gem 'bar (~> 2.0.0)'")}/ + # fall back to the locked resolution since strict means we can't regress either version + should_conservative_resolve_and_include [:minor, :strict], true, %w[foo-1.4.3 bar-2.2.3] + end + end + end + + it "handles versions that redundantly depend on themselves" do + @index = build_index do + gem "myrack", "3.0.0" + + gem "standalone_migrations", "7.1.0" do + dep "myrack", "~> 2.0" + end + + gem "standalone_migrations", "2.0.4" do + dep "standalone_migrations", ">= 0" + end + + gem "standalone_migrations", "1.0.13" do + dep "myrack", ">= 0" + end + end + + dep "myrack", "~> 3.0" + dep "standalone_migrations" + + should_resolve_as %w[myrack-3.0.0 standalone_migrations-2.0.4] + end + + it "ignores versions that incorrectly depend on themselves" do + @index = build_index do + gem "myrack", "3.0.0" + + gem "standalone_migrations", "7.1.0" do + dep "myrack", "~> 2.0" + end + + gem "standalone_migrations", "2.0.4" do + dep "standalone_migrations", ">= 2.0.5" + end + + gem "standalone_migrations", "1.0.13" do + dep "myrack", ">= 0" + end + end + + dep "myrack", "~> 3.0" + dep "standalone_migrations" + + should_resolve_as %w[myrack-3.0.0 standalone_migrations-1.0.13] + end + + it "does not ignore versions that incorrectly depend on themselves when dependency_api is not available" do + @index = build_index do + gem "myrack", "3.0.0" + + gem "standalone_migrations", "7.1.0" do + dep "myrack", "~> 2.0" + end + + gem "standalone_migrations", "2.0.4" do + dep "standalone_migrations", ">= 2.0.5" + end + + gem "standalone_migrations", "1.0.13" do + dep "myrack", ">= 0" end end + + dep "myrack", "~> 3.0" + dep "standalone_migrations" + + should_resolve_without_dependency_api %w[myrack-3.0.0 standalone_migrations-2.0.4] + end + + it "resolves fine cases that need joining unbounded disjoint ranges" do + @index = build_index do + gem "inspec", "5.22.3" do + dep "ruby", ">= 3.2.2" + dep "train-kubernetes", ">= 0.1.7" + end + + gem "ruby", "3.2.2" + + gem "train-kubernetes", "0.1.12" do + dep "k8s-ruby", ">= 0.14.0" + end + + gem "train-kubernetes", "0.1.10" do + dep "k8s-ruby", "= 0.10.5" + end + + gem "train-kubernetes", "0.1.7" do + dep "k8s-ruby", ">= 0.10.5" + end + + gem "k8s-ruby", "0.10.5" do + dep "ruby","< 3.2.2" + end + + gem "k8s-ruby", "0.11.0" do + dep "ruby", ">= 3.2.2" + end + + gem "k8s-ruby", "0.14.0" do + dep "ruby", "< 3.2.2" + end + end + + dep "inspec", "5.22.3" + dep "ruby", "3.2.2" + + should_resolve_as %w[inspec-5.22.3 ruby-3.2.2 train-kubernetes-0.1.7 k8s-ruby-0.11.0] end end diff --git a/spec/bundler/resolver/platform_spec.rb b/spec/bundler/resolver/platform_spec.rb index 90d6f637ce..a1d095d024 100644 --- a/spec/bundler/resolver/platform_spec.rb +++ b/spec/bundler/resolver/platform_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe "Resolving platform craziness" do describe "with cross-platform gems" do @@ -11,28 +10,339 @@ RSpec.describe "Resolving platform craziness" do dep "nokogiri" platforms "ruby", "java" - should_resolve_as %w(nokogiri-1.4.2 nokogiri-1.4.2-java weakling-0.0.3) + should_resolve_as %w[nokogiri-1.4.2 nokogiri-1.4.2-java weakling-0.0.3] end it "doesn't pull gems that don't exist for the current platform" do dep "nokogiri" platforms "ruby" - should_resolve_as %w(nokogiri-1.4.2) + should_resolve_as %w[nokogiri-1.4.2] end it "doesn't pull gems when the version is available for all requested platforms" do dep "nokogiri" platforms "mswin32" - should_resolve_as %w(nokogiri-1.4.2.1-x86-mswin32) + should_resolve_as %w[nokogiri-1.4.2.1-x86-mswin32] end end + it "resolves multiplatform gems with redundant platforms correctly" do + @index = build_index do + gem "zookeeper", "1.4.11" + gem "zookeeper", "1.4.11", "java" do + dep "slyphon-log4j", "= 1.2.15" + dep "slyphon-zookeeper_jar", "= 3.3.5" + end + gem "slyphon-log4j", "1.2.15" + gem "slyphon-zookeeper_jar", "3.3.5", "java" + end + + dep "zookeeper" + platforms "java", "ruby", "universal-java-11" + + should_resolve_as %w[zookeeper-1.4.11 zookeeper-1.4.11-java slyphon-log4j-1.2.15 slyphon-zookeeper_jar-3.3.5-java] + end + + it "takes the latest ruby gem, even if an older platform specific version is available" do + @index = build_index do + gem "foo", "1.0.0" + gem "foo", "1.0.0", "x64-mingw-ucrt" + gem "foo", "1.1.0" + end + dep "foo" + platforms "x64-mingw-ucrt" + + should_resolve_as %w[foo-1.1.0] + end + + it "takes the ruby version if the platform version is incompatible" do + @index = build_index do + gem "bar", "1.0.0" + gem "foo", "1.0.0" + gem "foo", "1.0.0", "x64-mingw-ucrt" do + dep "bar", "< 1" + end + end + dep "foo" + platforms "x64-mingw-ucrt" + + 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-mingw-ucrt" + end + dep "foo" + platforms "x64-mingw-ucrt" + + should_resolve_as %w[foo-1.0.0-x64-mingw-ucrt] + end + + describe "on a linux platform" do + # Ruby's platform is *-linux => platform's libc is glibc, so not musl + # Ruby's platform is *-linux-musl => platform's libc is musl, so not glibc + # Gem's platform is *-linux => gem is glibc + maybe musl compatible + # Gem's platform is *-linux-musl => gem is musl compatible but not glibc + + it "favors the platform version-specific gem on a version-specifying linux platform" do + @index = build_index do + gem "foo", "1.0.0" + gem "foo", "1.0.0", "x86_64-linux" + gem "foo", "1.0.0", "x86_64-linux-musl" + end + dep "foo" + platforms "x86_64-linux-musl" + + should_resolve_as %w[foo-1.0.0-x86_64-linux-musl] + end + + it "favors the version-less gem over the version-specific gem on a gnu linux platform" do + @index = build_index do + gem "foo", "1.0.0" + gem "foo", "1.0.0", "x86_64-linux" + gem "foo", "1.0.0", "x86_64-linux-musl" + end + dep "foo" + platforms "x86_64-linux" + + should_resolve_as %w[foo-1.0.0-x86_64-linux] + end + + it "ignores the platform version-specific gem on a gnu linux platform" do + @index = build_index do + gem "foo", "1.0.0", "x86_64-linux-musl" + end + dep "foo" + platforms "x86_64-linux" + + should_not_resolve + end + + it "falls back to the platform version-less gem on a linux platform with a version" do + @index = build_index do + gem "foo", "1.0.0" + gem "foo", "1.0.0", "x86_64-linux" + end + dep "foo" + platforms "x86_64-linux-musl" + + should_resolve_as %w[foo-1.0.0-x86_64-linux] + end + + it "falls back to the ruby platform gem on a gnu linux platform when only a version-specifying gem is available" do + @index = build_index do + gem "foo", "1.0.0" + gem "foo", "1.0.0", "x86_64-linux-musl" + end + dep "foo" + platforms "x86_64-linux" + + should_resolve_as %w[foo-1.0.0] + end + + it "falls back to the platform version-less gem on a version-specifying linux platform and no ruby platform gem is available" do + @index = build_index do + gem "foo", "1.0.0", "x86_64-linux" + end + dep "foo" + platforms "x86_64-linux-musl" + + should_resolve_as %w[foo-1.0.0-x86_64-linux] + end + end + + context "when the platform specific gem doesn't match the required_ruby_version" do + before do + @index = build_index do + gem "foo", "1.0.0" + gem "foo", "1.0.0", "x64-mingw-ucrt" + gem "foo", "1.1.0" + gem "foo", "1.1.0", "x64-mingw-ucrt" do |s| + s.required_ruby_version = [">= 2.0", "< 2.4"] + end + gem "Ruby\0", "2.5.1" + end + dep "Ruby\0", "2.5.1" + platforms "x64-mingw-ucrt" + end + + it "takes the latest ruby gem" do + dep "foo" + + should_resolve_as %w[foo-1.1.0] + end + + it "takes the latest ruby gem, even if requirement does not match previous versions with the same ruby requirement" do + dep "foo", "1.1.0" + + should_resolve_as %w[foo-1.1.0] + end + end + + it "takes the latest ruby gem with required_ruby_version if the platform specific gem doesn't match the required_ruby_version" do + @index = build_index do + gem "foo", "1.0.0" + gem "foo", "1.0.0", "x64-mingw-ucrt" + gem "foo", "1.1.0" do |s| + s.required_ruby_version = [">= 2.0"] + end + gem "foo", "1.1.0", "x64-mingw-ucrt" do |s| + s.required_ruby_version = [">= 2.0", "< 2.4"] + end + gem "Ruby\0", "2.5.1" + end + dep "foo" + dep "Ruby\0", "2.5.1" + platforms "x64-mingw-ucrt" + + should_resolve_as %w[foo-1.1.0] + end + + it "takes the latest ruby gem if the platform specific gem doesn't match the required_ruby_version with multiple platforms" do + @index = build_index do + gem "foo", "1.0.0" + gem "foo", "1.0.0", "x64-mingw-ucrt" + gem "foo", "1.1.0" do |s| + s.required_ruby_version = [">= 2.0"] + end + gem "foo", "1.1.0", "x64-mingw-ucrt" do |s| + s.required_ruby_version = [">= 2.0", "< 2.4"] + end + gem "Ruby\0", "2.5.1" + end + dep "foo" + dep "Ruby\0", "2.5.1" + platforms "x86_64-linux", "x64-mingw-ucrt" + + should_resolve_as %w[foo-1.1.0] + end + + it "includes gems needed for at least one platform" do + @index = build_index do + gem "empyrean", "0.1.0" + gem "coderay", "1.1.2" + gem "method_source", "0.9.0" + + gem "spoon", "0.0.6" do + dep "ffi", ">= 0" + end + + gem "pry", "0.11.3", "java" do + dep "coderay", "~> 1.1.0" + dep "method_source", "~> 0.9.0" + dep "spoon", "~> 0.0" + end + + gem "pry", "0.11.3" do + dep "coderay", "~> 1.1.0" + dep "method_source", "~> 0.9.0" + end + + gem "ffi", "1.9.23", "java" + gem "ffi", "1.9.23" + + gem "extra", "1.0.0" do + dep "ffi", ">= 0" + end + end + + dep "empyrean", "0.1.0" + dep "pry" + dep "extra" + + platforms "ruby", "java" + + should_resolve_as %w[coderay-1.1.2 empyrean-0.1.0 extra-1.0.0 ffi-1.9.23 ffi-1.9.23-java method_source-0.9.0 pry-0.11.3 pry-0.11.3-java spoon-0.0.6] + end + + it "includes gems needed for at least one platform even when the platform specific requirement is processed earlier than the generic requirement" do + @index = build_index do + gem "empyrean", "0.1.0" + gem "coderay", "1.1.2" + gem "method_source", "0.9.0" + + gem "spoon", "0.0.6" do + dep "ffi", ">= 0" + end + + gem "pry", "0.11.3", "java" do + dep "coderay", "~> 1.1.0" + dep "method_source", "~> 0.9.0" + dep "spoon", "~> 0.0" + end + + gem "pry", "0.11.3" do + dep "coderay", "~> 1.1.0" + dep "method_source", "~> 0.9.0" + end + + gem "ffi", "1.9.23", "java" + gem "ffi", "1.9.23" + + gem "extra", "1.0.0" do + dep "extra2", ">= 0" + end + + gem "extra2", "1.0.0" do + dep "extra3", ">= 0" + end + + gem "extra3", "1.0.0" do + dep "ffi", ">= 0" + end + end + + dep "empyrean", "0.1.0" + dep "pry" + dep "extra" + + platforms "ruby", "java" + + should_resolve_as %w[coderay-1.1.2 empyrean-0.1.0 extra-1.0.0 extra2-1.0.0 extra3-1.0.0 ffi-1.9.23 ffi-1.9.23-java method_source-0.9.0 pry-0.11.3 pry-0.11.3-java spoon-0.0.6] + end + + it "properly adds platforms when platform requirements come from different dependencies" do + @index = build_index do + gem "ffi", "1.9.14" + gem "ffi", "1.9.14", "universal-mingw32" + + gem "gssapi", "0.1" + gem "gssapi", "0.2" + gem "gssapi", "0.3" + gem "gssapi", "1.2.0" do + dep "ffi", ">= 1.0.1" + end + + gem "mixlib-shellout", "2.2.6" + gem "mixlib-shellout", "2.2.6", "universal-mingw32" do + dep "win32-process", "~> 0.8.2" + end + + # we need all these versions to get the sorting the same as it would be + # pulling from rubygems.org + %w[0.8.3 0.8.2 0.8.1 0.8.0].each do |v| + gem "win32-process", v do + dep "ffi", ">= 1.0.0" + end + end + end + + dep "mixlib-shellout" + dep "gssapi" + + platforms "universal-mingw32", "ruby" + + should_resolve_as %w[ffi-1.9.14 ffi-1.9.14-universal-mingw32 gssapi-1.2.0 mixlib-shellout-2.2.6 mixlib-shellout-2.2.6-universal-mingw32 win32-process-0.8.3] + end + describe "with mingw32" do before :each do @index = build_index do - platforms "mingw32 mswin32 x64-mingw32" do |platform| + platforms "mingw32 mswin32 x64-mingw-ucrt" do |platform| gem "thin", "1.2.7", platform end gem "win32-api", "1.5.1", "universal-mingw32" @@ -43,32 +353,44 @@ RSpec.describe "Resolving platform craziness" do # win32 is hardcoded to get CPU x86 in rubygems platforms "mswin32" dep "thin" - should_resolve_as %w(thin-1.2.7-x86-mswin32) + should_resolve_as %w[thin-1.2.7-x86-mswin32] end it "finds mingw gems" do # mingw is _not_ hardcoded to add CPU x86 in rubygems platforms "x86-mingw32" dep "thin" - should_resolve_as %w(thin-1.2.7-mingw32) + should_resolve_as %w[thin-1.2.7-mingw32] end - it "finds x64-mingw gems" do - platforms "x64-mingw32" + it "finds x64-mingw-ucrt gems" do + platforms "x64-mingw-ucrt" dep "thin" - should_resolve_as %w(thin-1.2.7-x64-mingw32) + should_resolve_as %w[thin-1.2.7-x64-mingw-ucrt] end it "finds universal-mingw gems on x86-mingw" do platform "x86-mingw32" dep "win32-api" - should_resolve_as %w(win32-api-1.5.1-universal-mingw32) + should_resolve_as %w[win32-api-1.5.1-universal-mingw32] end it "finds universal-mingw gems on x64-mingw" do - platform "x64-mingw32" + platform "x64-mingw-ucrt" + dep "win32-api" + should_resolve_as %w[win32-api-1.5.1-universal-mingw32] + end + + it "finds x64-mingw-ucrt gems" do + platforms "x64-mingw-ucrt" + dep "thin" + should_resolve_as %w[thin-1.2.7-x64-mingw-ucrt] + end + + it "finds universal-mingw gems on x64-mingw-ucrt" do + platform "x64-mingw-ucrt" dep "win32-api" - should_resolve_as %w(win32-api-1.5.1-universal-mingw32) + should_resolve_as %w[win32-api-1.5.1-universal-mingw32] end end @@ -87,15 +409,15 @@ RSpec.describe "Resolving platform craziness" do dep "baz", " ~> 1.1.0" end - gem "baz", %w(1.0.0 1.1.0 1.2.0) + gem "baz", %w[1.0.0 1.1.0 1.2.0] end end - it "reports on the conflict" do + it "takes the ruby version as fallback" do platforms "ruby", "java" dep "foo" - should_conflict_on "baz" + should_resolve_as %w[bar-1.0.0 baz-1.0.0 foo-1.0.0] end end end |
