diff options
author | Hiroshi SHIBATA <[email protected]> | 2022-11-12 06:00:58 +0900 |
---|---|---|
committer | Hiroshi SHIBATA <[email protected]> | 2022-11-12 07:40:31 +0900 |
commit | 0a9d51ee9d2b3d0111832e5ea1c8195a16e2f99b (patch) | |
tree | 4ecad2ecbcbb06893f20fe900e04b3d982b420e1 /spec | |
parent | 14a1394bcd85c90c9f14f687fd4a80ba5b96b437 (diff) |
Migrate our resolver engine to PubGrub
https://github.com/rubygems/rubygems/pull/5960
Co-authored-by: David RodrÃguez <[email protected]>
Diffstat (limited to 'spec')
-rw-r--r-- | spec/bundler/bundler/definition_spec.rb | 25 | ||||
-rw-r--r-- | spec/bundler/bundler/gem_version_promoter_spec.rb | 87 | ||||
-rw-r--r-- | spec/bundler/bundler/resolver/candidate_spec.rb | 10 | ||||
-rw-r--r-- | spec/bundler/bundler/version_ranges_spec.rb | 40 | ||||
-rw-r--r-- | spec/bundler/install/bundler_spec.rb | 56 | ||||
-rw-r--r-- | spec/bundler/install/gemfile/git_spec.rb | 2 | ||||
-rw-r--r-- | spec/bundler/install/gemfile/sources_spec.rb | 22 | ||||
-rw-r--r-- | spec/bundler/install/gemfile/specific_platform_spec.rb | 10 | ||||
-rw-r--r-- | spec/bundler/install/gems/flex_spec.rb | 10 | ||||
-rw-r--r-- | spec/bundler/install/gems/resolving_spec.rb | 66 | ||||
-rw-r--r-- | spec/bundler/realworld/edgecases_spec.rb | 3 | ||||
-rw-r--r-- | spec/bundler/resolver/basic_spec.rb | 21 | ||||
-rw-r--r-- | spec/bundler/resolver/platform_spec.rb | 33 | ||||
-rw-r--r-- | spec/bundler/runtime/inline_spec.rb | 6 | ||||
-rw-r--r-- | spec/bundler/support/indexes.rb | 29 |
15 files changed, 181 insertions, 239 deletions
diff --git a/spec/bundler/bundler/definition_spec.rb b/spec/bundler/bundler/definition_spec.rb index e7235a4e78..372fa2d5e2 100644 --- a/spec/bundler/bundler/definition_spec.rb +++ b/spec/bundler/bundler/definition_spec.rb @@ -193,31 +193,6 @@ RSpec.describe Bundler::Definition do describe "initialize" do context "gem version promoter" do - context "with lockfile" do - before do - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - gem "foo" - G - - allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) - end - - it "should get a locked specs list when updating all" do - definition = Bundler::Definition.new(bundled_app_lock, [], Bundler::SourceList.new, true) - locked_specs = definition.gem_version_promoter.locked_specs - expect(locked_specs.to_a.map(&:name)).to eq ["foo"] - expect(definition.instance_variable_get("@locked_specs").empty?).to eq true - end - end - - context "without gemfile or lockfile" do - it "should not attempt to parse empty lockfile contents" do - definition = Bundler::Definition.new(nil, [], mock_source_list, true) - expect(definition.gem_version_promoter.locked_specs.to_a).to eq [] - end - end - context "eager unlock" do let(:source_list) do Bundler::SourceList.new.tap do |source_list| diff --git a/spec/bundler/bundler/gem_version_promoter_spec.rb b/spec/bundler/bundler/gem_version_promoter_spec.rb index 54c559c1d8..b6f10be2aa 100644 --- a/spec/bundler/bundler/gem_version_promoter_spec.rb +++ b/spec/bundler/bundler/gem_version_promoter_spec.rb @@ -6,35 +6,32 @@ RSpec.describe Bundler::GemVersionPromoter do result.flatten.map(&:version).map(&:to_s) end - def make_instance(*args) - @gvp = Bundler::GemVersionPromoter.new(*args).tap do |gvp| + def make_instance + @gvp = Bundler::GemVersionPromoter.new.tap do |gvp| gvp.class.class_eval { public :filter_dep_specs, :sort_dep_specs } end end - def unlocking(options) - make_instance(Bundler::SpecSet.new([]), ["foo"]).tap do |p| + def with_options(options) + make_instance.tap do |p| p.level = options[:level] if options[:level] p.strict = options[:strict] if options[:strict] end end - def keep_locked(options) - make_instance(Bundler::SpecSet.new([]), ["bar"]).tap do |p| - p.level = options[:level] if options[:level] - p.strict = options[:strict] if options[:strict] + def build_candidates(versions) + versions.map do |v| + Bundler::Resolver::Candidate.new(v) end end - def build_spec_groups(name, versions) - versions.map do |v| - Bundler::Resolver::SpecGroup.new(build_spec(name, v), [Gem::Platform::RUBY]) - end + def build_spec_set(name, v) + Bundler::SpecSet.new(build_spec(name, v)) end # Rightmost (highest array index) in result is most preferred. # Leftmost (lowest array index) in result is least preferred. - # `build_spec_groups` has all versions of gem in index. + # `build_candidates` has all versions of gem in index. # `build_spec` is the version currently in the .lock file. # # In default (not strict) mode, all versions in the index will @@ -43,28 +40,28 @@ RSpec.describe Bundler::GemVersionPromoter do # would not consider conservative. context "filter specs (strict) level patch" do it "when keeping build_spec, keep current, next release" do - keep_locked(:level => :patch) + with_options(:level => :patch) res = @gvp.filter_dep_specs( - build_spec_groups("foo", %w[1.7.8 1.7.9 1.8.0]), - build_spec("foo", "1.7.8").first + build_candidates(%w[1.7.8 1.7.9 1.8.0]), + Bundler::Resolver::Package.new("foo", [], build_spec_set("foo", "1.7.8"), []) ) - expect(versions(res)).to eq %w[1.7.9 1.7.8] + expect(versions(res)).to match_array %w[1.7.9 1.7.8] end it "when unlocking prefer next release first" do - unlocking(:level => :patch) + with_options(:level => :patch) res = @gvp.filter_dep_specs( - build_spec_groups("foo", %w[1.7.8 1.7.9 1.8.0]), - build_spec("foo", "1.7.8").first + build_candidates(%w[1.7.8 1.7.9 1.8.0]), + Bundler::Resolver::Package.new("foo", [], build_spec_set("foo", "1.7.8"), []) ) expect(versions(res)).to eq %w[1.7.8 1.7.9] end it "when unlocking keep current when already at latest release" do - unlocking(:level => :patch) + with_options(:level => :patch) res = @gvp.filter_dep_specs( - build_spec_groups("foo", %w[1.7.9 1.8.0 2.0.0]), - build_spec("foo", "1.7.9").first + build_candidates(%w[1.7.9 1.8.0 2.0.0]), + Bundler::Resolver::Package.new("foo", [], build_spec_set("foo", "1.7.9"), []) ) expect(versions(res)).to eq %w[1.7.9] end @@ -72,57 +69,57 @@ RSpec.describe Bundler::GemVersionPromoter do context "filter specs (strict) level minor" do it "when unlocking favor next releases, remove minor and major increases" do - unlocking(:level => :minor) + with_options(:level => :minor) res = @gvp.filter_dep_specs( - build_spec_groups("foo", %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.0 2.0.1]), - build_spec("foo", "0.2.0").first + build_candidates(%w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.0 2.0.1]), + Bundler::Resolver::Package.new("foo", [], build_spec_set("foo", "0.2.0"), []) ) expect(versions(res)).to eq %w[0.2.0 0.3.0 0.3.1 0.9.0] end it "when keep locked, keep current, then favor next release, remove minor and major increases" do - keep_locked(:level => :minor) + with_options(:level => :minor) res = @gvp.filter_dep_specs( - build_spec_groups("foo", %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.0 2.0.1]), - build_spec("foo", "0.2.0").first + build_candidates(%w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.0 2.0.1]), + Bundler::Resolver::Package.new("foo", [], build_spec_set("foo", "0.2.0"), ["bar"]) ) - expect(versions(res)).to eq %w[0.3.0 0.3.1 0.9.0 0.2.0] + expect(versions(res)).to match_array %w[0.3.0 0.3.1 0.9.0 0.2.0] end end context "sort specs (not strict) level patch" do it "when not unlocking, same order but make sure build_spec version is most preferred to stay put" do - keep_locked(:level => :patch) + with_options(:level => :patch) res = @gvp.sort_dep_specs( - build_spec_groups("foo", %w[1.5.4 1.6.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 2.0.0 2.0.1]), - build_spec("foo", "1.7.7").first + build_candidates(%w[1.5.4 1.6.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 2.0.0 2.0.1]), + Bundler::Resolver::Package.new("foo", [], build_spec_set("foo", "1.7.7"), ["bar"]) ) expect(versions(res)).to eq %w[1.5.4 1.6.5 1.7.6 2.0.0 2.0.1 1.8.0 1.8.1 1.7.8 1.7.9 1.7.7] end it "when unlocking favor next release, then current over minor increase" do - unlocking(:level => :patch) + with_options(:level => :patch) res = @gvp.sort_dep_specs( - build_spec_groups("foo", %w[1.7.7 1.7.8 1.7.9 1.8.0]), - build_spec("foo", "1.7.8").first + build_candidates(%w[1.7.7 1.7.8 1.7.9 1.8.0]), + Bundler::Resolver::Package.new("foo", [], build_spec_set("foo", "1.7.8"), []) ) expect(versions(res)).to eq %w[1.7.7 1.8.0 1.7.8 1.7.9] end it "when unlocking do proper integer comparison, not string" do - unlocking(:level => :patch) + with_options(:level => :patch) res = @gvp.sort_dep_specs( - build_spec_groups("foo", %w[1.7.7 1.7.8 1.7.9 1.7.15 1.8.0]), - build_spec("foo", "1.7.8").first + build_candidates(%w[1.7.7 1.7.8 1.7.9 1.7.15 1.8.0]), + Bundler::Resolver::Package.new("foo", [], build_spec_set("foo", "1.7.8"), []) ) expect(versions(res)).to eq %w[1.7.7 1.8.0 1.7.8 1.7.9 1.7.15] end it "leave current when unlocking but already at latest release" do - unlocking(:level => :patch) + with_options(:level => :patch) res = @gvp.sort_dep_specs( - build_spec_groups("foo", %w[1.7.9 1.8.0 2.0.0]), - build_spec("foo", "1.7.9").first + build_candidates(%w[1.7.9 1.8.0 2.0.0]), + Bundler::Resolver::Package.new("foo", [], build_spec_set("foo", "1.7.9"), []) ) expect(versions(res)).to eq %w[2.0.0 1.8.0 1.7.9] end @@ -130,10 +127,10 @@ RSpec.describe Bundler::GemVersionPromoter do context "sort specs (not strict) level minor" do it "when unlocking favor next release, then minor increase over current" do - unlocking(:level => :minor) + with_options(:level => :minor) res = @gvp.sort_dep_specs( - build_spec_groups("foo", %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.0 2.0.1]), - build_spec("foo", "0.2.0").first + build_candidates(%w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.0 2.0.1]), + Bundler::Resolver::Package.new("foo", [], build_spec_set("foo", "0.2.0"), []) ) expect(versions(res)).to eq %w[2.0.0 2.0.1 1.0.0 0.2.0 0.3.0 0.3.1 0.9.0] end diff --git a/spec/bundler/bundler/resolver/candidate_spec.rb b/spec/bundler/bundler/resolver/candidate_spec.rb new file mode 100644 index 0000000000..0840f77245 --- /dev/null +++ b/spec/bundler/bundler/resolver/candidate_spec.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +RSpec.describe Bundler::Resolver::Candidate do + it "compares fine" do + version1 = described_class.new("1.12.5", :specs => [Gem::Specification.new("foo", "1.12.5") {|s| s.platform = Gem::Platform::RUBY }]) + version2 = described_class.new("1.12.5") + + expect(version1 >= version2).to be true + end +end diff --git a/spec/bundler/bundler/version_ranges_spec.rb b/spec/bundler/bundler/version_ranges_spec.rb deleted file mode 100644 index bca044b0c0..0000000000 --- a/spec/bundler/bundler/version_ranges_spec.rb +++ /dev/null @@ -1,40 +0,0 @@ -# frozen_string_literal: true - -require "bundler/version_ranges" - -RSpec.describe Bundler::VersionRanges do - describe ".empty?" do - shared_examples_for "empty?" do |exp, *req| - it "returns #{exp} for #{req}" do - r = Gem::Requirement.new(*req) - ranges = described_class.for(r) - expect(described_class.empty?(*ranges)).to eq(exp), "expected `#{r}` #{exp ? "" : "not "}to be empty" - end - end - - include_examples "empty?", false - include_examples "empty?", false, "!= 1" - include_examples "empty?", false, "!= 1", "= 2" - include_examples "empty?", false, "!= 1", "> 1" - include_examples "empty?", false, "!= 1", ">= 1" - include_examples "empty?", false, "= 1", ">= 0.1", "<= 1.1" - include_examples "empty?", false, "= 1", ">= 1", "<= 1" - include_examples "empty?", false, "= 1", "~> 1" - include_examples "empty?", false, ">= 0.z", "= 0" - include_examples "empty?", false, ">= 0" - include_examples "empty?", false, ">= 1.0.0", "< 2.0.0" - include_examples "empty?", false, "~> 1" - include_examples "empty?", false, "~> 2.0", "~> 2.1" - include_examples "empty?", true, ">= 4.1.0", "< 5.0", "= 5.2.1" - include_examples "empty?", true, "< 5.0", "< 5.3", "< 6.0", "< 6", "= 5.2.0", "> 2", ">= 3.0", ">= 3.1", ">= 3.2", ">= 4.0.0", ">= 4.1.0", ">= 4.2.0", ">= 4.2", ">= 4" - include_examples "empty?", true, "!= 1", "< 2", "> 2" - include_examples "empty?", true, "!= 1", "<= 1", ">= 1" - include_examples "empty?", true, "< 2", "> 2" - include_examples "empty?", true, "< 2", "> 2", "= 2" - include_examples "empty?", true, "= 1", "!= 1" - include_examples "empty?", true, "= 1", "= 2" - include_examples "empty?", true, "= 1", "~> 2" - include_examples "empty?", true, ">= 0", "<= 0.a" - include_examples "empty?", true, "~> 2.0", "~> 3" - end -end diff --git a/spec/bundler/install/bundler_spec.rb b/spec/bundler/install/bundler_spec.rb index 963ce82db8..ae7c94c31f 100644 --- a/spec/bundler/install/bundler_spec.rb +++ b/spec/bundler/install/bundler_spec.rb @@ -37,12 +37,11 @@ RSpec.describe "bundle install" do G nice_error = <<-E.strip.gsub(/^ {8}/, "") - Bundler could not find compatible versions for gem "bundler": - In Gemfile: - bundler (= 0.9.1) + Could not find compatible versions - Current Bundler version: - bundler (#{Bundler::VERSION}) + Because the current Bundler version (#{Bundler::VERSION}) does not satisfy bundler = 0.9.1 + and Gemfile depends on bundler = 0.9.1, + version solving has failed. Your bundle requires a different version of Bundler than the one you're running. Install the necessary version with `gem install bundler:0.9.1` and rerun bundler using `bundle _0.9.1_ install` @@ -58,12 +57,14 @@ RSpec.describe "bundle install" do G nice_error = <<-E.strip.gsub(/^ {8}/, "") - Bundler could not find compatible versions for gem "bundler": - In Gemfile: - bundler (~> 0.8) + Could not find compatible versions - Current Bundler version: - bundler (#{Bundler::VERSION}) + Because rails >= 3.0 depends on bundler >= 0.9.0.pre + and the current Bundler version (#{Bundler::VERSION}) does not satisfy bundler >= 0.9.0.pre, < 1.A, + rails >= 3.0 requires bundler >= 1.A. + So, because Gemfile depends on rails = 3.0 + and Gemfile depends on bundler ~> 0.8, + version solving has failed. Your bundle requires a different version of Bundler than the one you're running. Install the necessary version with `gem install bundler:0.9.1` and rerun bundler using `bundle _0.9.1_ install` @@ -79,12 +80,11 @@ RSpec.describe "bundle install" do G nice_error = <<-E.strip.gsub(/^ {8}/, "") - Bundler could not find compatible versions for gem "bundler": - In Gemfile: - bundler (= 0.9.2) + Could not find compatible versions - Current Bundler version: - bundler (#{Bundler::VERSION}) + Because the current Bundler version (#{Bundler::VERSION}) does not satisfy bundler = 0.9.2 + and Gemfile depends on bundler = 0.9.2, + version solving has failed. Your bundle requires a different version of Bundler than the one you're running, and that version could not be found. E @@ -150,13 +150,14 @@ RSpec.describe "bundle install" do G nice_error = <<-E.strip.gsub(/^ {8}/, "") - Bundler could not find compatible versions for gem "activesupport": - In Gemfile: - activemerchant was resolved to 1.0, which depends on - activesupport (>= 2.0.0) - - rails_pinned_to_old_activesupport was resolved to 1.0, which depends on - activesupport (= 1.2.3) + Could not find compatible versions + + Because every version of rails_pinned_to_old_activesupport depends on activesupport = 1.2.3 + and every version of activemerchant depends on activesupport >= 2.0.0, + every version of rails_pinned_to_old_activesupport is incompatible with activemerchant >= 0. + So, because Gemfile depends on activemerchant >= 0 + and Gemfile depends on rails_pinned_to_old_activesupport >= 0, + version solving has failed. E expect(err).to include(nice_error) end @@ -177,12 +178,13 @@ RSpec.describe "bundle install" do G nice_error = <<-E.strip.gsub(/^ {8}/, "") - Bundler could not find compatible versions for gem "activesupport": - In Gemfile: - activesupport (= 2.3.5) + Could not find compatible versions - rails_pinned_to_old_activesupport was resolved to 1.0, which depends on - activesupport (= 1.2.3) + Because every version of rails_pinned_to_old_activesupport depends on activesupport = 1.2.3 + and Gemfile depends on rails_pinned_to_old_activesupport >= 0, + activesupport = 1.2.3 is required. + So, because Gemfile depends on activesupport = 2.3.5, + version solving has failed. E expect(err).to include(nice_error) end diff --git a/spec/bundler/install/gemfile/git_spec.rb b/spec/bundler/install/gemfile/git_spec.rb index fb99c99b2d..636a3daaad 100644 --- a/spec/bundler/install/gemfile/git_spec.rb +++ b/spec/bundler/install/gemfile/git_spec.rb @@ -881,7 +881,7 @@ RSpec.describe "bundle install with git sources" do gem "has_submodule" end G - expect(err).to match(/could not find gem 'submodule/i) + expect(err).to match(%r{submodule >= 0 could not be found in rubygems repository #{file_uri_for(gem_repo1)}/ or installed locally}) expect(the_bundle).not_to include_gems "has_submodule 1.0" end diff --git a/spec/bundler/install/gemfile/sources_spec.rb b/spec/bundler/install/gemfile/sources_spec.rb index d2733993bb..174bac511e 100644 --- a/spec/bundler/install/gemfile/sources_spec.rb +++ b/spec/bundler/install/gemfile/sources_spec.rb @@ -371,7 +371,15 @@ RSpec.describe "bundle install with gems on multiple sources" do it "fails" do bundle :install, :artifice => "compact_index", :raise_on_error => false - expect(err).to include("Could not find gem 'missing', which is required by gem 'depends_on_missing', in any of the sources.") + expect(err).to end_with <<~E.strip + Could not find compatible versions + + Because every version of depends_on_missing depends on missing >= 0 + and missing >= 0 could not be found in any of the sources, + every version of depends_on_missing is forbidden. + So, because Gemfile depends on depends_on_missing >= 0, + version solving has failed. + E end end @@ -425,9 +433,15 @@ RSpec.describe "bundle install with gems on multiple sources" do it "does not find the dependency" do bundle :install, :artifice => "compact_index", :raise_on_error => false - expect(err).to include( - "Could not find gem 'rack', which is required by gem 'depends_on_rack', in rubygems repository https://gem.repo2/ or installed locally." - ) + expect(err).to end_with <<~E.strip + Could not find compatible versions + + Because every version of depends_on_rack depends on rack >= 0 + and rack >= 0 could not be found in rubygems repository https://gem.repo2/ or installed locally, + every version of depends_on_rack is forbidden. + So, because Gemfile depends on depends_on_rack >= 0, + version solving has failed. + E end end diff --git a/spec/bundler/install/gemfile/specific_platform_spec.rb b/spec/bundler/install/gemfile/specific_platform_spec.rb index 98efec396c..1f615ec8a5 100644 --- a/spec/bundler/install/gemfile/specific_platform_spec.rb +++ b/spec/bundler/install/gemfile/specific_platform_spec.rb @@ -370,6 +370,16 @@ RSpec.describe "bundle install with specific platforms" do * sorbet-static-0.5.6433-x86_64-linux ERROR + error_message = <<~ERROR.strip + Could not find compatible versions + + Because every version of sorbet depends on sorbet-static = 0.5.6433 + and sorbet-static = 0.5.6433 could not be found in rubygems repository #{file_uri_for(gem_repo4)}/ or installed locally, + every version of sorbet is forbidden. + So, because Gemfile depends on sorbet = 0.5.6433, + version solving has failed. + ERROR + simulate_platform "arm64-darwin-21" do bundle "lock", :raise_on_error => false end diff --git a/spec/bundler/install/gems/flex_spec.rb b/spec/bundler/install/gems/flex_spec.rb index ed30d2cc35..4bbb2ea038 100644 --- a/spec/bundler/install/gems/flex_spec.rb +++ b/spec/bundler/install/gems/flex_spec.rb @@ -194,11 +194,13 @@ RSpec.describe "bundle flex_install" do bundle "config set force_ruby_platform true" nice_error = <<-E.strip.gsub(/^ {8}/, "") - Could not find gem 'rack (= 1.2)', which is required by gem 'rack-obama (= 2.0)', in rubygems repository #{file_uri_for(gem_repo2)}/ or installed locally. + Could not find compatible versions - The source contains the following gems matching 'rack': - * rack-0.9.1 - * rack-1.0.0 + Because rack-obama >= 2.0 depends on rack = 1.2 + and rack = 1.2 could not be found in rubygems repository #{file_uri_for(gem_repo2)}/ or installed locally, + rack-obama >= 2.0 is forbidden. + So, because Gemfile depends on rack-obama = 2.0, + version solving has failed. E bundle :install, :retry => 0, :raise_on_error => false diff --git a/spec/bundler/install/gems/resolving_spec.rb b/spec/bundler/install/gems/resolving_spec.rb index 7a5307720f..3977122568 100644 --- a/spec/bundler/install/gems/resolving_spec.rb +++ b/spec/bundler/install/gems/resolving_spec.rb @@ -159,7 +159,7 @@ RSpec.describe "bundle install with install-time dependencies" do bundle :install, :env => { "BUNDLER_DEBUG_RESOLVER" => "1", "DEBUG" => "1" } - expect(out).to include("BUNDLER: Starting resolution") + expect(out).to include("Resolving dependencies...") end end @@ -173,7 +173,7 @@ RSpec.describe "bundle install with install-time dependencies" do bundle :install, :env => { "DEBUG_RESOLVER" => "1", "DEBUG" => "1" } - expect(out).to include("BUNDLER: Starting resolution") + expect(out).to include("Resolving dependencies...") end end @@ -187,12 +187,10 @@ RSpec.describe "bundle install with install-time dependencies" do bundle :install, :env => { "DEBUG_RESOLVER_TREE" => "1", "DEBUG" => "1" } - activated_groups = "net_b (1.0) (ruby)" - expect(out).to include(" net_b"). - and include("BUNDLER: Starting resolution"). - and include("BUNDLER: Finished resolution"). - and include("Attempting to activate [#{activated_groups}]") + and include("Resolving dependencies..."). + and include("Solution found after 1 attempts:"). + and include("selecting net_b 1.0") end end end @@ -379,12 +377,12 @@ RSpec.describe "bundle install with install-time dependencies" do it "gives a meaningful error on ruby version mismatches between dependencies" do build_repo4 do build_gem "requires-old-ruby" do |s| - s.required_ruby_version = "< #{RUBY_VERSION}" + s.required_ruby_version = "< #{Gem.ruby_version}" end end build_lib("foo", :path => bundled_app) do |s| - s.required_ruby_version = ">= #{RUBY_VERSION}" + s.required_ruby_version = ">= #{Gem.ruby_version}" s.add_dependency "requires-old-ruby" end @@ -394,7 +392,16 @@ RSpec.describe "bundle install with install-time dependencies" do gemspec G - expect(err).to include("Bundler found conflicting requirements for the Ruby\0 version:") + expect(err).to end_with <<~E.strip + Could not find compatible versions + + Because every version of foo depends on requires-old-ruby >= 0 + and every version of requires-old-ruby depends on Ruby < #{Gem.ruby_version}, + every version of foo requires Ruby < #{Gem.ruby_version}. + So, because Gemfile depends on foo >= 0 + and current Ruby version is = #{Gem.ruby_version}, + version solving has failed. + E end it "installs the older version under rate limiting conditions" do @@ -464,14 +471,13 @@ RSpec.describe "bundle install with install-time dependencies" do expect(out).to_not include("Gem::InstallError: require_ruby requires Ruby version > 9000") nice_error = strip_whitespace(<<-E).strip - Bundler found conflicting requirements for the Ruby\0 version: - In Gemfile: - require_ruby was resolved to 1.0, which depends on - Ruby\0 (> 9000) - - Current Ruby\0 version: - Ruby\0 (#{error_message_requirement}) + Could not find compatible versions + Because every version of require_ruby depends on Ruby > 9000 + and Gemfile depends on require_ruby >= 0, + Ruby > 9000 is required. + So, because current Ruby version is #{error_message_requirement}, + version solving has failed. E expect(err).to end_with(nice_error) end @@ -487,14 +493,13 @@ RSpec.describe "bundle install with install-time dependencies" do expect(out).to_not include("Gem::InstallError: require_ruby requires Ruby version > 9000") nice_error = strip_whitespace(<<-E).strip - Bundler found conflicting requirements for the Ruby\0 version: - In Gemfile: - require_ruby was resolved to 1.0, which depends on - Ruby\0 (> 9000) - - Current Ruby\0 version: - Ruby\0 (#{error_message_requirement}) + Could not find compatible versions + Because every version of require_ruby depends on Ruby > 9000 + and Gemfile depends on require_ruby >= 0, + Ruby > 9000 is required. + So, because current Ruby version is #{error_message_requirement}, + version solving has failed. E expect(err).to end_with(nice_error) end @@ -532,14 +537,11 @@ RSpec.describe "bundle install with install-time dependencies" do expect(err).to_not include("Gem::InstallError: require_rubygems requires RubyGems version > 9000") nice_error = strip_whitespace(<<-E).strip - Bundler found conflicting requirements for the RubyGems\0 version: - In Gemfile: - require_rubygems was resolved to 1.0, which depends on - RubyGems\0 (> 9000) - - Current RubyGems\0 version: - RubyGems\0 (= #{Gem::VERSION}) - + Because every version of require_rubygems depends on RubyGems > 9000 + and Gemfile depends on require_rubygems >= 0, + RubyGems > 9000 is required. + So, because current RubyGems version is = #{Gem::VERSION}, + version solving has failed. E expect(err).to end_with(nice_error) end diff --git a/spec/bundler/realworld/edgecases_spec.rb b/spec/bundler/realworld/edgecases_spec.rb index a98859c2d9..e1bb92d36e 100644 --- a/spec/bundler/realworld/edgecases_spec.rb +++ b/spec/bundler/realworld/edgecases_spec.rb @@ -11,7 +11,8 @@ RSpec.describe "real world edgecases", :realworld => true do source = Bundler::Source::Rubygems::Remote.new(Bundler::URI("https://rubygems.org")) fetcher = Bundler::Fetcher.new(source) index = fetcher.specs([#{name.dump}], nil) - index.search(Gem::Dependency.new(#{name.dump}, #{requirement.dump})).last + requirement = Gem::Requirement.create(#{requirement.dump}) + index.search(#{name.dump}).select {|spec| requirement.satisfied_by?(spec.version) }.last end if rubygem.nil? raise "Could not find #{name} (#{requirement}) on rubygems.org!\n" \ diff --git a/spec/bundler/resolver/basic_spec.rb b/spec/bundler/resolver/basic_spec.rb index b583fb8715..41c6d9972c 100644 --- a/spec/bundler/resolver/basic_spec.rb +++ b/spec/bundler/resolver/basic_spec.rb @@ -104,7 +104,7 @@ RSpec.describe "Resolving" do dep "chef_app_error" expect do resolve - end.to raise_error(Bundler::VersionConflict) + end.to raise_error(Bundler::SolveFailure) end it "raises an exception with the minimal set of conflicting dependencies" do @@ -118,14 +118,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 @@ -134,7 +135,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 diff --git a/spec/bundler/resolver/platform_spec.rb b/spec/bundler/resolver/platform_spec.rb index 418293365c..2d143fd84a 100644 --- a/spec/bundler/resolver/platform_spec.rb +++ b/spec/bundler/resolver/platform_spec.rb @@ -210,39 +210,6 @@ RSpec.describe "Resolving platform craziness" do should_resolve_as %w[foo-1.1.0] end - it "doesn't include gems not needed for none of the platforms" 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" - end - - dep "empyrean", "0.1.0" - dep "pry" - - platforms "ruby", "java" - - should_resolve_as %w[coderay-1.1.2 empyrean-0.1.0 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" do @index = build_index do gem "empyrean", "0.1.0" diff --git a/spec/bundler/runtime/inline_spec.rb b/spec/bundler/runtime/inline_spec.rb index d53e8663a6..fd1dd6dc26 100644 --- a/spec/bundler/runtime/inline_spec.rb +++ b/spec/bundler/runtime/inline_spec.rb @@ -96,12 +96,14 @@ RSpec.describe "bundler/inline#gemfile" do it "lets me use my own ui object" do script <<-RUBY, :artifice => "endpoint" require '#{entrypoint}' - class MyBundlerUI < Bundler::UI::Silent + class MyBundlerUI < Bundler::UI::Shell def confirm(msg, newline = nil) puts "CONFIRMED!" end end - gemfile(true, :ui => MyBundlerUI.new) do + my_ui = MyBundlerUI.new + my_ui.level = "confirm" + gemfile(true, :ui => my_ui) do source "https://notaserver.com" gem "activesupport", :require => true end diff --git a/spec/bundler/support/indexes.rb b/spec/bundler/support/indexes.rb index e20059429c..744dd6e233 100644 --- a/spec/bundler/support/indexes.rb +++ b/spec/bundler/support/indexes.rb @@ -18,15 +18,22 @@ module Spec @platforms ||= ["ruby"] default_source = instance_double("Bundler::Source::Rubygems", :specs => @index, :to_s => "locally install gems") source_requirements = { :default => default_source } - @deps.each do |d| - source_requirements[d.name] = d.source = default_source - end args[0] ||= Bundler::SpecSet.new([]) # base args[0].each {|ls| ls.source = default_source } args[1] ||= Bundler::GemVersionPromoter.new # gem_version_promoter args[2] ||= [] # additional_base_requirements - args[3] ||= @platforms # platforms - Bundler::Resolver.new(source_requirements, *args).start(@deps) + originally_locked = args[3] || Bundler::SpecSet.new([]) + unlock = args[4] || [] + packages = Hash.new do |h, k| + h[k] = Bundler::Resolver::Package.new(k, @platforms, originally_locked, unlock) + end + @deps.each do |d| + name = d.name + platforms = d.gem_platforms(@platforms) + source_requirements[name] = d.source = default_source + packages[name] = Bundler::Resolver::Package.new(name, platforms, originally_locked, unlock, :dependency => d) + end + Bundler::Resolver.new(source_requirements, *args[0..2]).start(@deps, packages) end def should_not_resolve @@ -47,13 +54,6 @@ module Spec end end - def should_conflict_on(names) - got = resolve - raise "The resolve succeeded with: #{got.map(&:full_name).sort.inspect}" - rescue Bundler::VersionConflict => e - expect(Array(names).sort).to eq(e.conflicts.sort) - end - def gem(*args, &blk) build_spec(*args, &blk).first end @@ -67,12 +67,11 @@ module Spec def should_conservative_resolve_and_include(opts, unlock, specs) # empty unlock means unlock all opts = Array(opts) - search = Bundler::GemVersionPromoter.new(@locked, unlock).tap do |s| + search = Bundler::GemVersionPromoter.new.tap do |s| s.level = opts.first s.strict = opts.include?(:strict) - s.prerelease_specified = Hash[@deps.map {|d| [d.name, d.requirement.prerelease?] }] end - should_resolve_and_include specs, [@base, search] + should_resolve_and_include specs, [@base, search, [], @locked, unlock] end def an_awesome_index |