diff options
Diffstat (limited to 'spec')
29 files changed, 895 insertions, 637 deletions
diff --git a/spec/bundler/bundler/definition_spec.rb b/spec/bundler/bundler/definition_spec.rb index 5f8b88a101..78c7dc79b9 100644 --- a/spec/bundler/bundler/definition_spec.rb +++ b/spec/bundler/bundler/definition_spec.rb @@ -268,7 +268,7 @@ RSpec.describe Bundler::Definition do bundled_app_lock, updated_deps_in_gemfile, source_list, - :gems => ["shared_owner_a"], :lock_shared_dependencies => true + :gems => ["shared_owner_a"], :conservative => true ) locked = definition.send(:converge_locked_specs).map(&:name) expect(locked).to eq %w[isolated_dep isolated_owner shared_dep shared_owner_b] @@ -278,33 +278,6 @@ RSpec.describe Bundler::Definition do end end - describe "find_resolved_spec" do - it "with no platform set in SpecSet" do - ss = Bundler::SpecSet.new([build_stub_spec("a", "1.0"), build_stub_spec("b", "1.0")]) - dfn = Bundler::Definition.new(nil, [], mock_source_list, true) - dfn.instance_variable_set("@specs", ss) - found = dfn.find_resolved_spec(build_spec("a", "0.9", "ruby").first) - expect(found.name).to eq "a" - expect(found.version.to_s).to eq "1.0" - end - end - - describe "find_indexed_specs" do - it "with no platform set in indexed specs" do - index = Bundler::Index.new - %w[1.0.0 1.0.1 1.1.0].each {|v| index << build_stub_spec("foo", v) } - - dfn = Bundler::Definition.new(nil, [], mock_source_list, true) - dfn.instance_variable_set("@index", index) - found = dfn.find_indexed_specs(build_spec("foo", "0.9", "ruby").first) - expect(found.length).to eq 3 - end - end - - def build_stub_spec(name, version) - Bundler::StubSpecification.new(name, version, nil, nil) - end - def mock_source_list Class.new do def all_sources diff --git a/spec/bundler/bundler/fetcher/downloader_spec.rb b/spec/bundler/bundler/fetcher/downloader_spec.rb index 667f484349..4d3dff3a89 100644 --- a/spec/bundler/bundler/fetcher/downloader_spec.rb +++ b/spec/bundler/bundler/fetcher/downloader_spec.rb @@ -231,16 +231,7 @@ RSpec.describe Bundler::Fetcher::Downloader do end end - context "when error message is about getaddrinfo issues" do - let(:message) { "getaddrinfo: nodename nor servname provided for http://www.uri-to-fetch.com" } - - it "should raise a Bundler::Fetcher::NetworkDownError" do - expect { subject.request(uri, options) }.to raise_error(Bundler::Fetcher::NetworkDownError, - /Could not reach host www.uri-to-fetch.com/) - end - end - - context "when error message is about neither host down or getaddrinfo" do + context "when error message is not about host down" do let(:message) { "other error about network" } it "should raise a Bundler::HTTPError" do diff --git a/spec/bundler/bundler/fetcher/index_spec.rb b/spec/bundler/bundler/fetcher/index_spec.rb index b8ce46321e..f0db07583c 100644 --- a/spec/bundler/bundler/fetcher/index_spec.rb +++ b/spec/bundler/bundler/fetcher/index_spec.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "rubygems/remote_fetcher" + RSpec.describe Bundler::Fetcher::Index do let(:downloader) { nil } let(:remote) { nil } diff --git a/spec/bundler/bundler/settings_spec.rb b/spec/bundler/bundler/settings_spec.rb index 116a038445..0f1a9c2a6f 100644 --- a/spec/bundler/bundler/settings_spec.rb +++ b/spec/bundler/bundler/settings_spec.rb @@ -312,16 +312,26 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow describe "BUNDLE_ keys format" do let(:settings) { described_class.new(bundled_app(".bundle")) } - it "converts older keys without double dashes" do + it "converts older keys without double underscore" do config("BUNDLE_MY__PERSONAL.RACK" => "~/Work/git/rack") expect(settings["my.personal.rack"]).to eq("~/Work/git/rack") end - it "converts older keys without trailing slashes and double dashes" do + it "converts older keys without trailing slashes and double underscore" do config("BUNDLE_MIRROR__HTTPS://RUBYGEMS.ORG" => "http://rubygems-mirror.org") expect(settings["mirror.https://rubygems.org/"]).to eq("http://rubygems-mirror.org") end + it "converts older keys with dashes" do + config("BUNDLE_MY-PERSONAL-SERVER__ORG" => "my-personal-server.org") + expect(Bundler.ui).to receive(:warn).with( + "Your #{bundled_app(".bundle/config")} config includes `BUNDLE_MY-PERSONAL-SERVER__ORG`, which contains the dash character (`-`).\n" \ + "This is deprecated, because configuration through `ENV` should be possible, but `ENV` keys cannot include dashes.\n" \ + "Please edit #{bundled_app(".bundle/config")} and replace any dashes in configuration keys with a triple underscore (`___`)." + ) + expect(settings["my-personal-server.org"]).to eq("my-personal-server.org") + end + it "reads newer keys format properly" do config("BUNDLE_MIRROR__HTTPS://RUBYGEMS__ORG/" => "http://rubygems-mirror.org") expect(settings["mirror.https://rubygems.org/"]).to eq("http://rubygems-mirror.org") diff --git a/spec/bundler/commands/cache_spec.rb b/spec/bundler/commands/cache_spec.rb index df027a497a..4f9c1c26c4 100644 --- a/spec/bundler/commands/cache_spec.rb +++ b/spec/bundler/commands/cache_spec.rb @@ -298,6 +298,30 @@ RSpec.describe "bundle cache" do expect(out).to include("frozen").or include("deployment") end end + + context "with gems with extensions" do + before do + build_repo2 do + build_gem "racc", "2.0" do |s| + s.add_dependency "rake" + s.extensions << "Rakefile" + s.write "Rakefile", "task(:default) { puts 'INSTALLING rack' }" + end + end + + gemfile <<~G + source "#{file_uri_for(gem_repo2)}" + + gem "racc" + G + end + + it "installs them properly from cache to a different path" do + bundle "cache" + bundle "config set --local path vendor/bundle" + bundle "install --local" + end + end end RSpec.describe "bundle install with gem sources" do @@ -317,7 +341,7 @@ RSpec.describe "bundle install with gem sources" do expect(the_bundle).to include_gems "rack 1.0.0" end - it "does not hit the remote at all" do + it "does not hit the remote at all in frozen mode" do build_repo2 install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" @@ -334,6 +358,24 @@ RSpec.describe "bundle install with gem sources" do expect(the_bundle).to include_gems "rack 1.0.0" end + it "does not hit the remote at all when cache_all_platforms configured" do + build_repo2 + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "rack" + G + + bundle :cache + simulate_new_machine + FileUtils.rm_rf gem_repo2 + + bundle "config set --local cache_all_platforms true" + bundle "config set --local path vendor/bundle" + bundle "install --local" + expect(out).not_to include("Fetching gem metadata") + expect(the_bundle).to include_gems "rack 1.0.0" + end + it "does not reinstall already-installed gems" do install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" diff --git a/spec/bundler/commands/check_spec.rb b/spec/bundler/commands/check_spec.rb index 2fb03186be..2860c82a12 100644 --- a/spec/bundler/commands/check_spec.rb +++ b/spec/bundler/commands/check_spec.rb @@ -288,6 +288,66 @@ RSpec.describe "bundle check" do end end + describe "when using only scoped rubygems sources" do + before do + gemfile <<~G + source "#{file_uri_for(gem_repo1)}" do + gem "rack" + end + G + end + + it "returns success when the Gemfile is satisfied" do + system_gems "rack-1.0.0", :path => default_bundle_path + bundle :check + expect(out).to include("The Gemfile's dependencies are satisfied") + end + end + + describe "when using only scoped rubygems sources with indirect dependencies" do + before do + build_repo4 do + build_gem "depends_on_rack" do |s| + s.add_dependency "rack" + end + + build_gem "rack" + end + + gemfile <<~G + source "#{file_uri_for(gem_repo4)}" do + gem "depends_on_rack" + end + G + end + + it "returns success when the Gemfile is satisfied and generates a correct lockfile" do + system_gems "depends_on_rack-1.0", "rack-1.0", :gem_repo => gem_repo4, :path => default_bundle_path + bundle :check + expect(out).to include("The Gemfile's dependencies are satisfied") + expect(lockfile).to eq <<~L + GEM + specs: + + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + depends_on_rack (1.0) + rack + rack (1.0) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + depends_on_rack! + + BUNDLED WITH + #{Bundler::VERSION} + L + end + end + describe "BUNDLED WITH" do def lock_with(bundler_version = nil) lock = <<-L diff --git a/spec/bundler/commands/lock_spec.rb b/spec/bundler/commands/lock_spec.rb index 264af30f6c..21eb6e5456 100644 --- a/spec/bundler/commands/lock_spec.rb +++ b/spec/bundler/commands/lock_spec.rb @@ -533,7 +533,7 @@ RSpec.describe "bundle lock" do #{Bundler::VERSION} L - bundle "lock --add-platform x86_64-linux", :artifice => :compact_index, :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s } + bundle "lock --add-platform x86_64-linux", :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s } end context "when an update is available" do diff --git a/spec/bundler/commands/outdated_spec.rb b/spec/bundler/commands/outdated_spec.rb index b0f0448655..731d67af1b 100644 --- a/spec/bundler/commands/outdated_spec.rb +++ b/spec/bundler/commands/outdated_spec.rb @@ -205,8 +205,8 @@ RSpec.describe "bundle outdated" do end it "works" do - bundle :install, :artifice => :compact_index - bundle :outdated, :artifice => :compact_index, :raise_on_error => false + bundle :install, :artifice => "compact_index" + bundle :outdated, :artifice => "compact_index", :raise_on_error => false expected_output = <<~TABLE Gem Current Latest Requested Groups @@ -1292,4 +1292,53 @@ RSpec.describe "bundle outdated" do expect(out).to end_with(expected_output) end end + + context "when a gem is no longer a dependency after a full update" do + before do + build_repo4 do + build_gem "mini_portile2", "2.5.2" do |s| + s.add_dependency "net-ftp", "~> 0.1" + end + + build_gem "mini_portile2", "2.5.3" + + build_gem "net-ftp", "0.1.2" + end + + gemfile <<~G + source "#{file_uri_for(gem_repo4)}" + + gem "mini_portile2" + G + + lockfile <<~L + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + mini_portile2 (2.5.2) + net-ftp (~> 0.1) + net-ftp (0.1.2) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + mini_portile2 + + BUNDLED WITH + #{Bundler::VERSION} + L + end + + it "works" do + bundle "outdated", :raise_on_error => false + + expected_output = <<~TABLE.strip + Gem Current Latest Requested Groups + mini_portile2 2.5.2 2.5.3 >= 0 default + TABLE + + expect(out).to end_with(expected_output) + end + end end diff --git a/spec/bundler/commands/update_spec.rb b/spec/bundler/commands/update_spec.rb index 51a0b925a3..86314952ad 100644 --- a/spec/bundler/commands/update_spec.rb +++ b/spec/bundler/commands/update_spec.rb @@ -411,7 +411,7 @@ RSpec.describe "bundle update" do build_repo2 end - it "should not update gems not included in the source that happen to have the same name", :bundler => "< 3" do + it "should not update gems not included in the source that happen to have the same name" do install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" gem "activesupport" @@ -419,10 +419,10 @@ RSpec.describe "bundle update" do update_repo2 { build_gem "activesupport", "3.0" } bundle "update --source activesupport" - expect(the_bundle).to include_gem "activesupport 3.0" + expect(the_bundle).not_to include_gem "activesupport 3.0" end - it "should not update gems not included in the source that happen to have the same name", :bundler => "3" do + it "should not update gems not included in the source that happen to have the same name" do install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" gem "activesupport" @@ -430,22 +430,7 @@ RSpec.describe "bundle update" do update_repo2 { build_gem "activesupport", "3.0" } bundle "update --source activesupport" - expect(the_bundle).not_to include_gem "activesupport 3.0" - end - - context "with unlock_source_unlocks_spec set to false" do - before { bundle "config set unlock_source_unlocks_spec false" } - - it "should not update gems not included in the source that happen to have the same name" do - install_gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - gem "activesupport" - G - update_repo2 { build_gem "activesupport", "3.0" } - - bundle "update --source activesupport" - expect(the_bundle).not_to include_gems "activesupport 3.0" - end + expect(the_bundle).not_to include_gems "activesupport 3.0" end end @@ -465,20 +450,7 @@ RSpec.describe "bundle update" do G end - it "should not update the child dependencies of a gem that has the same name as the source", :bundler => "< 3" do - update_repo2 do - build_gem "fred", "2.0" - build_gem "harry", "2.0" do |s| - s.add_dependency "fred" - end - end - - bundle "update --source harry" - expect(the_bundle).to include_gems "harry 2.0" - expect(the_bundle).to include_gems "fred 1.0" - end - - it "should not update the child dependencies of a gem that has the same name as the source", :bundler => "3" do + it "should not update the child dependencies of a gem that has the same name as the source" do update_repo2 do build_gem "fred", "2.0" build_gem "harry", "2.0" do |s| @@ -510,21 +482,7 @@ RSpec.describe "bundle update" do G end - it "should not update the child dependencies of a gem that has the same name as the source", :bundler => "< 3" do - update_repo2 do - build_gem "george", "2.0" - build_gem "harry", "2.0" do |s| - s.add_dependency "george" - end - end - - bundle "update --source harry" - expect(the_bundle).to include_gems "harry 2.0" - expect(the_bundle).to include_gems "fred 1.0" - expect(the_bundle).to include_gems "george 1.0" - end - - it "should not update the child dependencies of a gem that has the same name as the source", :bundler => "3" do + it "should not update the child dependencies of a gem that has the same name as the source" do update_repo2 do build_gem "george", "2.0" build_gem "harry", "2.0" do |s| @@ -649,8 +607,8 @@ RSpec.describe "bundle update" do end it "works" do - bundle :install, :artifice => :compact_index - bundle "update oj", :artifice => :compact_index + bundle :install, :artifice => "compact_index" + bundle "update oj", :artifice => "compact_index" expect(out).to include("Bundle updated!") expect(the_bundle).to include_gems "oj 3.11.5" @@ -1106,9 +1064,9 @@ RSpec.describe "bundle update conservative" do gem 'shared_owner_b' G - lockfile <<-L + lockfile <<~L GEM - remote: #{file_uri_for(gem_repo4)} + remote: #{file_uri_for(gem_repo4)}/ specs: isolated_dep (2.0.1) isolated_owner (1.0.1) @@ -1120,12 +1078,12 @@ RSpec.describe "bundle update conservative" do shared_dep (~> 5.0) PLATFORMS - ruby + #{specific_local_platform} DEPENDENCIES + isolated_owner shared_owner_a shared_owner_b - isolated_owner BUNDLED WITH #{Bundler::VERSION} @@ -1147,7 +1105,42 @@ RSpec.describe "bundle update conservative" do it "should not eagerly unlock with --conservative" do bundle "update --conservative shared_owner_a isolated_owner" - expect(the_bundle).to include_gems "isolated_owner 1.0.2", "isolated_dep 2.0.2", "shared_dep 5.0.1", "shared_owner_a 3.0.2", "shared_owner_b 4.0.1" + expect(the_bundle).to include_gems "isolated_owner 1.0.2", "isolated_dep 2.0.1", "shared_dep 5.0.1", "shared_owner_a 3.0.2", "shared_owner_b 4.0.1" + end + + it "should only update direct dependencies when fully updating with --conservative" do + bundle "update --conservative" + + expect(the_bundle).to include_gems "isolated_owner 1.0.2", "isolated_dep 2.0.1", "shared_dep 5.0.1", "shared_owner_a 3.0.2", "shared_owner_b 4.0.2" + end + + it "should only change direct dependencies when updating the lockfile with --conservative" do + bundle "lock --update --conservative" + + expect(lockfile).to eq <<~L + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + isolated_dep (2.0.1) + isolated_owner (1.0.2) + isolated_dep (~> 2.0) + shared_dep (5.0.1) + shared_owner_a (3.0.2) + shared_dep (~> 5.0) + shared_owner_b (4.0.2) + shared_dep (~> 5.0) + + PLATFORMS + #{specific_local_platform} + + DEPENDENCIES + isolated_owner + shared_owner_a + shared_owner_b + + BUNDLED WITH + #{Bundler::VERSION} + L end it "should match bundle install conservative update behavior when not eagerly unlocking" do diff --git a/spec/bundler/install/gemfile/groups_spec.rb b/spec/bundler/install/gemfile/groups_spec.rb index f53315e766..c92b5dcc57 100644 --- a/spec/bundler/install/gemfile/groups_spec.rb +++ b/spec/bundler/install/gemfile/groups_spec.rb @@ -358,7 +358,7 @@ RSpec.describe "bundle install with groups" do G ruby <<-R - require "#{lib_dir}/bundler" + require "#{entrypoint}" Bundler.setup :default Bundler.require :default puts RACK diff --git a/spec/bundler/install/gemfile/sources_spec.rb b/spec/bundler/install/gemfile/sources_spec.rb index 4f931a493b..16c5b232da 100644 --- a/spec/bundler/install/gemfile/sources_spec.rb +++ b/spec/bundler/install/gemfile/sources_spec.rb @@ -20,23 +20,23 @@ RSpec.describe "bundle install with gems on multiple sources" do before do gemfile <<-G - source "#{file_uri_for(gem_repo3)}" - source "#{file_uri_for(gem_repo1)}" + source "https://gem.repo3" + source "https://gem.repo1" gem "rack-obama" gem "rack" G end it "warns about ambiguous gems, but installs anyway, prioritizing sources last to first", :bundler => "< 3" do - bundle :install + bundle :install, :artifice => "compact_index" expect(err).to include("Warning: the gem 'rack' was found in multiple sources.") - expect(err).to include("Installed from: #{file_uri_for(gem_repo1)}") + expect(err).to include("Installed from: https://gem.repo1") expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0", :source => "remote1") end it "fails", :bundler => "3" do - bundle :instal, :raise_on_error => false + bundle :instal, :artifice => "compact_index", :raise_on_error => false expect(err).to include("Each source after the first must include a block") expect(exitstatus).to eq(4) end @@ -47,22 +47,22 @@ RSpec.describe "bundle install with gems on multiple sources" do before do gemfile <<-G - source "#{file_uri_for(gem_repo3)}" - source "#{file_uri_for(gem_repo1)}" + source "https://gem.repo3" + source "https://gem.repo1" gem "rack-obama" gem "rack", "1.0.0" # force it to install the working version in repo1 G end it "warns about ambiguous gems, but installs anyway", :bundler => "< 3" do - bundle :install + bundle :install, :artifice => "compact_index" expect(err).to include("Warning: the gem 'rack' was found in multiple sources.") - expect(err).to include("Installed from: #{file_uri_for(gem_repo1)}") + expect(err).to include("Installed from: https://gem.repo1") expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0", :source => "remote1") end it "fails", :bundler => "3" do - bundle :install, :raise_on_error => false + bundle :install, :artifice => "compact_index", :raise_on_error => false expect(err).to include("Each source after the first must include a block") expect(exitstatus).to eq(4) end @@ -85,8 +85,8 @@ RSpec.describe "bundle install with gems on multiple sources" do end gemfile <<-G - source "#{file_uri_for(gem_repo3)}" - source "#{file_uri_for(gem_repo1)}" do + source "https://gem.repo3" + source "https://gem.repo1" do gem "thin" # comes first to test name sorting gem "rack" end @@ -95,20 +95,20 @@ RSpec.describe "bundle install with gems on multiple sources" do end it "installs the gems without any warning" do - bundle :install + bundle :install, :artifice => "compact_index" expect(err).not_to include("Warning") expect(the_bundle).to include_gems("rack-obama 1.0.0") expect(the_bundle).to include_gems("rack 1.0.0", :source => "remote1") end it "can cache and deploy" do - bundle :cache + bundle :cache, :artifice => "compact_index" expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist expect(bundled_app("vendor/cache/rack-obama-1.0.gem")).to exist bundle "config set --local deployment true" - bundle :install + bundle :install, :artifice => "compact_index" expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0") end @@ -128,10 +128,10 @@ RSpec.describe "bundle install with gems on multiple sources" do end end - install_gemfile <<-G - source "#{file_uri_for(gem_repo3)}" + install_gemfile <<-G, :artifice => "compact_index" + source "https://gem.repo3" gem "rack-obama" # should come from repo3! - gem "rack", :source => "#{file_uri_for(gem_repo1)}" + gem "rack", :source => "https://gem.repo1" G end @@ -155,8 +155,8 @@ RSpec.describe "bundle install with gems on multiple sources" do end gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - source "#{file_uri_for(gem_repo3)}" do + source "https://gem.repo2" + source "https://gem.repo3" do gem "depends_on_rack" end G @@ -168,7 +168,7 @@ RSpec.describe "bundle install with gems on multiple sources" do end it "installs from the same source without any warning" do - bundle :install + bundle :install, :artifice => "compact_index" expect(err).not_to include("Warning") expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3") end @@ -185,7 +185,7 @@ RSpec.describe "bundle install with gems on multiple sources" do end it "installs from the same source without any warning" do - bundle :install + bundle :install, :artifice => "compact_index" expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3") @@ -193,7 +193,7 @@ RSpec.describe "bundle install with gems on multiple sources" do # In https://github.com/bundler/bundler/issues/3585 this failed # when there is already a lock file, and the gems are missing, so try again system_gems [] - bundle :install + bundle :install, :artifice => "compact_index" expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3") @@ -218,9 +218,9 @@ RSpec.describe "bundle install with gems on multiple sources" do context "and not in any other sources" do before do - install_gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - source "#{file_uri_for(gem_repo3)}" do + install_gemfile <<-G, :artifice => "compact_index" + source "https://gem.repo2" + source "https://gem.repo3" do gem "depends_on_rack" end G @@ -235,23 +235,49 @@ RSpec.describe "bundle install with gems on multiple sources" do context "and in yet another source" do before do gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - source "#{file_uri_for(gem_repo2)}" - source "#{file_uri_for(gem_repo3)}" do + source "https://gem.repo1" + source "https://gem.repo2" + source "https://gem.repo3" do gem "depends_on_rack" end G end it "installs from the other source and warns about ambiguous gems", :bundler => "< 3" do - bundle :install + bundle :install, :artifice => "compact_index" expect(err).to include("Warning: the gem 'rack' was found in multiple sources.") - expect(err).to include("Installed from: #{file_uri_for(gem_repo2)}") + expect(err).to include("Installed from: https://gem.repo2") + + expect(lockfile).to eq <<~L + GEM + remote: https://gem.repo1/ + remote: https://gem.repo2/ + specs: + rack (1.0.0) + + GEM + remote: https://gem.repo3/ + specs: + depends_on_rack (1.0.1) + rack + + PLATFORMS + #{specific_local_platform} + + DEPENDENCIES + depends_on_rack! + + BUNDLED WITH + #{Bundler::VERSION} + L + + previous_lockfile = lockfile expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0") + expect(lockfile).to eq(previous_lockfile) end it "fails", :bundler => "3" do - bundle :install, :raise_on_error => false + bundle :install, :artifice => "compact_index", :raise_on_error => false expect(err).to include("Each source after the first must include a block") expect(exitstatus).to eq(4) end @@ -267,16 +293,16 @@ RSpec.describe "bundle install with gems on multiple sources" do end gemfile <<-G - source "#{file_uri_for(gem_repo3)}" # contains depends_on_rack - source "#{file_uri_for(gem_repo2)}" # contains broken rack + source "https://gem.repo3" # contains depends_on_rack + source "https://gem.repo2" # contains broken rack gem "depends_on_rack" # installed from gem_repo3 - gem "rack", :source => "#{file_uri_for(gem_repo1)}" + gem "rack", :source => "https://gem.repo1" G end it "installs the dependency from the pinned source without warning", :bundler => "< 3" do - bundle :install + bundle :install, :artifice => "compact_index" expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0") @@ -284,14 +310,14 @@ RSpec.describe "bundle install with gems on multiple sources" do # In https://github.com/rubygems/bundler/issues/3585 this failed # when there is already a lock file, and the gems are missing, so try again system_gems [] - bundle :install + bundle :install, :artifice => "compact_index" expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0") end it "fails", :bundler => "3" do - bundle :install, :raise_on_error => false + bundle :install, :artifice => "compact_index", :raise_on_error => false expect(err).to include("Each source after the first must include a block") expect(exitstatus).to eq(4) end @@ -308,360 +334,508 @@ RSpec.describe "bundle install with gems on multiple sources" do end gemfile <<-G - source "#{file_uri_for(gem_repo2)}" + source "https://gem.repo2" gem "private_gem_1" - source "#{file_uri_for(gem_repo3)}" do + source "https://gem.repo3" do gem "private_gem_2" end G end it "fails" do - bundle :install, :raise_on_error => false - expect(err).to include("Could not find gem 'private_gem_1' in rubygems repository #{file_uri_for(gem_repo2)}/ or installed locally.") + bundle :install, :artifice => "compact_index", :raise_on_error => false + expect(err).to include("Could not find gem 'private_gem_1' in rubygems repository https://gem.repo2/ or installed locally.") expect(err).to include("The source does not contain any versions of 'private_gem_1'") end end + context "when an indirect dependency can't be found in the aggregate rubygems source", :bundler => "< 3" do + before do + build_repo2 + + build_repo gem_repo3 do + build_gem "depends_on_missing", "1.0.1" do |s| + s.add_dependency "missing" + end + end + + gemfile <<-G + source "https://gem.repo2" + + source "https://gem.repo3" + + gem "depends_on_missing" + G + end + + 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.") + end + end + context "when a top-level gem has an indirect dependency" do - context "when disable_multisource is set" do - before do - bundle "config set disable_multisource true" + before do + build_repo gem_repo2 do + build_gem "depends_on_rack", "1.0.1" do |s| + s.add_dependency "rack" + end + end + + build_repo gem_repo3 do + build_gem "unrelated_gem", "1.0.0" end + gemfile <<-G + source "https://gem.repo2" + + gem "depends_on_rack" + + source "https://gem.repo3" do + gem "unrelated_gem" + end + G + end + + context "and the dependency is only in the top-level source" do before do - build_repo gem_repo2 do - build_gem "depends_on_rack", "1.0.1" do |s| - s.add_dependency "rack" - end + update_repo gem_repo2 do + build_gem "rack", "1.0.0" end + end - build_repo gem_repo3 do - build_gem "unrelated_gem", "1.0.0" + it "installs the dependency from the top-level source without warning" do + bundle :install, :artifice => "compact_index" + expect(err).not_to include("Warning") + expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", "unrelated_gem 1.0.0") + expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote2") + expect(the_bundle).to include_gems("unrelated_gem 1.0.0", :source => "remote3") + end + end + + context "and the dependency is only in a pinned source" do + before do + update_repo gem_repo3 do + build_gem "rack", "1.0.0" do |s| + s.write "lib/rack.rb", "RACK = 'FAIL'" + end end + end - gemfile <<-G - source "#{file_uri_for(gem_repo2)}" + 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." + ) + end + end - gem "depends_on_rack" + context "and the dependency is in both the top-level and a pinned source" do + before do + update_repo gem_repo2 do + build_gem "rack", "1.0.0" + end - source "#{file_uri_for(gem_repo3)}" do - gem "unrelated_gem" + update_repo gem_repo3 do + build_gem "rack", "1.0.0" do |s| + s.write "lib/rack.rb", "RACK = 'FAIL'" end - G + end end - context "and the dependency is only in the top-level source" do - before do - update_repo gem_repo2 do - build_gem "rack", "1.0.0" - end + it "installs the dependency from the top-level source without warning" do + bundle :install, :artifice => "compact_index" + expect(err).not_to include("Warning") + expect(run("require 'rack'; puts RACK")).to eq("1.0.0") + expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", "unrelated_gem 1.0.0") + expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote2") + expect(the_bundle).to include_gems("unrelated_gem 1.0.0", :source => "remote3") + end + end + end + + context "when a scoped gem has a deeply nested indirect dependency" do + before do + build_repo gem_repo3 do + build_gem "depends_on_depends_on_rack", "1.0.1" do |s| + s.add_dependency "depends_on_rack" end - it "installs all gems without warning" do - bundle :install - expect(err).not_to include("Warning") - expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", "unrelated_gem 1.0.0") + build_gem "depends_on_rack", "1.0.1" do |s| + s.add_dependency "rack" end end - context "and the dependency is only in a pinned source" do - before do - update_repo gem_repo3 do - build_gem "rack", "1.0.0" do |s| - s.write "lib/rack.rb", "RACK = 'FAIL'" - end - end + gemfile <<-G + source "https://gem.repo2" + + source "https://gem.repo3" do + gem "depends_on_depends_on_rack" end + G + end - it "does not find the dependency" do - bundle :install, :raise_on_error => false - expect(err).to include("Could not find gem 'rack', which is required by gem 'depends_on_rack', in any of the relevant sources") + context "and the dependency is only in the top-level source" do + before do + update_repo gem_repo2 do + build_gem "rack", "1.0.0" end end - context "and the dependency is in both the top-level and a pinned source" do - before do - update_repo gem_repo2 do - build_gem "rack", "1.0.0" - end + it "installs the dependency from the top-level source" do + bundle :install, :artifice => "compact_index" + expect(the_bundle).to include_gems("depends_on_depends_on_rack 1.0.1", "depends_on_rack 1.0.1", "rack 1.0.0") + expect(the_bundle).to include_gems("rack 1.0.0", :source => "remote2") + expect(the_bundle).to include_gems("depends_on_depends_on_rack 1.0.1", "depends_on_rack 1.0.1", :source => "remote3") + end + end - update_repo gem_repo3 do - build_gem "rack", "1.0.0" do |s| - s.write "lib/rack.rb", "RACK = 'FAIL'" - end - end - end + context "and the dependency is only in a pinned source" do + before do + build_repo2 - it "installs the dependency from the top-level source without warning" do - bundle :install - expect(err).not_to include("Warning") - expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", "unrelated_gem 1.0.0") + update_repo gem_repo3 do + build_gem "rack", "1.0.0" end end + + it "installs the dependency from the pinned source" do + bundle :install, :artifice => "compact_index" + expect(the_bundle).to include_gems("depends_on_depends_on_rack 1.0.1", "depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3") + end end - context "when the lockfile has aggregated rubygems sources and newer versions of dependencies are available" do + context "and the dependency is in both the top-level and a pinned source" do before do - build_repo gem_repo2 do - build_gem "activesupport", "6.0.3.4" do |s| - s.add_dependency "concurrent-ruby", "~> 1.0", ">= 1.0.2" - s.add_dependency "i18n", ">= 0.7", "< 2" - s.add_dependency "minitest", "~> 5.1" - s.add_dependency "tzinfo", "~> 1.1" - s.add_dependency "zeitwerk", "~> 2.2", ">= 2.2.2" + update_repo gem_repo2 do + build_gem "rack", "1.0.0" do |s| + s.write "lib/rack.rb", "RACK = 'FAIL'" end + end - build_gem "activesupport", "6.1.2.1" do |s| - s.add_dependency "concurrent-ruby", "~> 1.0", ">= 1.0.2" - s.add_dependency "i18n", ">= 1.6", "< 2" - s.add_dependency "minitest", ">= 5.1" - s.add_dependency "tzinfo", "~> 2.0" - s.add_dependency "zeitwerk", "~> 2.3" - end + update_repo gem_repo3 do + build_gem "rack", "1.0.0" + end + end + + it "installs the dependency from the pinned source without warning" do + bundle :install, :artifice => "compact_index" + expect(the_bundle).to include_gems("depends_on_depends_on_rack 1.0.1", "depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3") + end + end + end - build_gem "concurrent-ruby", "1.1.8" - build_gem "concurrent-ruby", "1.1.9" - build_gem "connection_pool", "2.2.3" + context "when the lockfile has aggregated rubygems sources and newer versions of dependencies are available" do + before do + build_repo gem_repo2 do + build_gem "activesupport", "6.0.3.4" do |s| + s.add_dependency "concurrent-ruby", "~> 1.0", ">= 1.0.2" + s.add_dependency "i18n", ">= 0.7", "< 2" + s.add_dependency "minitest", "~> 5.1" + s.add_dependency "tzinfo", "~> 1.1" + s.add_dependency "zeitwerk", "~> 2.2", ">= 2.2.2" + end - build_gem "i18n", "1.8.9" do |s| - s.add_dependency "concurrent-ruby", "~> 1.0" - end + build_gem "activesupport", "6.1.2.1" do |s| + s.add_dependency "concurrent-ruby", "~> 1.0", ">= 1.0.2" + s.add_dependency "i18n", ">= 1.6", "< 2" + s.add_dependency "minitest", ">= 5.1" + s.add_dependency "tzinfo", "~> 2.0" + s.add_dependency "zeitwerk", "~> 2.3" + end - build_gem "minitest", "5.14.3" - build_gem "rack", "2.2.3" - build_gem "redis", "4.2.5" + build_gem "concurrent-ruby", "1.1.8" + build_gem "concurrent-ruby", "1.1.9" + build_gem "connection_pool", "2.2.3" - build_gem "sidekiq", "6.1.3" do |s| - s.add_dependency "connection_pool", ">= 2.2.2" - s.add_dependency "rack", "~> 2.0" - s.add_dependency "redis", ">= 4.2.0" - end + build_gem "i18n", "1.8.9" do |s| + s.add_dependency "concurrent-ruby", "~> 1.0" + end - build_gem "thread_safe", "0.3.6" + build_gem "minitest", "5.14.3" + build_gem "rack", "2.2.3" + build_gem "redis", "4.2.5" - build_gem "tzinfo", "1.2.9" do |s| - s.add_dependency "thread_safe", "~> 0.1" - end + build_gem "sidekiq", "6.1.3" do |s| + s.add_dependency "connection_pool", ">= 2.2.2" + s.add_dependency "rack", "~> 2.0" + s.add_dependency "redis", ">= 4.2.0" + end - build_gem "tzinfo", "2.0.4" do |s| - s.add_dependency "concurrent-ruby", "~> 1.0" - end + build_gem "thread_safe", "0.3.6" - build_gem "zeitwerk", "2.4.2" + build_gem "tzinfo", "1.2.9" do |s| + s.add_dependency "thread_safe", "~> 0.1" end - build_repo gem_repo3 do - build_gem "sidekiq-pro", "5.2.1" do |s| - s.add_dependency "connection_pool", ">= 2.2.3" - s.add_dependency "sidekiq", ">= 6.1.0" - end + build_gem "tzinfo", "2.0.4" do |s| + s.add_dependency "concurrent-ruby", "~> 1.0" end - gemfile <<-G - # frozen_string_literal: true + build_gem "zeitwerk", "2.4.2" + end - source "#{file_uri_for(gem_repo2)}" + build_repo gem_repo3 do + build_gem "sidekiq-pro", "5.2.1" do |s| + s.add_dependency "connection_pool", ">= 2.2.3" + s.add_dependency "sidekiq", ">= 6.1.0" + end + end - gem "activesupport" + gemfile <<-G + # frozen_string_literal: true - source "#{file_uri_for(gem_repo3)}" do - gem "sidekiq-pro" - end - G + source "https://gem.repo2" - lockfile <<~L - GEM - remote: #{file_uri_for(gem_repo2)}/ - remote: #{file_uri_for(gem_repo3)}/ - specs: - activesupport (6.0.3.4) - concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - zeitwerk (~> 2.2, >= 2.2.2) - concurrent-ruby (1.1.8) - connection_pool (2.2.3) - i18n (1.8.9) - concurrent-ruby (~> 1.0) - minitest (5.14.3) - rack (2.2.3) - redis (4.2.5) - sidekiq (6.1.3) - connection_pool (>= 2.2.2) - rack (~> 2.0) - redis (>= 4.2.0) - sidekiq-pro (5.2.1) - connection_pool (>= 2.2.3) - sidekiq (>= 6.1.0) - thread_safe (0.3.6) - tzinfo (1.2.9) - thread_safe (~> 0.1) - zeitwerk (2.4.2) + gem "activesupport" - PLATFORMS - #{specific_local_platform} + source "https://gem.repo3" do + gem "sidekiq-pro" + end + G - DEPENDENCIES - activesupport - sidekiq-pro! + lockfile <<~L + GEM + remote: https://gem.repo2/ + remote: https://gem.repo3/ + specs: + activesupport (6.0.3.4) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + zeitwerk (~> 2.2, >= 2.2.2) + concurrent-ruby (1.1.8) + connection_pool (2.2.3) + i18n (1.8.9) + concurrent-ruby (~> 1.0) + minitest (5.14.3) + rack (2.2.3) + redis (4.2.5) + sidekiq (6.1.3) + connection_pool (>= 2.2.2) + rack (~> 2.0) + redis (>= 4.2.0) + sidekiq-pro (5.2.1) + connection_pool (>= 2.2.3) + sidekiq (>= 6.1.0) + thread_safe (0.3.6) + tzinfo (1.2.9) + thread_safe (~> 0.1) + zeitwerk (2.4.2) - BUNDLED WITH - #{Bundler::VERSION} - L - end + PLATFORMS + #{specific_local_platform} - it "does not install newer versions or generate lockfile changes when running bundle install, and warns", :bundler => "< 3" do - initial_lockfile = lockfile + DEPENDENCIES + activesupport + sidekiq-pro! - bundle :install + BUNDLED WITH + #{Bundler::VERSION} + L + end - expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.") + it "does not install newer versions but updates the lockfile format when running bundle install in non frozen mode, and doesn't warn" do + bundle :install, :artifice => "compact_index" + expect(err).to be_empty - expect(the_bundle).to include_gems("activesupport 6.0.3.4") - expect(the_bundle).not_to include_gems("activesupport 6.1.2.1") - expect(the_bundle).to include_gems("tzinfo 1.2.9") - expect(the_bundle).not_to include_gems("tzinfo 2.0.4") - expect(the_bundle).to include_gems("concurrent-ruby 1.1.8") - expect(the_bundle).not_to include_gems("concurrent-ruby 1.1.9") + expect(the_bundle).to include_gems("activesupport 6.0.3.4") + expect(the_bundle).not_to include_gems("activesupport 6.1.2.1") + expect(the_bundle).to include_gems("tzinfo 1.2.9") + expect(the_bundle).not_to include_gems("tzinfo 2.0.4") + expect(the_bundle).to include_gems("concurrent-ruby 1.1.8") + expect(the_bundle).not_to include_gems("concurrent-ruby 1.1.9") - expect(lockfile).to eq(initial_lockfile) - end + expect(lockfile).to eq <<~L + GEM + remote: https://gem.repo2/ + specs: + activesupport (6.0.3.4) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + zeitwerk (~> 2.2, >= 2.2.2) + concurrent-ruby (1.1.8) + connection_pool (2.2.3) + i18n (1.8.9) + concurrent-ruby (~> 1.0) + minitest (5.14.3) + rack (2.2.3) + redis (4.2.5) + sidekiq (6.1.3) + connection_pool (>= 2.2.2) + rack (~> 2.0) + redis (>= 4.2.0) + thread_safe (0.3.6) + tzinfo (1.2.9) + thread_safe (~> 0.1) + zeitwerk (2.4.2) - it "fails when running bundle install", :bundler => "3" do - initial_lockfile = lockfile + GEM + remote: https://gem.repo3/ + specs: + sidekiq-pro (5.2.1) + connection_pool (>= 2.2.3) + sidekiq (>= 6.1.0) - bundle :install, :raise_on_error => false + PLATFORMS + #{specific_local_platform} - expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.") + DEPENDENCIES + activesupport + sidekiq-pro! - expect(lockfile).to eq(initial_lockfile) - end + BUNDLED WITH + #{Bundler::VERSION} + L + end - it "splits sections and upgrades gems when running bundle update, and doesn't warn" do - bundle "update --all" - expect(err).to be_empty + it "does not install newer versions or generate lockfile changes when running bundle install in frozen mode, and warns", :bundler => "< 3" do + initial_lockfile = lockfile - expect(the_bundle).not_to include_gems("activesupport 6.0.3.4") - expect(the_bundle).to include_gems("activesupport 6.1.2.1") - expect(the_bundle).not_to include_gems("tzinfo 1.2.9") - expect(the_bundle).to include_gems("tzinfo 2.0.4") - expect(the_bundle).not_to include_gems("concurrent-ruby 1.1.8") - expect(the_bundle).to include_gems("concurrent-ruby 1.1.9") + bundle "config set --local frozen true" + bundle :install, :artifice => "compact_index" - expect(lockfile).to eq <<~L - GEM - remote: #{file_uri_for(gem_repo2)}/ - specs: - activesupport (6.1.2.1) - concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 1.6, < 2) - minitest (>= 5.1) - tzinfo (~> 2.0) - zeitwerk (~> 2.3) - concurrent-ruby (1.1.9) - connection_pool (2.2.3) - i18n (1.8.9) - concurrent-ruby (~> 1.0) - minitest (5.14.3) - rack (2.2.3) - redis (4.2.5) - sidekiq (6.1.3) - connection_pool (>= 2.2.2) - rack (~> 2.0) - redis (>= 4.2.0) - tzinfo (2.0.4) - concurrent-ruby (~> 1.0) - zeitwerk (2.4.2) + expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.") - GEM - remote: #{file_uri_for(gem_repo3)}/ - specs: - sidekiq-pro (5.2.1) - connection_pool (>= 2.2.3) - sidekiq (>= 6.1.0) + expect(the_bundle).to include_gems("activesupport 6.0.3.4") + expect(the_bundle).not_to include_gems("activesupport 6.1.2.1") + expect(the_bundle).to include_gems("tzinfo 1.2.9") + expect(the_bundle).not_to include_gems("tzinfo 2.0.4") + expect(the_bundle).to include_gems("concurrent-ruby 1.1.8") + expect(the_bundle).not_to include_gems("concurrent-ruby 1.1.9") - PLATFORMS - #{specific_local_platform} + expect(lockfile).to eq(initial_lockfile) + end - DEPENDENCIES - activesupport - sidekiq-pro! + it "fails when running bundle install in frozen mode", :bundler => "3" do + initial_lockfile = lockfile - BUNDLED WITH - #{Bundler::VERSION} - L - end + bundle "config set --local frozen true" + bundle :install, :artifice => "compact_index", :raise_on_error => false - it "it keeps the current lockfile format and upgrades the requested gem when running bundle update with an argument, and warns", :bundler => "< 3" do - bundle "update concurrent-ruby" - expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.") + expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.") - expect(the_bundle).to include_gems("activesupport 6.0.3.4") - expect(the_bundle).not_to include_gems("activesupport 6.1.2.1") - expect(the_bundle).to include_gems("tzinfo 1.2.9") - expect(the_bundle).not_to include_gems("tzinfo 2.0.4") - expect(the_bundle).to include_gems("concurrent-ruby 1.1.9") - expect(the_bundle).not_to include_gems("concurrent-ruby 1.1.8") + expect(lockfile).to eq(initial_lockfile) + end - expect(lockfile).to eq <<~L - GEM - remote: #{file_uri_for(gem_repo2)}/ - remote: #{file_uri_for(gem_repo3)}/ - specs: - activesupport (6.0.3.4) - concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - zeitwerk (~> 2.2, >= 2.2.2) - concurrent-ruby (1.1.9) - connection_pool (2.2.3) - i18n (1.8.9) - concurrent-ruby (~> 1.0) - minitest (5.14.3) - rack (2.2.3) - redis (4.2.5) - sidekiq (6.1.3) - connection_pool (>= 2.2.2) - rack (~> 2.0) - redis (>= 4.2.0) - sidekiq-pro (5.2.1) - connection_pool (>= 2.2.3) - sidekiq (>= 6.1.0) - thread_safe (0.3.6) - tzinfo (1.2.9) - thread_safe (~> 0.1) - zeitwerk (2.4.2) + it "splits sections and upgrades gems when running bundle update, and doesn't warn" do + bundle "update --all", :artifice => "compact_index" + expect(err).to be_empty - PLATFORMS - #{specific_local_platform} + expect(the_bundle).not_to include_gems("activesupport 6.0.3.4") + expect(the_bundle).to include_gems("activesupport 6.1.2.1") + expect(the_bundle).not_to include_gems("tzinfo 1.2.9") + expect(the_bundle).to include_gems("tzinfo 2.0.4") + expect(the_bundle).not_to include_gems("concurrent-ruby 1.1.8") + expect(the_bundle).to include_gems("concurrent-ruby 1.1.9") - DEPENDENCIES - activesupport - sidekiq-pro! + expect(lockfile).to eq <<~L + GEM + remote: https://gem.repo2/ + specs: + activesupport (6.1.2.1) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + zeitwerk (~> 2.3) + concurrent-ruby (1.1.9) + connection_pool (2.2.3) + i18n (1.8.9) + concurrent-ruby (~> 1.0) + minitest (5.14.3) + rack (2.2.3) + redis (4.2.5) + sidekiq (6.1.3) + connection_pool (>= 2.2.2) + rack (~> 2.0) + redis (>= 4.2.0) + tzinfo (2.0.4) + concurrent-ruby (~> 1.0) + zeitwerk (2.4.2) - BUNDLED WITH - #{Bundler::VERSION} - L - end + GEM + remote: https://gem.repo3/ + specs: + sidekiq-pro (5.2.1) + connection_pool (>= 2.2.3) + sidekiq (>= 6.1.0) + + PLATFORMS + #{specific_local_platform} + + DEPENDENCIES + activesupport + sidekiq-pro! + + BUNDLED WITH + #{Bundler::VERSION} + L + end - it "fails when running bundle update with an argument", :bundler => "3" do - initial_lockfile = lockfile + it "upgrades the lockfile format and upgrades the requested gem when running bundle update with an argument" do + bundle "update concurrent-ruby", :artifice => "compact_index" + expect(err).to be_empty - bundle "update concurrent-ruby", :raise_on_error => false + expect(the_bundle).to include_gems("activesupport 6.0.3.4") + expect(the_bundle).not_to include_gems("activesupport 6.1.2.1") + expect(the_bundle).to include_gems("tzinfo 1.2.9") + expect(the_bundle).not_to include_gems("tzinfo 2.0.4") + expect(the_bundle).to include_gems("concurrent-ruby 1.1.9") + expect(the_bundle).not_to include_gems("concurrent-ruby 1.1.8") - expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.") + expect(lockfile).to eq <<~L + GEM + remote: https://gem.repo2/ + specs: + activesupport (6.0.3.4) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + zeitwerk (~> 2.2, >= 2.2.2) + concurrent-ruby (1.1.9) + connection_pool (2.2.3) + i18n (1.8.9) + concurrent-ruby (~> 1.0) + minitest (5.14.3) + rack (2.2.3) + redis (4.2.5) + sidekiq (6.1.3) + connection_pool (>= 2.2.2) + rack (~> 2.0) + redis (>= 4.2.0) + thread_safe (0.3.6) + tzinfo (1.2.9) + thread_safe (~> 0.1) + zeitwerk (2.4.2) - expect(lockfile).to eq(initial_lockfile) - end + GEM + remote: https://gem.repo3/ + specs: + sidekiq-pro (5.2.1) + connection_pool (>= 2.2.3) + sidekiq (>= 6.1.0) + + PLATFORMS + #{specific_local_platform} + + DEPENDENCIES + activesupport + sidekiq-pro! + + BUNDLED WITH + #{Bundler::VERSION} + L end end - context "when a top-level gem has an indirect dependency present in the default source, but with a different version from the one resolved", :bundler => "< 3" do + context "when a top-level gem has an indirect dependency present in the default source, but with a different version from the one resolved" do before do build_lib "activesupport", "7.0.0.alpha", :path => lib_path("rails/activesupport") build_lib "rails", "7.0.0.alpha", :path => lib_path("rails") do |s| @@ -677,7 +851,7 @@ RSpec.describe "bundle install with gems on multiple sources" do end gemfile <<-G - source "#{file_uri_for(gem_repo2)}" + source "https://gem.repo2" gemspec :path => "#{lib_path("rails")}" @@ -686,7 +860,7 @@ RSpec.describe "bundle install with gems on multiple sources" do end it "installs all gems without warning" do - bundle :install + bundle :install, :artifice => "compact_index" expect(err).not_to include("Warning") expect(the_bundle).to include_gems("activesupport 7.0.0.alpha", "rails 7.0.0.alpha") expect(the_bundle).to include_gems("activesupport 7.0.0.alpha", :source => "path@#{lib_path("rails/activesupport")}") @@ -711,9 +885,9 @@ RSpec.describe "bundle install with gems on multiple sources" do end gemfile <<-G - source "#{file_uri_for(gem_repo2)}" + source "https://gem.repo2" - source "#{file_uri_for(gem_repo3)}" do + source "https://gem.repo3" do gem "handsoap" end @@ -724,14 +898,14 @@ RSpec.describe "bundle install with gems on multiple sources" do it "installs from the default source without any warnings or errors and generates a proper lockfile" do expected_lockfile = <<~L GEM - remote: #{file_uri_for(gem_repo2)}/ + remote: https://gem.repo2/ specs: nokogiri (1.11.1) racca (~> 1.4) racca (1.5.2) GEM - remote: #{file_uri_for(gem_repo3)}/ + remote: https://gem.repo3/ specs: handsoap (0.2.5.5) nokogiri (>= 1.2.3) @@ -747,7 +921,7 @@ RSpec.describe "bundle install with gems on multiple sources" do #{Bundler::VERSION} L - bundle "install --verbose" + bundle "install --verbose", :artifice => "compact_index" expect(err).not_to include("Warning") expect(the_bundle).to include_gems("handsoap 0.2.5.5", "nokogiri 1.11.1", "racca 1.5.2") expect(the_bundle).to include_gems("handsoap 0.2.5.5", :source => "remote3") @@ -756,7 +930,7 @@ RSpec.describe "bundle install with gems on multiple sources" do # Even if the gems are already installed FileUtils.rm bundled_app_lock - bundle "install --verbose" + bundle "install --verbose", :artifice => "compact_index" expect(err).not_to include("Warning") expect(the_bundle).to include_gems("handsoap 0.2.5.5", "nokogiri 1.11.1", "racca 1.5.2") expect(the_bundle).to include_gems("handsoap 0.2.5.5", :source => "remote3") @@ -771,9 +945,9 @@ RSpec.describe "bundle install with gems on multiple sources" do build_gem "not_in_repo1", "1.0.0" end - install_gemfile <<-G, :raise_on_error => false - source "#{file_uri_for(gem_repo3)}" - gem "not_in_repo1", :source => "#{file_uri_for(gem_repo1)}" + install_gemfile <<-G, :artifice => "compact_index", :raise_on_error => false + source "https://gem.repo3" + gem "not_in_repo1", :source => "https://gem.repo1" G end @@ -788,24 +962,24 @@ RSpec.describe "bundle install with gems on multiple sources" do lockfile <<-L GEM - remote: #{file_uri_for(gem_repo1)} + remote: https://gem.repo1 specs: GEM - remote: #{file_uri_for(gem_repo3)} + remote: https://gem.repo3 specs: rack (0.9.1) PLATFORMS - ruby + #{specific_local_platform} DEPENDENCIES rack! L gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - source "#{file_uri_for(gem_repo3)}" do + source "https://gem.repo1" + source "https://gem.repo3" do gem 'rack' end G @@ -821,8 +995,8 @@ RSpec.describe "bundle install with gems on multiple sources" do let(:aggregate_gem_section_lockfile) do <<~L GEM - remote: #{file_uri_for(gem_repo1)}/ - remote: #{file_uri_for(gem_repo3)}/ + remote: https://gem.repo1/ + remote: https://gem.repo3/ specs: rack (0.9.1) @@ -840,11 +1014,11 @@ RSpec.describe "bundle install with gems on multiple sources" do let(:split_gem_section_lockfile) do <<~L GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: https://gem.repo1/ specs: GEM - remote: #{file_uri_for(gem_repo3)}/ + remote: https://gem.repo3/ specs: rack (0.9.1) @@ -865,8 +1039,8 @@ RSpec.describe "bundle install with gems on multiple sources" do end gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - source "#{file_uri_for(gem_repo3)}" do + source "https://gem.repo1" + source "https://gem.repo3" do gem 'rack' end G @@ -877,7 +1051,7 @@ RSpec.describe "bundle install with gems on multiple sources" do it "installs the existing lockfile but prints a warning", :bundler => "< 3" do bundle "config set --local deployment true" - bundle "install" + bundle "install", :artifice => "compact_index" expect(lockfile).to eq(aggregate_gem_section_lockfile) expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.") @@ -887,7 +1061,7 @@ RSpec.describe "bundle install with gems on multiple sources" do it "refuses to install the existing lockfile and prints an error", :bundler => "3" do bundle "config set --local deployment true" - bundle "install", :raise_on_error =>false + bundle "install", :artifice => "compact_index", :raise_on_error =>false expect(lockfile).to eq(aggregate_gem_section_lockfile) expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.") @@ -900,13 +1074,13 @@ RSpec.describe "bundle install with gems on multiple sources" do build_lib "foo" gemfile <<-G - gem "rack", :source => "#{file_uri_for(gem_repo1)}" + gem "rack", :source => "https://gem.repo1" gem "foo", :path => "#{lib_path("foo-1.0")}" G end it "does not unlock the non-path gem after install" do - bundle :install + bundle :install, :artifice => "compact_index" bundle %(exec ruby -e 'puts "OK"') @@ -919,8 +1093,8 @@ RSpec.describe "bundle install with gems on multiple sources" do before do system_gems "rack-0.9.1" - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + install_gemfile <<-G, :artifice => "compact_index" + source "https://gem.repo1" gem "rack" # should come from repo1! G end @@ -941,14 +1115,14 @@ RSpec.describe "bundle install with gems on multiple sources" do # Installing this gemfile... gemfile <<-G - source '#{file_uri_for(gem_repo1)}' + source 'https://gem.repo1' gem 'rack' - gem 'foo', '~> 0.1', :source => '#{file_uri_for(gem_repo4)}' - gem 'bar', '~> 0.1', :source => '#{file_uri_for(gem_repo4)}' + gem 'foo', '~> 0.1', :source => 'https://gem.repo4' + gem 'bar', '~> 0.1', :source => 'https://gem.repo4' G bundle "config set --local path ../gems/system" - bundle :install + bundle :install, :artifice => "compact_index" # And then we add some new versions... update_repo4 do @@ -959,11 +1133,11 @@ RSpec.describe "bundle install with gems on multiple sources" do it "allows them to be unlocked separately" do # And install this gemfile, updating only foo. - install_gemfile <<-G - source '#{file_uri_for(gem_repo1)}' + install_gemfile <<-G, :artifice => "compact_index" + source 'https://gem.repo1' gem 'rack' - gem 'foo', '~> 0.2', :source => '#{file_uri_for(gem_repo4)}' - gem 'bar', '~> 0.1', :source => '#{file_uri_for(gem_repo4)}' + gem 'foo', '~> 0.2', :source => 'https://gem.repo4' + gem 'bar', '~> 0.1', :source => 'https://gem.repo4' G # It should update foo to 0.2, but not the (locked) bar 0.1 @@ -983,11 +1157,11 @@ RSpec.describe "bundle install with gems on multiple sources" do build_git "git1" build_git "git2" - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + install_gemfile <<-G, :artifice => "compact_index" + source "https://gem.repo1" gem "rails" - source "#{file_uri_for(gem_repo3)}" do + source "https://gem.repo3" do gem "rack" end @@ -999,7 +1173,7 @@ RSpec.describe "bundle install with gems on multiple sources" do end it "does not re-resolve" do - bundle :install, :verbose => true + bundle :install, :artifice => "compact_index", :verbose => true expect(out).to include("using resolution from the lockfile") expect(out).not_to include("re-resolving dependencies") end @@ -1008,27 +1182,24 @@ RSpec.describe "bundle install with gems on multiple sources" do context "when a gem is installed to system gems" do before do - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + install_gemfile <<-G, :artifice => "compact_index" + source "https://gem.repo1" gem "rack" G end context "and the gemfile changes" do it "is still able to find that gem from remote sources" do - source_uri = file_uri_for(gem_repo1) - second_uri = file_uri_for(gem_repo4) - build_repo4 do build_gem "rack", "2.0.1.1.forked" build_gem "thor", "0.19.1.1.forked" end # When this gemfile is installed... - install_gemfile <<-G - source "#{source_uri}" + install_gemfile <<-G, :artifice => "compact_index" + source "https://gem.repo1" - source "#{second_uri}" do + source "https://gem.repo4" do gem "rack", "2.0.1.1.forked" gem "thor" end @@ -1037,9 +1208,9 @@ RSpec.describe "bundle install with gems on multiple sources" do # Then we change the Gemfile by adding a version to thor gemfile <<-G - source "#{source_uri}" + source "https://gem.repo1" - source "#{second_uri}" do + source "https://gem.repo4" do gem "rack", "2.0.1.1.forked" gem "thor", "0.19.1.1.forked" end @@ -1047,15 +1218,15 @@ RSpec.describe "bundle install with gems on multiple sources" do G # But we should still be able to find rack 2.0.1.1.forked and install it - bundle :install + bundle :install, :artifice => "compact_index" end end end describe "source changed to one containing a higher version of a dependency" do before do - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + install_gemfile <<-G, :artifice => "compact_index" + source "https://gem.repo1" gem "rack" G @@ -1072,8 +1243,8 @@ RSpec.describe "bundle install with gems on multiple sources" do s.add_dependency "bar", "=1.0.0" end - install_gemfile <<-G - source "#{file_uri_for(gem_repo2)}" + install_gemfile <<-G, :artifice => "compact_index" + source "https://gem.repo2" gem "rack" gemspec :path => "#{tmp.join("gemspec_test")}" G @@ -1093,10 +1264,10 @@ RSpec.describe "bundle install with gems on multiple sources" do build_gem "example", "1.0.2" end - install_gemfile <<-G - source "#{file_uri_for(gem_repo4)}" + install_gemfile <<-G, :artifice => "compact_index" + source "https://gem.repo4" - gem "example", :source => "#{file_uri_for(gem_repo2)}" + gem "example", :source => "https://gem.repo2" G bundle "info example" @@ -1104,12 +1275,60 @@ RSpec.describe "bundle install with gems on multiple sources" do system_gems "example-1.0.2", :path => default_bundle_path, :gem_repo => gem_repo4 - bundle "update example --verbose" + bundle "update example --verbose", :artifice => "compact_index" expect(out).not_to include("Using example 1.0.2") expect(out).to include("Using example 0.1.0") end - context "when a gem is available from multiple ambiguous sources", :bundler => "3" do + it "fails inmmediately with a helpful error when a non retriable network error happens while resolving sources" do + gemfile <<-G + source "https://gem.repo1" + + source "https://gem.repo4" do + gem "example" + end + G + + simulate_bundler_version_when_missing_prerelease_default_gem_activation do + ruby <<~R, :raise_on_error => false + require 'bundler/setup' + R + end + + expect(last_command).to be_failure + expect(err).to include("Could not reach host gem.repo4. Check your network connection and try again.") + end + + context "when an indirect dependency is available from multiple ambiguous sources", :bundler => "< 3" do + it "succeeds but warns, suggesting a source block" do + build_repo4 do + build_gem "depends_on_rack" do |s| + s.add_dependency "rack" + end + build_gem "rack" + end + + install_gemfile <<-G, :artifice => "compact_index", :raise_on_error => false + source "https://gem.repo4" do + gem "depends_on_rack" + end + + source "https://gem.repo1" do + gem "thin" + end + G + expect(err).to eq strip_whitespace(<<-EOS).strip + Warning: The gem 'rack' was found in multiple relevant sources. + * rubygems repository https://gem.repo1/ or installed locally + * rubygems repository https://gem.repo4/ or installed locally + You should add this gem to the source block for the source you wish it to be installed from. + EOS + expect(last_command).to be_success + expect(the_bundle).to be_locked + end + end + + context "when an indirect dependency is available from multiple ambiguous sources", :bundler => "3" do it "raises, suggesting a source block" do build_repo4 do build_gem "depends_on_rack" do |s| @@ -1118,18 +1337,19 @@ RSpec.describe "bundle install with gems on multiple sources" do build_gem "rack" end - install_gemfile <<-G, :raise_on_error => false - source "#{file_uri_for(gem_repo4)}" - source "#{file_uri_for(gem_repo1)}" do + install_gemfile <<-G, :artifice => "compact_index", :raise_on_error => false + source "https://gem.repo4" do + gem "depends_on_rack" + end + source "https://gem.repo1" do gem "thin" end - gem "depends_on_rack" G expect(last_command).to be_failure expect(err).to eq strip_whitespace(<<-EOS).strip The gem 'rack' was found in multiple relevant sources. - * rubygems repository #{file_uri_for(gem_repo1)}/ or installed locally - * rubygems repository #{file_uri_for(gem_repo4)}/ or installed locally + * rubygems repository https://gem.repo1/ or installed locally + * rubygems repository https://gem.repo4/ or installed locally You must add this gem to the source block for the source you wish it to be installed from. EOS expect(the_bundle).not_to be_locked diff --git a/spec/bundler/install/gemfile/specific_platform_spec.rb b/spec/bundler/install/gemfile/specific_platform_spec.rb index a5b78443b9..c6e526a95e 100644 --- a/spec/bundler/install/gemfile/specific_platform_spec.rb +++ b/spec/bundler/install/gemfile/specific_platform_spec.rb @@ -141,10 +141,10 @@ RSpec.describe "bundle install with specific platforms" do 2.1.4 L - bundle "install --verbose", :artifice => :compact_index, :env => { "BUNDLER_VERSION" => "2.1.4", "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s } + bundle "install --verbose", :artifice => "compact_index", :env => { "BUNDLER_VERSION" => "2.1.4", "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s } expect(out).to include("Installing libv8 8.4.255.0 (universal-darwin)") - bundle "add mini_racer --verbose", :artifice => :compact_index, :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s } + bundle "add mini_racer --verbose", :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s } expect(out).to include("Using libv8 8.4.255.0 (universal-darwin)") end diff --git a/spec/bundler/install/gems/compact_index_spec.rb b/spec/bundler/install/gems/compact_index_spec.rb index 9454508e41..8be97ed5d2 100644 --- a/spec/bundler/install/gems/compact_index_spec.rb +++ b/spec/bundler/install/gems/compact_index_spec.rb @@ -366,31 +366,6 @@ The checksum of /versions does not match the checksum provided by the server! So expect(the_bundle).to include_gems "activesupport 1.2.3" end - it "considers all possible versions of dependencies from all api gem sources when using blocks", :bundler => "< 3" do - # In this scenario, the gem "somegem" only exists in repo4. It depends on specific version of activesupport that - # exists only in repo1. There happens also be a version of activesupport in repo4, but not the one that version 1.0.0 - # of somegem wants. This test makes sure that bundler actually finds version 1.2.3 of active support in the other - # repo and installs it. - build_repo4 do - build_gem "activesupport", "1.2.0" - build_gem "somegem", "1.0.0" do |s| - s.add_dependency "activesupport", "1.2.3" # This version exists only in repo1 - end - end - - gemfile <<-G - source "#{source_uri}" - source "#{source_uri}/extra" do - gem 'somegem', '1.0.0' - end - G - - bundle :install, :artifice => "compact_index_extra_api" - - expect(the_bundle).to include_gems "somegem 1.0.0" - expect(the_bundle).to include_gems "activesupport 1.2.3" - end - it "prints API output properly with back deps" do build_repo2 do build_gem "back_deps" do |s| @@ -467,7 +442,7 @@ The checksum of /versions does not match the checksum provided by the server! So expect(the_bundle).to include_gems "foo 1.0" end - it "fetches again when more dependencies are found in subsequent sources using --deployment", :bundler => "< 3" do + it "fetches again when more dependencies are found in subsequent sources using deployment mode", :bundler => "< 3" do build_repo2 do build_gem "back_deps" do |s| s.add_dependency "foo" @@ -482,8 +457,8 @@ The checksum of /versions does not match the checksum provided by the server! So G bundle :install, :artifice => "compact_index_extra" - - bundle "install --deployment", :artifice => "compact_index_extra" + bundle "config --set local deployment true" + bundle :install, :artifice => "compact_index_extra" expect(the_bundle).to include_gems "back_deps 1.0" end diff --git a/spec/bundler/install/gems/dependency_api_spec.rb b/spec/bundler/install/gems/dependency_api_spec.rb index d8d2ac1668..eae8daa682 100644 --- a/spec/bundler/install/gems/dependency_api_spec.rb +++ b/spec/bundler/install/gems/dependency_api_spec.rb @@ -338,31 +338,6 @@ RSpec.describe "gemcutter's dependency API" do expect(the_bundle).to include_gems "activesupport 1.2.3" end - it "considers all possible versions of dependencies from all api gem sources using blocks" do - # In this scenario, the gem "somegem" only exists in repo4. It depends on specific version of activesupport that - # exists only in repo1. There happens also be a version of activesupport in repo4, but not the one that version 1.0.0 - # of somegem wants. This test makes sure that bundler actually finds version 1.2.3 of active support in the other - # repo and installs it. - build_repo4 do - build_gem "activesupport", "1.2.0" - build_gem "somegem", "1.0.0" do |s| - s.add_dependency "activesupport", "1.2.3" # This version exists only in repo1 - end - end - - gemfile <<-G - source "#{source_uri}" - source "#{source_uri}/extra" do - gem 'somegem', '1.0.0' - end - G - - bundle :install, :artifice => "endpoint_extra_api" - - expect(the_bundle).to include_gems "somegem 1.0.0" - expect(the_bundle).to include_gems "activesupport 1.2.3" - end - it "prints API output properly with back deps" do build_repo2 do build_gem "back_deps" do |s| @@ -438,7 +413,7 @@ RSpec.describe "gemcutter's dependency API" do expect(the_bundle).to include_gems "foo 1.0" end - it "fetches again when more dependencies are found in subsequent sources using --deployment", :bundler => "< 3" do + it "fetches again when more dependencies are found in subsequent sources using deployment mode", :bundler => "< 3" do build_repo2 do build_gem "back_deps" do |s| s.add_dependency "foo" @@ -453,8 +428,8 @@ RSpec.describe "gemcutter's dependency API" do G bundle :install, :artifice => "endpoint_extra" - - bundle "install --deployment", :artifice => "endpoint_extra" + bundle "config set --local deployment true" + bundle :install, :artifice => "endpoint_extra" expect(the_bundle).to include_gems "back_deps 1.0" end @@ -474,7 +449,6 @@ RSpec.describe "gemcutter's dependency API" do G bundle :install, :artifice => "endpoint_extra" - bundle "config set --local deployment true" bundle "install", :artifice => "endpoint_extra" expect(the_bundle).to include_gems "back_deps 1.0" diff --git a/spec/bundler/install/global_cache_spec.rb b/spec/bundler/install/global_cache_spec.rb index f3609715fb..68ebef2d89 100644 --- a/spec/bundler/install/global_cache_spec.rb +++ b/spec/bundler/install/global_cache_spec.rb @@ -113,6 +113,8 @@ RSpec.describe "global gem caching" do expect(source2_global_cache("rack-0.9.1.gem")).to exist bundle :install, :artifice => "compact_index_no_gem", :raise_on_error => false expect(err).to include("Internal Server Error 500") + expect(err).not_to include("please copy and paste the report template above into a new issue") + # rack 1.0.0 is not installed and rack 0.9.1 is not expect(the_bundle).not_to include_gems "rack 1.0.0" expect(the_bundle).not_to include_gems "rack 0.9.1" @@ -126,6 +128,8 @@ RSpec.describe "global gem caching" do expect(source2_global_cache("rack-0.9.1.gem")).to exist bundle :install, :artifice => "compact_index_no_gem", :raise_on_error => false expect(err).to include("Internal Server Error 500") + expect(err).not_to include("please copy and paste the report template above into a new issue") + # rack 0.9.1 is not installed and rack 1.0.0 is not expect(the_bundle).not_to include_gems "rack 0.9.1" expect(the_bundle).not_to include_gems "rack 1.0.0" diff --git a/spec/bundler/lock/lockfile_spec.rb b/spec/bundler/lock/lockfile_spec.rb index d68410824e..0fbe9ee80d 100644 --- a/spec/bundler/lock/lockfile_spec.rb +++ b/spec/bundler/lock/lockfile_spec.rb @@ -1347,7 +1347,7 @@ RSpec.describe "the lockfile format" do expect do ruby <<-RUBY - require '#{lib_dir}/bundler' + require '#{entrypoint}' Bundler.setup RUBY end.not_to change { File.mtime(bundled_app_lock) } diff --git a/spec/bundler/other/major_deprecation_spec.rb b/spec/bundler/other/major_deprecation_spec.rb index 92b05d8b74..3ffb138104 100644 --- a/spec/bundler/other/major_deprecation_spec.rb +++ b/spec/bundler/other/major_deprecation_spec.rb @@ -409,10 +409,38 @@ RSpec.describe "major deprecations" do ) end + it "doesn't show lockfile deprecations if there's a lockfile", :bundler => "< 3" do + bundle "install" + + expect(deprecations).to include( + "Your Gemfile contains multiple primary sources. " \ + "Using `source` more than once without a block is a security risk, and " \ + "may result in installing unexpected gems. To resolve this warning, use " \ + "a block to indicate which gems should come from the secondary source." + ) + expect(deprecations).not_to include( + "Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. " \ + "Make sure you run `bundle install` in non frozen mode and commit the result to make your lockfile secure." + ) + bundle "config set --local frozen true" + bundle "install" + + expect(deprecations).to include( + "Your Gemfile contains multiple primary sources. " \ + "Using `source` more than once without a block is a security risk, and " \ + "may result in installing unexpected gems. To resolve this warning, use " \ + "a block to indicate which gems should come from the secondary source." + ) + expect(deprecations).not_to include( + "Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. " \ + "Make sure you run `bundle install` in non frozen mode and commit the result to make your lockfile secure." + ) + end + pending "fails with a helpful error", :bundler => "3" end - context "bundle install with a lockfile with a single rubygems section with multiple remotes" do + context "bundle install in frozen mode with a lockfile with a single rubygems section with multiple remotes" do before do build_repo gem_repo3 do build_gem "rack", "0.9.1" @@ -441,12 +469,14 @@ RSpec.describe "major deprecations" do BUNDLED WITH #{Bundler::VERSION} L + + bundle "config set --local frozen true" end it "shows a deprecation", :bundler => "< 3" do bundle "install" - expect(deprecations).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. You should run `bundle update` or generate your lockfile from scratch.") + expect(deprecations).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. Make sure you run `bundle install` in non frozen mode and commit the result to make your lockfile secure.") end pending "fails with a helpful error", :bundler => "3" @@ -461,7 +491,7 @@ RSpec.describe "major deprecations" do G ruby <<-RUBY - require '#{lib_dir}/bundler' + require '#{entrypoint}' Bundler.setup Bundler.setup @@ -569,18 +599,6 @@ The :gist git source is deprecated, and will be removed in the future. Add this G end - context "without flags" do - before do - bundle :show - end - - it "prints a deprecation warning recommending `bundle list`", :bundler => "< 3" do - expect(deprecations).to include("use `bundle list` instead of `bundle show`") - end - - pending "fails with a helpful message", :bundler => "3" - end - context "with --outdated flag" do before do bundle "show --outdated" @@ -592,54 +610,6 @@ The :gist git source is deprecated, and will be removed in the future. Add this pending "fails with a helpful message", :bundler => "3" end - - context "with --verbose flag" do - before do - bundle "show --verbose" - end - - it "prints a deprecation warning informing about its removal", :bundler => "< 3" do - expect(deprecations).to include("the `--verbose` flag to `bundle show` was undocumented and will be removed without replacement") - end - - pending "fails with a helpful message", :bundler => "3" - end - - context "with a gem argument" do - before do - bundle "show rack" - end - - it "prints a deprecation warning recommending `bundle info`", :bundler => "< 3" do - expect(deprecations).to include("use `bundle info rack` instead of `bundle show rack`") - end - - pending "fails with a helpful message", :bundler => "3" - end - - context "with the --paths option" do - before do - bundle "show --paths" - end - - it "prints a deprecation warning recommending `bundle list`", :bundler => "< 3" do - expect(deprecations).to include("use `bundle list` instead of `bundle show --paths`") - end - - pending "fails with a helpful message", :bundler => "3" - end - - context "with a gem argument and the --paths option" do - before do - bundle "show rack --paths" - end - - it "prints deprecation warning recommending `bundle info`", :bundler => "< 3" do - expect(deprecations).to include("use `bundle info rack --path` instead of `bundle show rack --paths`") - end - - pending "fails with a helpful message", :bundler => "3" - end end context "bundle console" do diff --git a/spec/bundler/realworld/double_check_spec.rb b/spec/bundler/realworld/double_check_spec.rb index 07697f080e..d7f28d10bb 100644 --- a/spec/bundler/realworld/double_check_spec.rb +++ b/spec/bundler/realworld/double_check_spec.rb @@ -25,9 +25,9 @@ RSpec.describe "double checking sources", :realworld => true do RUBY cmd = <<-RUBY - require "#{lib_dir}/bundler" + require "#{entrypoint}" require "#{spec_dir}/support/artifice/vcr" - require "#{lib_dir}/bundler/inline" + require "#{entrypoint}/inline" gemfile(true) do source "https://rubygems.org" gem "rails", path: "." diff --git a/spec/bundler/realworld/edgecases_spec.rb b/spec/bundler/realworld/edgecases_spec.rb index 9f6ae399af..e0844bbeba 100644 --- a/spec/bundler/realworld/edgecases_spec.rb +++ b/spec/bundler/realworld/edgecases_spec.rb @@ -4,9 +4,9 @@ RSpec.describe "real world edgecases", :realworld => true do def rubygems_version(name, requirement) ruby <<-RUBY require "#{spec_dir}/support/artifice/vcr" - require "#{lib_dir}/bundler" - require "#{lib_dir}/bundler/source/rubygems/remote" - require "#{lib_dir}/bundler/fetcher" + require "#{entrypoint}" + require "#{entrypoint}/source/rubygems/remote" + require "#{entrypoint}/fetcher" rubygem = Bundler.ui.silence do source = Bundler::Source::Rubygems::Remote.new(Bundler::URI("https://rubygems.org")) fetcher = Bundler::Fetcher.new(source) diff --git a/spec/bundler/runtime/inline_spec.rb b/spec/bundler/runtime/inline_spec.rb index 57b7392608..cfcf556658 100644 --- a/spec/bundler/runtime/inline_spec.rb +++ b/spec/bundler/runtime/inline_spec.rb @@ -2,7 +2,7 @@ RSpec.describe "bundler/inline#gemfile" do def script(code, options = {}) - requires = ["#{lib_dir}/bundler/inline"] + requires = ["#{entrypoint}/inline"] requires.unshift "#{spec_dir}/support/artifice/" + options.delete(:artifice) if options.key?(:artifice) requires = requires.map {|r| "require '#{r}'" }.join("\n") ruby("#{requires}\n\n" + code, options) @@ -93,7 +93,7 @@ RSpec.describe "bundler/inline#gemfile" do it "lets me use my own ui object" do script <<-RUBY, :artifice => "endpoint" - require '#{lib_dir}/bundler' + require '#{entrypoint}' class MyBundlerUI < Bundler::UI::Silent def confirm(msg, newline = nil) puts "CONFIRMED!" @@ -110,7 +110,7 @@ RSpec.describe "bundler/inline#gemfile" do it "has an option for quiet installation" do script <<-RUBY, :artifice => "endpoint" - require '#{lib_dir}/bundler/inline' + require '#{entrypoint}/inline' gemfile(true, :quiet => true) do source "https://notaserver.com" @@ -136,7 +136,7 @@ RSpec.describe "bundler/inline#gemfile" do it "does not mutate the option argument" do script <<-RUBY - require '#{lib_dir}/bundler' + require '#{entrypoint}' options = { :ui => Bundler::UI::Shell.new } gemfile(false, options) do path "#{lib_path}" do @@ -218,7 +218,7 @@ RSpec.describe "bundler/inline#gemfile" do rake BUNDLED WITH - 1.13.6 + #{Bundler::VERSION} G script <<-RUBY diff --git a/spec/bundler/runtime/load_spec.rb b/spec/bundler/runtime/load_spec.rb index 0274ba18b8..96a22a46cc 100644 --- a/spec/bundler/runtime/load_spec.rb +++ b/spec/bundler/runtime/load_spec.rb @@ -82,7 +82,7 @@ RSpec.describe "Bundler.load" do G ruby <<-RUBY - require "#{lib_dir}/bundler" + require "#{entrypoint}" Bundler.setup :default Bundler.require :default puts RACK diff --git a/spec/bundler/runtime/platform_spec.rb b/spec/bundler/runtime/platform_spec.rb index bec42e0f70..d81bccbdf8 100644 --- a/spec/bundler/runtime/platform_spec.rb +++ b/spec/bundler/runtime/platform_spec.rb @@ -22,7 +22,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" do ruby <<-R begin - require '#{lib_dir}/bundler' + require '#{entrypoint}' Bundler.ui.silence { Bundler.setup } rescue Bundler::GemNotFound => e puts "WIN" diff --git a/spec/bundler/runtime/require_spec.rb b/spec/bundler/runtime/require_spec.rb index ad30529e86..a3fa4fbe47 100644 --- a/spec/bundler/runtime/require_spec.rb +++ b/spec/bundler/runtime/require_spec.rb @@ -192,7 +192,7 @@ RSpec.describe "Bundler.require" do G cmd = <<-RUBY - require '#{lib_dir}/bundler' + require '#{entrypoint}' Bundler.require RUBY ruby(cmd) diff --git a/spec/bundler/runtime/setup_spec.rb b/spec/bundler/runtime/setup_spec.rb index 4d5e1c616e..d8ba569f0a 100644 --- a/spec/bundler/runtime/setup_spec.rb +++ b/spec/bundler/runtime/setup_spec.rb @@ -108,8 +108,8 @@ RSpec.describe "Bundler.setup" do context "load order" do def clean_load_path(lp) without_bundler_load_path = ruby("puts $LOAD_PATH").split("\n") - lp -= without_bundler_load_path - lp.map! {|p| p.sub(/^#{Regexp.union system_gem_path.to_s, default_bundle_path.to_s, lib_dir.to_s}/i, "") } + lp -= [*without_bundler_load_path, lib_dir.to_s] + lp.map! {|p| p.sub(system_gem_path.to_s, "") } end it "puts loaded gems after -I and RUBYLIB", :ruby_repo do @@ -143,12 +143,8 @@ RSpec.describe "Bundler.setup" do gem "rails" G - # We require an absolute path because relying on the $LOAD_PATH behaves - # inconsistently depending on whether we're in a ruby-core setup (and - # bundler's lib is in RUBYLIB) or not. - ruby <<-RUBY - require '#{lib_dir}/bundler' + require 'bundler' Bundler.setup puts $LOAD_PATH RUBY @@ -157,7 +153,6 @@ RSpec.describe "Bundler.setup" do expect(load_path).to start_with( "/gems/rails-2.3.2/lib", - "/gems/bundler-#{Bundler::VERSION}/lib", "/gems/activeresource-2.3.2/lib", "/gems/activerecord-2.3.2/lib", "/gems/actionpack-2.3.2/lib", @@ -168,6 +163,8 @@ RSpec.describe "Bundler.setup" do end it "falls back to order the load path alphabetically for backwards compatibility" do + bundle "config set path.system true" + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "weakling" @@ -175,12 +172,8 @@ RSpec.describe "Bundler.setup" do gem "terranova" G - # We require an absolute path because relying on the $LOAD_PATH behaves - # inconsistently depending on whether we're in a ruby-core setup (and - # bundler's lib is in RUBYLIB) or not. - ruby <<-RUBY - require '#{lib_dir}/bundler/setup' + require 'bundler/setup' puts $LOAD_PATH RUBY @@ -200,8 +193,6 @@ RSpec.describe "Bundler.setup" do gem "rack" G - entrypoint = mis_activates_prerelease_default_bundler? ? "#{lib_dir}/bundler" : "bundler" - ruby <<-R require '#{entrypoint}' @@ -474,8 +465,6 @@ RSpec.describe "Bundler.setup" do break_git! - entrypoint = mis_activates_prerelease_default_bundler? ? "#{lib_dir}/bundler" : "bundler" - ruby <<-R require "#{entrypoint}" @@ -1126,9 +1115,8 @@ end context "is not present" do it "does not change the lock" do - entrypoint = mis_activates_prerelease_default_bundler? ? "#{lib_dir}/bundler/setup" : "bundler/setup" lockfile lock_with(nil) - ruby "require '#{entrypoint}'" + ruby "require '#{entrypoint}/setup'" lockfile_should_be lock_with(nil) end end @@ -1145,10 +1133,9 @@ end context "is older" do it "does not change the lock" do - entrypoint = mis_activates_prerelease_default_bundler? ? "#{lib_dir}/bundler/setup" : "bundler/setup" system_gems "bundler-1.10.1" lockfile lock_with("1.10.1") - ruby "require '#{entrypoint}'" + ruby "require '#{entrypoint}/setup'" lockfile_should_be lock_with("1.10.1") end end @@ -1219,9 +1206,8 @@ end describe "with gemified standard libraries" do it "does not load Psych" do gemfile "" - entrypoint = mis_activates_prerelease_default_bundler? ? "#{lib_dir}/bundler/setup" : "bundler/setup" ruby <<-RUBY - require '#{entrypoint}' + require '#{entrypoint}/setup' puts defined?(Psych::VERSION) ? Psych::VERSION : "undefined" require 'psych' puts Psych::VERSION @@ -1422,9 +1408,4 @@ end expect(last_command.stdboth).to eq("true") end end - - # Tested rubygems does not include https://github.com/rubygems/rubygems/pull/2728 and will not always end up activating the current bundler - def mis_activates_prerelease_default_bundler? - Gem.rubygems_version < Gem::Version.new("3.1.a") - end end diff --git a/spec/bundler/support/artifice/endpoint.rb b/spec/bundler/support/artifice/endpoint.rb index e0650fa7d5..37ca378ef9 100644 --- a/spec/bundler/support/artifice/endpoint.rb +++ b/spec/bundler/support/artifice/endpoint.rb @@ -45,10 +45,14 @@ class Endpoint < Sinatra::Base Pathname.new(ENV["BUNDLER_SPEC_GEM_REPO"]) else case request.host + when "gem.repo1" + Spec::Path.gem_repo1 when "gem.repo2" Spec::Path.gem_repo2 when "gem.repo3" Spec::Path.gem_repo3 + when "gem.repo4" + Spec::Path.gem_repo4 else Spec::Path.gem_repo1 end diff --git a/spec/bundler/support/helpers.rb b/spec/bundler/support/helpers.rb index 6fb0c6cb1c..2df41028fc 100644 --- a/spec/bundler/support/helpers.rb +++ b/spec/bundler/support/helpers.rb @@ -60,7 +60,7 @@ module Spec def run(cmd, *args) opts = args.last.is_a?(Hash) ? args.pop : {} groups = args.map(&:inspect).join(", ") - setup = "require '#{lib_dir}/bundler' ; Bundler.ui.silence { Bundler.setup(#{groups}) }" + setup = "require '#{entrypoint}' ; Bundler.ui.silence { Bundler.setup(#{groups}) }" ruby([setup, cmd].join(" ; "), opts) end @@ -468,9 +468,8 @@ module Spec ENV["BUNDLER_SPEC_WINDOWS"] = old end - # workaround for missing https://github.com/rubygems/rubygems/commit/929e92d752baad3a08f3ac92eaec162cb96aedd1 def simulate_bundler_version_when_missing_prerelease_default_gem_activation - return yield unless Gem.rubygems_version < Gem::Version.new("3.1.0.pre.1") + return yield unless rubygems_version_failing_to_activate_bundler_prereleases old = ENV["BUNDLER_VERSION"] ENV["BUNDLER_VERSION"] = Bundler::VERSION @@ -479,15 +478,20 @@ module Spec ENV["BUNDLER_VERSION"] = old end - # workaround for missing https://github.com/rubygems/rubygems/commit/929e92d752baad3a08f3ac92eaec162cb96aedd1 def env_for_missing_prerelease_default_gem_activation - if Gem.rubygems_version < Gem::Version.new("3.1.0.pre.1") + if rubygems_version_failing_to_activate_bundler_prereleases { "BUNDLER_VERSION" => Bundler::VERSION } else {} end end + # versions providing a bundler version finder but not including + # https://github.com/rubygems/rubygems/commit/929e92d752baad3a08f3ac92eaec162cb96aedd1 + def rubygems_version_failing_to_activate_bundler_prereleases + Gem.rubygems_version < Gem::Version.new("3.1.0.pre.1") && Gem.rubygems_version >= Gem::Version.new("2.7.0") + end + def revision_for(path) sys_exec("git rev-parse HEAD", :dir => path).strip end diff --git a/spec/bundler/support/indexes.rb b/spec/bundler/support/indexes.rb index 1f3c4ddaa6..bf4300edb2 100644 --- a/spec/bundler/support/indexes.rb +++ b/spec/bundler/support/indexes.rb @@ -20,12 +20,11 @@ module Spec default_source = instance_double("Bundler::Source::Rubygems", :specs => @index) source_requirements = { :default => default_source } @deps.each do |d| + source_requirements[d.name] = d.source = default_source @platforms.each do |p| - source_requirements[d.name] = d.source = default_source deps << Bundler::DepProxy.get_proxy(d, p) end end - source_requirements ||= {} args[0] ||= [] # base args[1] ||= Bundler::GemVersionPromoter.new # gem_version_promoter args[2] ||= [] # additional_base_requirements diff --git a/spec/bundler/support/matchers.rb b/spec/bundler/support/matchers.rb index 1613662981..3c1014edc7 100644 --- a/spec/bundler/support/matchers.rb +++ b/spec/bundler/support/matchers.rb @@ -156,7 +156,7 @@ module Spec actual_source = out.split("\n").last next "Expected #{name} (#{version}) to be installed from `#{source}`, was actually from `#{actual_source}`" end - next "Command to check forgem inclusion of gem #{full_name} failed" + next "Command to check for inclusion of gem #{full_name} failed" end.compact @errors.empty? diff --git a/spec/bundler/support/path.rb b/spec/bundler/support/path.rb index a9e9704cf9..000b3f87b8 100644 --- a/spec/bundler/support/path.rb +++ b/spec/bundler/support/path.rb @@ -213,6 +213,13 @@ module Spec root.join("lib") end + # Sometimes rubygems version under test does not include + # https://github.com/rubygems/rubygems/pull/2728 and will not always end up + # activating the current bundler. In that case, require bundler absolutely. + def entrypoint + Gem.rubygems_version < Gem::Version.new("3.1.a") ? "#{lib_dir}/bundler" : "bundler" + end + def global_plugin_gem(*args) home ".bundle", "plugin", "gems", *args end |