diff options
| author | David RodrÃguez <2887858+deivid-rodriguez@users.noreply.github.com> | 2025-09-09 19:18:42 +0200 |
|---|---|---|
| committer | Hiroshi SHIBATA <hsbt@ruby-lang.org> | 2025-09-16 17:17:32 +0900 |
| commit | 6adcc5596884619e386d5412e94ef4443868b94f (patch) | |
| tree | d5076faaa392104e0769c0256c3d0a971a489fa0 | |
| parent | 9878060181d2592c26dce0c314a8b4b6e4826646 (diff) | |
[rubygems/rubygems] Completely remove multisources support
https://github.com/rubygems/rubygems/commit/8f9d6c54a1
| -rw-r--r-- | lib/bundler/cli/install.rb | 16 | ||||
| -rw-r--r-- | lib/bundler/definition.rb | 16 | ||||
| -rw-r--r-- | lib/bundler/dsl.rb | 22 | ||||
| -rw-r--r-- | lib/bundler/errors.rb | 5 | ||||
| -rw-r--r-- | lib/bundler/index.rb | 7 | ||||
| -rw-r--r-- | lib/bundler/installer.rb | 6 | ||||
| -rw-r--r-- | lib/bundler/source/rubygems.rb | 13 | ||||
| -rw-r--r-- | lib/bundler/source_list.rb | 24 | ||||
| -rw-r--r-- | lib/bundler/source_map.rb | 7 | ||||
| -rw-r--r-- | spec/bundler/bundler/definition_spec.rb | 4 | ||||
| -rw-r--r-- | spec/bundler/commands/install_spec.rb | 18 | ||||
| -rw-r--r-- | spec/bundler/commands/outdated_spec.rb | 66 | ||||
| -rw-r--r-- | spec/bundler/commands/update_spec.rb | 62 | ||||
| -rw-r--r-- | spec/bundler/install/gemfile/sources_spec.rb | 908 | ||||
| -rw-r--r-- | spec/bundler/install/gems/compact_index_spec.rb | 73 | ||||
| -rw-r--r-- | spec/bundler/install/gems/dependency_api_spec.rb | 92 | ||||
| -rw-r--r-- | spec/bundler/other/major_deprecation_spec.rb | 67 |
17 files changed, 73 insertions, 1333 deletions
diff --git a/lib/bundler/cli/install.rb b/lib/bundler/cli/install.rb index a676e2d6f1..c4063f808a 100644 --- a/lib/bundler/cli/install.rb +++ b/lib/bundler/cli/install.rb @@ -69,8 +69,6 @@ module Bundler Bundler::CLI::Common.output_post_install_messages installer.post_install_messages - warn_ambiguous_gems - if CLI::Common.clean_after_install? require_relative "clean" Bundler::CLI::Clean.new(options).run @@ -126,19 +124,5 @@ module Bundler options[:force] = options[:redownload] if options[:redownload] end - - def warn_ambiguous_gems - # TODO: remove this when we drop Bundler 1.x support - Installer.ambiguous_gems.to_a.each do |name, installed_from_uri, *also_found_in_uris| - Bundler.ui.warn "Warning: the gem '#{name}' was found in multiple sources." - Bundler.ui.warn "Installed from: #{installed_from_uri}" - Bundler.ui.warn "Also found in:" - also_found_in_uris.each {|uri| Bundler.ui.warn " * #{uri}" } - Bundler.ui.warn "You should add a source requirement to restrict this gem to your preferred source." - Bundler.ui.warn "For example:" - Bundler.ui.warn " gem '#{name}', :source => '#{installed_from_uri}'" - Bundler.ui.warn "Then uninstall the gem '#{name}' (or delete all bundled gems) and then install again." - end - end end end diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index ab488e046b..32dd13399e 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -119,16 +119,12 @@ module Bundler end locked_gem_sources = @originally_locked_sources.select {|s| s.is_a?(Source::Rubygems) } - @multisource_lockfile = locked_gem_sources.size == 1 && locked_gem_sources.first.multiple_remotes? + multisource_lockfile = locked_gem_sources.size == 1 && locked_gem_sources.first.multiple_remotes? - if @multisource_lockfile && Bundler.frozen_bundle? - unless sources.aggregate_global_source? - msg = "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." + if multisource_lockfile + msg = "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." - Bundler::SharedHelpers.major_deprecation 2, msg - end - - @sources.merged_gem_lockfile_sections!(locked_gem_sources.first) + Bundler::SharedHelpers.feature_removed! msg end else @locked_gems = nil @@ -765,7 +761,7 @@ module Bundler end def precompute_source_requirements_for_indirect_dependencies? - sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && !sources.aggregate_global_source? + sources.non_global_rubygems_sources.all?(&:dependency_api_available?) end def current_platform_locked? @@ -1139,7 +1135,7 @@ module Bundler end def additional_base_requirements_to_prevent_downgrades(resolution_base) - return resolution_base unless @locked_gems && !@multisource_lockfile + return resolution_base unless @locked_gems @originally_locked_specs.each do |locked_spec| next if locked_spec.source.is_a?(Source::Path) || locked_spec.source_changed? diff --git a/lib/bundler/dsl.rb b/lib/bundler/dsl.rb index 0e36f52269..3bf5dbc115 100644 --- a/lib/bundler/dsl.rb +++ b/lib/bundler/dsl.rb @@ -521,24 +521,10 @@ module Bundler end def multiple_global_source_warning - if Bundler.feature_flag.bundler_4_mode? - msg = "This Gemfile contains multiple global sources. " \ - "Each source after the first must include a block to indicate which gems " \ - "should come from that source" - raise GemfileEvalError, msg - else - message = - "Your Gemfile contains multiple global 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." - removed_message = - "Your Gemfile contains multiple global sources. " \ - "Using `source` more than once without a block is a security risk, and " \ - "may result in installing unexpected gems. To resolve this error, use " \ - "a block to indicate which gems should come from the secondary source." - Bundler::SharedHelpers.major_deprecation 2, message, removed_message: removed_message - end + msg = "This Gemfile contains multiple global sources. " \ + "Each source after the first must include a block to indicate which gems " \ + "should come from that source" + raise GemfileEvalError, msg end class DSLError < GemfileError diff --git a/lib/bundler/errors.rb b/lib/bundler/errors.rb index 28da892d31..8cd1336356 100644 --- a/lib/bundler/errors.rb +++ b/lib/bundler/errors.rb @@ -77,11 +77,6 @@ module Bundler def mismatch_resolution_instructions removable, remote = [@existing, @checksum].partition(&:removable?) case removable.size - when 0 - msg = +"Mismatched checksums each have an authoritative source:\n" - msg << " 1. #{@existing.sources.reject(&:removable?).map(&:to_s).join(" and ")}\n" - msg << " 2. #{@checksum.sources.reject(&:removable?).map(&:to_s).join(" and ")}\n" - msg << "You may need to alter your Gemfile sources to resolve this issue.\n" when 1 msg = +"If you trust #{remote.first.sources.first}, to resolve this issue you can:\n" msg << removable.first.removal_instructions diff --git a/lib/bundler/index.rb b/lib/bundler/index.rb index d591b34cc7..9aef2dfa12 100644 --- a/lib/bundler/index.rb +++ b/lib/bundler/index.rb @@ -46,13 +46,6 @@ module Bundler true end - def search_all(name, &blk) - return enum_for(:search_all, name) unless blk - specs_by_name(name).each(&blk) - @duplicates[name]&.each(&blk) - @sources.each {|source| source.search_all(name, &blk) } - end - # Search this index's specs, and any source indexes that this index knows # about, returning all of the results. def search(query) diff --git a/lib/bundler/installer.rb b/lib/bundler/installer.rb index d41740a411..c5fd75431f 100644 --- a/lib/bundler/installer.rb +++ b/lib/bundler/installer.rb @@ -7,12 +7,6 @@ require_relative "installer/gem_installer" module Bundler class Installer - class << self - attr_accessor :ambiguous_gems - - Installer.ambiguous_gems = [] - end - attr_reader :post_install_messages, :definition # Begins the installation process for Bundler. diff --git a/lib/bundler/source/rubygems.rb b/lib/bundler/source/rubygems.rb index 19800e9c58..fdc3a77b24 100644 --- a/lib/bundler/source/rubygems.rb +++ b/lib/bundler/source/rubygems.rb @@ -168,12 +168,6 @@ module Bundler return nil # no post-install message end - if spec.remote - # Check for this spec from other sources - uris = [spec.remote, *remotes_for_spec(spec)].map(&:anonymized_uri).uniq - Installer.ambiguous_gems << [spec.name, *uris] if uris.length > 1 - end - path = fetch_gem_if_possible(spec, options[:previous_spec]) raise GemNotFound, "Could not find #{spec.file_name} for installation" unless path @@ -332,13 +326,6 @@ module Bundler remotes.map(&method(:remove_auth)) end - def remotes_for_spec(spec) - specs.search_all(spec.name).inject([]) do |uris, s| - uris << s.remote if s.remote - uris - end - end - def cached_gem(spec) global_cache_path = download_cache_path(spec) caches << global_cache_path if global_cache_path diff --git a/lib/bundler/source_list.rb b/lib/bundler/source_list.rb index 70b74f6a91..6dba3f35e8 100644 --- a/lib/bundler/source_list.rb +++ b/lib/bundler/source_list.rb @@ -21,19 +21,9 @@ module Bundler @rubygems_sources = [] @metadata_source = Source::Metadata.new - @merged_gem_lockfile_sections = false @local_mode = true end - def merged_gem_lockfile_sections? - @merged_gem_lockfile_sections - end - - def merged_gem_lockfile_sections!(replacement_source) - @merged_gem_lockfile_sections = true - @global_rubygems_source = replacement_source - end - def aggregate_global_source? global_rubygems_source.multiple_remotes? end @@ -90,10 +80,6 @@ module Bundler @rubygems_sources end - def rubygems_remotes - rubygems_sources.flat_map(&:remotes).uniq - end - def all_sources path_sources + git_sources + plugin_sources + rubygems_sources + [metadata_source] end @@ -115,11 +101,7 @@ module Bundler end def lock_rubygems_sources - if merged_gem_lockfile_sections? - [combine_rubygems_sources] - else - rubygems_sources.sort_by(&:identifier) - end + rubygems_sources.sort_by(&:identifier) end # Returns true if there are changes @@ -228,10 +210,6 @@ module Bundler end end - def combine_rubygems_sources - Source::Rubygems.new("remotes" => rubygems_remotes) - end - def warn_on_git_protocol(source) return if Bundler.settings["git.allow_insecure"] diff --git a/lib/bundler/source_map.rb b/lib/bundler/source_map.rb index a8e12d08c3..cb88caf1bd 100644 --- a/lib/bundler/source_map.rb +++ b/lib/bundler/source_map.rb @@ -23,15 +23,12 @@ module Bundler if previous_source.nil? requirements[indirect_dependency_name] = source else - no_ambiguous_sources = Bundler.feature_flag.bundler_4_mode? - msg = ["The gem '#{indirect_dependency_name}' was found in multiple relevant sources."] msg.concat [previous_source, source].map {|s| " * #{s}" }.sort - msg << "You #{no_ambiguous_sources ? :must : :should} add this gem to the source block for the source you wish it to be installed from." + msg << "You must add this gem to the source block for the source you wish it to be installed from." msg = msg.join("\n") - raise SecurityError, msg if no_ambiguous_sources - Bundler.ui.warn "Warning: #{msg}" + raise SecurityError, msg end end diff --git a/spec/bundler/bundler/definition_spec.rb b/spec/bundler/bundler/definition_spec.rb index 8f796877fd..67fc51e86a 100644 --- a/spec/bundler/bundler/definition_spec.rb +++ b/spec/bundler/bundler/definition_spec.rb @@ -299,10 +299,6 @@ RSpec.describe Bundler::Definition do [] end - def rubygems_remotes - [] - end - def replace_sources!(arg) nil end diff --git a/spec/bundler/commands/install_spec.rb b/spec/bundler/commands/install_spec.rb index ae2e84766a..65903b3e78 100644 --- a/spec/bundler/commands/install_spec.rb +++ b/spec/bundler/commands/install_spec.rb @@ -342,24 +342,6 @@ RSpec.describe "bundle install with gem sources" do end end - it "finds gems in multiple sources" do - build_repo2 do - build_gem "myrack", "1.2" do |s| - s.executables = "myrackup" - end - end - - install_gemfile <<-G, artifice: "compact_index_extra" - source "https://gemserver.test" - source "https://gemserver.test/extra" - - gem "activesupport", "1.2.3" - gem "myrack", "1.2" - G - - expect(the_bundle).to include_gems "myrack 1.2", "activesupport 1.2.3" - end - it "gives useful errors if no global sources are set, and gems not installed locally, with and without a lockfile" do install_gemfile <<-G, raise_on_error: false gem "myrack" diff --git a/spec/bundler/commands/outdated_spec.rb b/spec/bundler/commands/outdated_spec.rb index c7d285cd36..3eeac7f624 100644 --- a/spec/bundler/commands/outdated_spec.rb +++ b/spec/bundler/commands/outdated_spec.rb @@ -151,72 +151,6 @@ RSpec.describe "bundle outdated" do end end - describe "with multiple, duplicated sources, with lockfile in old format" do - before do - build_repo2 do - build_gem "dotenv", "2.7.6" - - build_gem "oj", "3.11.3" - build_gem "oj", "3.11.5" - - build_gem "vcr", "6.0.0" - end - - build_repo3 do - build_gem "pkg-gem-flowbyte-with-dep", "1.0.0" do |s| - s.add_dependency "oj" - end - end - - gemfile <<~G - source "https://gem.repo2" - - gem "dotenv" - - source "https://gem.repo3" do - gem 'pkg-gem-flowbyte-with-dep' - end - - gem "vcr",source: "https://gem.repo2" - G - - lockfile <<~L - GEM - remote: https://gem.repo2/ - remote: https://gem.repo3/ - specs: - dotenv (2.7.6) - oj (3.11.3) - pkg-gem-flowbyte-with-dep (1.0.0) - oj - vcr (6.0.0) - - PLATFORMS - #{local_platform} - - DEPENDENCIES - dotenv - pkg-gem-flowbyte-with-dep! - vcr! - - BUNDLED WITH - #{Bundler::VERSION} - L - end - - it "works" do - bundle :install, artifice: "compact_index" - bundle :outdated, artifice: "compact_index", raise_on_error: false - - expected_output = <<~TABLE - Gem Current Latest Requested Groups - oj 3.11.3 3.11.5 - TABLE - - expect(out).to include(expected_output.strip) - end - end - describe "with --group option" do before do build_repo2 do diff --git a/spec/bundler/commands/update_spec.rb b/spec/bundler/commands/update_spec.rb index ef856edf37..f81c557884 100644 --- a/spec/bundler/commands/update_spec.rb +++ b/spec/bundler/commands/update_spec.rb @@ -1078,68 +1078,6 @@ RSpec.describe "bundle update" do L end end - - context "with multiple, duplicated sources, with lockfile in old format" do - before do - build_repo2 do - build_gem "dotenv", "2.7.6" - - build_gem "oj", "3.11.3" - build_gem "oj", "3.11.5" - - build_gem "vcr", "6.0.0" - end - - build_repo3 do - build_gem "pkg-gem-flowbyte-with-dep", "1.0.0" do |s| - s.add_dependency "oj" - end - end - - gemfile <<~G - source "https://gem.repo2" - - gem "dotenv" - - source "https://gem.repo3" do - gem 'pkg-gem-flowbyte-with-dep' - end - - gem "vcr",source: "https://gem.repo2" - G - - lockfile <<~L - GEM - remote: https://gem.repo2/ - remote: https://gem.repo3/ - specs: - dotenv (2.7.6) - oj (3.11.3) - pkg-gem-flowbyte-with-dep (1.0.0) - oj - vcr (6.0.0) - - PLATFORMS - #{local_platform} - - DEPENDENCIES - dotenv - pkg-gem-flowbyte-with-dep! - vcr! - - BUNDLED WITH - #{Bundler::VERSION} - L - end - - it "works" do - 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" - end - end end RSpec.describe "bundle update in more complicated situations" do diff --git a/spec/bundler/install/gemfile/sources_spec.rb b/spec/bundler/install/gemfile/sources_spec.rb index 406d881541..c2a0905d21 100644 --- a/spec/bundler/install/gemfile/sources_spec.rb +++ b/spec/bundler/install/gemfile/sources_spec.rb @@ -4,153 +4,6 @@ RSpec.describe "bundle install with gems on multiple sources" do # repo1 is built automatically before all of the specs run # it contains myrack-obama 1.0.0 and myrack 0.9.1 & 1.0.0 amongst other gems - context "without source affinity" do - before do - # Oh no! Someone evil is trying to hijack myrack :( - # need this to be broken to check for correct source ordering - build_repo3 do - build_gem "myrack", repo3_myrack_version do |s| - s.write "lib/myrack.rb", "MYRACK = 'FAIL'" - end - end - end - - context "with multiple toplevel sources" do - let(:repo3_myrack_version) { "1.0.0" } - - before do - gemfile <<-G - source "https://gem.repo3" - source "https://gem.repo1" - gem "myrack-obama" - gem "myrack" - G - end - - it "refuses to install mismatched checksum because one gem has been tampered with" do - lockfile <<~L - GEM - remote: https://gem.repo3/ - remote: https://gem.repo1/ - specs: - myrack (1.0.0) - - PLATFORMS - #{local_platform} - - DEPENDENCIES - depends_on_myrack! - - BUNDLED WITH - #{Bundler::VERSION} - L - - bundle :install, artifice: "compact_index", raise_on_error: false - - expect(exitstatus).to eq(37) - expect(err).to eq <<~E.strip - [DEPRECATED] Your Gemfile contains multiple global 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. - Bundler found mismatched checksums. This is a potential security risk. - #{checksum_to_lock(gem_repo1, "myrack", "1.0.0")} - from the API at https://gem.repo1/ - #{checksum_to_lock(gem_repo3, "myrack", "1.0.0")} - from the API at https://gem.repo3/ - - Mismatched checksums each have an authoritative source: - 1. the API at https://gem.repo1/ - 2. the API at https://gem.repo3/ - You may need to alter your Gemfile sources to resolve this issue. - - To ignore checksum security warnings, disable checksum validation with - `bundle config set --local disable_checksum_validation true` - E - end - - context "when checksum validation is disabled" do - before do - bundle "config set --local disable_checksum_validation true" - end - - it "warns about ambiguous gems, but installs anyway, prioritizing sources last to first" do - bundle :install, artifice: "compact_index" - - expect(err).to include("Warning: the gem 'myrack' was found in multiple sources.") - expect(err).to include("Installed from: https://gem.repo1") - expect(the_bundle).to include_gems("myrack-obama 1.0.0", "myrack 1.0.0", source: "remote1") - end - - it "does not use the full index unnecessarily" do - bundle :install, artifice: "compact_index", verbose: true - - expect(out).to include("https://gem.repo1/versions") - expect(out).to include("https://gem.repo3/versions") - expect(out).not_to include("https://gem.repo1/quick/Marshal.4.8/") - expect(out).not_to include("https://gem.repo3/quick/Marshal.4.8/") - end - - it "fails", bundler: "4" do - 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 - end - end - - context "when different versions of the same gem are in multiple sources" do - let(:repo3_myrack_version) { "1.2" } - - before do - gemfile <<-G - source "https://gem.repo3" - source "https://gem.repo1" - gem "myrack-obama" - gem "myrack", "1.0.0" # force it to install the working version in repo1 - G - end - - it "warns about ambiguous gems, but installs anyway" do - bundle :install, artifice: "compact_index" - expect(err).to include("Warning: the gem 'myrack' was found in multiple sources.") - expect(err).to include("Installed from: https://gem.repo1") - expect(the_bundle).to include_gems("myrack-obama 1.0.0", "myrack 1.0.0", source: "remote1") - end - - it "fails", bundler: "4" do - 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 - end - end - - context "without source affinity, and a stdlib gem present in one of the sources", :ruby_repo do - let(:default_json_version) { ruby "gem 'json'; require 'json'; puts JSON::VERSION" } - - before do - build_repo2 do - build_gem "json", default_json_version - end - - build_repo4 do - build_gem "foo" do |s| - s.add_dependency "json", default_json_version - end - end - - gemfile <<-G - source "https://gem.repo2" - source "https://gem.repo4" - - gem "foo" - G - end - - it "works in standalone mode" do - gem_checksum = checksum_digest(gem_repo4, "foo", "1.0") - bundle "install --standalone", artifice: "compact_index", env: { "BUNDLER_SPEC_FOO_CHECKSUM" => gem_checksum } - end - end - context "with source affinity" do context "with sources given by a block" do before do @@ -313,189 +166,6 @@ RSpec.describe "bundle install with gems on multiple sources" do expect(the_bundle).to include_gems("depends_on_myrack 1.0.1", "myrack 1.0.0") end end - - context "and in yet another source" do - before do - gemfile <<-G - source "https://gem.repo1" - source "https://gem.repo2" - source "https://gem.repo3" do - gem "depends_on_myrack" - end - G - end - - it "fails when the two sources don't have the same checksum" do - bundle :install, artifice: "compact_index", raise_on_error: false - - expect(err).to eq(<<~E.strip) - [DEPRECATED] Your Gemfile contains multiple global 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. - Bundler found mismatched checksums. This is a potential security risk. - #{checksum_to_lock(gem_repo2, "myrack", "1.0.0")} - from the API at https://gem.repo2/ - #{checksum_to_lock(gem_repo1, "myrack", "1.0.0")} - from the API at https://gem.repo1/ - - Mismatched checksums each have an authoritative source: - 1. the API at https://gem.repo2/ - 2. the API at https://gem.repo1/ - You may need to alter your Gemfile sources to resolve this issue. - - To ignore checksum security warnings, disable checksum validation with - `bundle config set --local disable_checksum_validation true` - E - expect(exitstatus).to eq(37) - end - - it "fails when the two sources agree, but the local gem calculates a different checksum" do - myrack_checksum = "c0ffee11" * 8 - bundle :install, artifice: "compact_index", env: { "BUNDLER_SPEC_MYRACK_CHECKSUM" => myrack_checksum }, raise_on_error: false - - expect(err).to eq(<<~E.strip) - [DEPRECATED] Your Gemfile contains multiple global 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. - Bundler found mismatched checksums. This is a potential security risk. - myrack (1.0.0) sha256=#{myrack_checksum} - from the API at https://gem.repo2/ - and the API at https://gem.repo1/ - #{checksum_to_lock(gem_repo2, "myrack", "1.0.0")} - from the gem at #{default_bundle_path("cache", "myrack-1.0.0.gem")} - - If you trust the API at https://gem.repo2/, to resolve this issue you can: - 1. remove the gem at #{default_bundle_path("cache", "myrack-1.0.0.gem")} - 2. run `bundle install` - - To ignore checksum security warnings, disable checksum validation with - `bundle config set --local disable_checksum_validation true` - E - expect(exitstatus).to eq(37) - end - - it "installs from the other source and warns about ambiguous gems when the sources have the same checksum" do - gem_checksum = checksum_digest(gem_repo2, "myrack", "1.0.0") - bundle :install, artifice: "compact_index", env: { "BUNDLER_SPEC_MYRACK_CHECKSUM" => gem_checksum, "DEBUG" => "1" } - - expect(err).to include("Warning: the gem 'myrack' was found in multiple sources.") - expect(err).to include("Installed from: https://gem.repo2") - - checksums = checksums_section_when_enabled do |c| - c.checksum gem_repo3, "depends_on_myrack", "1.0.1" - c.checksum gem_repo2, "myrack", "1.0.0" - end - - expect(lockfile).to eq <<~L - GEM - remote: https://gem.repo1/ - remote: https://gem.repo2/ - specs: - myrack (1.0.0) - - GEM - remote: https://gem.repo3/ - specs: - depends_on_myrack (1.0.1) - myrack - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - depends_on_myrack! - #{checksums} - BUNDLED WITH - #{Bundler::VERSION} - L - - previous_lockfile = lockfile - expect(the_bundle).to include_gems("depends_on_myrack 1.0.1", "myrack 1.0.0") - expect(lockfile).to eq(previous_lockfile) - end - - it "installs from the other source and warns about ambiguous gems when checksum validation is disabled" do - bundle "config set --local disable_checksum_validation true" - bundle :install, artifice: "compact_index" - - expect(err).to include("Warning: the gem 'myrack' was found in multiple sources.") - expect(err).to include("Installed from: https://gem.repo2") - - checksums = checksums_section_when_enabled do |c| - c.no_checksum "depends_on_myrack", "1.0.1" - c.no_checksum "myrack", "1.0.0" - end - - expect(lockfile).to eq <<~L - GEM - remote: https://gem.repo1/ - remote: https://gem.repo2/ - specs: - myrack (1.0.0) - - GEM - remote: https://gem.repo3/ - specs: - depends_on_myrack (1.0.1) - myrack - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - depends_on_myrack! - #{checksums} - BUNDLED WITH - #{Bundler::VERSION} - L - - previous_lockfile = lockfile - expect(the_bundle).to include_gems("depends_on_myrack 1.0.1", "myrack 1.0.0") - expect(lockfile).to eq(previous_lockfile) - end - - it "fails", bundler: "4" do - 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 - end - - context "and only the dependency is pinned" do - before do - # need this to be broken to check for correct source ordering - build_repo gem_repo2 do - build_gem "myrack", "1.0.0" do |s| - s.write "lib/myrack.rb", "MYRACK = 'FAIL'" - end - end - - gemfile <<-G - source "https://gem.repo3" # contains depends_on_myrack - source "https://gem.repo2" # contains broken myrack - - gem "depends_on_myrack" # installed from gem_repo3 - gem "myrack", :source => "https://gem.repo1" - G - end - - it "installs the dependency from the pinned source without warning" do - bundle :install, artifice: "compact_index" - - expect(err).not_to include("Warning: the gem 'myrack' was found in multiple sources.") - expect(the_bundle).to include_gems("depends_on_myrack 1.0.1", "myrack 1.0.0") - - # In https://github.com/rubygems/bundler/issues/3585 this failed - # when there is already a lockfile, and the gems are missing, so try again - system_gems [] - bundle :install, artifice: "compact_index" - - expect(err).not_to include("Warning: the gem 'myrack' was found in multiple sources.") - expect(the_bundle).to include_gems("depends_on_myrack 1.0.1", "myrack 1.0.0") - end - - it "fails", bundler: "4" do - 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 - end end context "when a top-level gem can only be found in an scoped source" do @@ -524,39 +194,6 @@ RSpec.describe "bundle install with gems on multiple sources" do end end - context "when an indirect dependency can't be found in the aggregate rubygems source" do - before do - build_repo2 - - build_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 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, - depends_on_missing cannot be used. - So, because Gemfile depends on depends_on_missing >= 0, - version solving has failed. - E - end - end - context "when a top-level gem has an indirect dependency" do before do build_repo gem_repo2 do @@ -714,337 +351,6 @@ RSpec.describe "bundle install with gems on multiple sources" do end end - 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 "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 "concurrent-ruby", "1.1.8" - build_gem "concurrent-ruby", "1.1.9" - build_gem "connection_pool", "2.2.3" - - build_gem "i18n", "1.8.9" do |s| - s.add_dependency "concurrent-ruby", "~> 1.0" - end - - build_gem "minitest", "5.14.3" - build_gem "myrack", "2.2.3" - build_gem "redis", "4.2.5" - - build_gem "sidekiq", "6.1.3" do |s| - s.add_dependency "connection_pool", ">= 2.2.2" - s.add_dependency "myrack", "~> 2.0" - s.add_dependency "redis", ">= 4.2.0" - end - - build_gem "thread_safe", "0.3.6" - - build_gem "tzinfo", "1.2.9" do |s| - s.add_dependency "thread_safe", "~> 0.1" - end - - build_gem "tzinfo", "2.0.4" do |s| - s.add_dependency "concurrent-ruby", "~> 1.0" - end - - build_gem "zeitwerk", "2.4.2" - end - - build_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 - - gemfile <<-G - # frozen_string_literal: true - - source "https://gem.repo2" - - gem "activesupport" - - source "https://gem.repo3" do - gem "sidekiq-pro" - end - G - - @locked_checksums = checksums_section_when_enabled do |c| - c.checksum gem_repo2, "activesupport", "6.0.3.4" - c.checksum gem_repo2, "concurrent-ruby", "1.1.8" - c.checksum gem_repo2, "connection_pool", "2.2.3" - c.checksum gem_repo2, "i18n", "1.8.9" - c.checksum gem_repo2, "minitest", "5.14.3" - c.checksum gem_repo2, "myrack", "2.2.3" - c.checksum gem_repo2, "redis", "4.2.5" - c.checksum gem_repo2, "sidekiq", "6.1.3" - c.checksum gem_repo3, "sidekiq-pro", "5.2.1" - c.checksum gem_repo2, "thread_safe", "0.3.6" - c.checksum gem_repo2, "tzinfo", "1.2.9" - c.checksum gem_repo2, "zeitwerk", "2.4.2" - end - - 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) - myrack (2.2.3) - redis (4.2.5) - sidekiq (6.1.3) - connection_pool (>= 2.2.2) - myrack (~> 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) - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - activesupport - sidekiq-pro! - #{@locked_checksums} - BUNDLED WITH - #{Bundler::VERSION} - L - end - - 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(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) - myrack (2.2.3) - redis (4.2.5) - sidekiq (6.1.3) - connection_pool (>= 2.2.2) - myrack (~> 2.0) - redis (>= 4.2.0) - thread_safe (0.3.6) - tzinfo (1.2.9) - thread_safe (~> 0.1) - zeitwerk (2.4.2) - - GEM - remote: https://gem.repo3/ - specs: - sidekiq-pro (5.2.1) - connection_pool (>= 2.2.3) - sidekiq (>= 6.1.0) - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - activesupport - sidekiq-pro! - #{@locked_checksums} - BUNDLED WITH - #{Bundler::VERSION} - L - end - - it "does not install newer versions or generate lockfile changes when running bundle install in frozen mode, and warns" do - initial_lockfile = lockfile - - bundle "config set --local frozen true" - bundle :install, artifice: "compact_index" - - 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.8") - expect(the_bundle).not_to include_gems("concurrent-ruby 1.1.9") - - expect(lockfile).to eq(initial_lockfile) - end - - it "fails when running bundle install in frozen mode", bundler: "4" do - initial_lockfile = lockfile - - bundle "config set --local frozen true" - bundle :install, artifice: "compact_index", raise_on_error: false - - expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.") - - expect(lockfile).to eq(initial_lockfile) - end - - 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 - - expect(the_bundle).not_to include_gems("activesupport 6.0.3.4") - expect(the_bundle).to include_gems("activesupport 6.1.2.1") - @locked_checksums.checksum gem_repo2, "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") - @locked_checksums.checksum gem_repo2, "tzinfo", "2.0.4" - @locked_checksums.delete "thread_safe" - - expect(the_bundle).not_to include_gems("concurrent-ruby 1.1.8") - expect(the_bundle).to include_gems("concurrent-ruby 1.1.9") - @locked_checksums.checksum gem_repo2, "concurrent-ruby", "1.1.9" - - 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) - myrack (2.2.3) - redis (4.2.5) - sidekiq (6.1.3) - connection_pool (>= 2.2.2) - myrack (~> 2.0) - redis (>= 4.2.0) - tzinfo (2.0.4) - concurrent-ruby (~> 1.0) - zeitwerk (2.4.2) - - GEM - remote: https://gem.repo3/ - specs: - sidekiq-pro (5.2.1) - connection_pool (>= 2.2.3) - sidekiq (>= 6.1.0) - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - activesupport - sidekiq-pro! - #{@locked_checksums} - BUNDLED WITH - #{Bundler::VERSION} - L - end - - 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 - - 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") - - @locked_checksums.checksum gem_repo2, "concurrent-ruby", "1.1.9" - - 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) - myrack (2.2.3) - redis (4.2.5) - sidekiq (6.1.3) - connection_pool (>= 2.2.2) - myrack (~> 2.0) - redis (>= 4.2.0) - thread_safe (0.3.6) - tzinfo (1.2.9) - thread_safe (~> 0.1) - zeitwerk (2.4.2) - - GEM - remote: https://gem.repo3/ - specs: - sidekiq-pro (5.2.1) - connection_pool (>= 2.2.3) - sidekiq (>= 6.1.0) - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - activesupport - sidekiq-pro! - #{@locked_checksums} - 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" do before do build_lib "activesupport", "7.0.0.alpha", path: lib_path("rails/activesupport") @@ -1207,112 +513,6 @@ RSpec.describe "bundle install with gems on multiple sources" do end end - context "with a lockfile with aggregated rubygems sources" do - let(:aggregate_gem_section_lockfile) do - <<~L - GEM - remote: https://gem.repo1/ - remote: https://gem.repo3/ - specs: - myrack (0.9.1) - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - myrack! - - BUNDLED WITH - #{Bundler::VERSION} - L - end - - let(:split_gem_section_lockfile) do - <<~L - GEM - remote: https://gem.repo1/ - specs: - - GEM - remote: https://gem.repo3/ - specs: - myrack (0.9.1) - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - myrack! - - BUNDLED WITH - #{Bundler::VERSION} - L - end - - before do - build_repo3 do - build_gem "myrack", "0.9.1" - end - - gemfile <<-G - source "https://gem.repo1" - source "https://gem.repo3" do - gem 'myrack' - end - G - - lockfile aggregate_gem_section_lockfile - end - - it "installs the existing lockfile but prints a warning when checksum validation is disabled" do - bundle "config set --local deployment true" - bundle "config set --local disable_checksum_validation true" - - 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.") - expect(the_bundle).to include_gems("myrack 0.9.1", source: "remote3") - end - - it "prints a checksum warning when the checksums from both sources do not match" do - bundle "config set --local deployment true" - - bundle "install", artifice: "compact_index", raise_on_error: false - - api_checksum1 = checksum_digest(gem_repo1, "myrack", "0.9.1") - api_checksum3 = checksum_digest(gem_repo3, "myrack", "0.9.1") - - expect(exitstatus).to eq(37) - expect(err).to eq(<<~E.strip) - [DEPRECATED] 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. - Bundler found mismatched checksums. This is a potential security risk. - myrack (0.9.1) sha256=#{api_checksum3} - from the API at https://gem.repo3/ - myrack (0.9.1) sha256=#{api_checksum1} - from the API at https://gem.repo1/ - - Mismatched checksums each have an authoritative source: - 1. the API at https://gem.repo3/ - 2. the API at https://gem.repo1/ - You may need to alter your Gemfile sources to resolve this issue. - - To ignore checksum security warnings, disable checksum validation with - `bundle config set --local disable_checksum_validation true` - E - end - - it "refuses to install the existing lockfile and prints an error", bundler: "4" do - bundle "config set --local deployment true" - - 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.") - expect(out).to be_empty - end - end - context "with a path gem in the same Gemfile" do before do build_lib "foo" @@ -1584,37 +784,6 @@ RSpec.describe "bundle install with gems on multiple sources" do end context "when an indirect dependency is available from multiple ambiguous sources" do - it "succeeds but warns, suggesting a source block" do - build_repo4 do - build_gem "depends_on_myrack" do |s| - s.add_dependency "myrack" - end - build_gem "myrack" - end - - install_gemfile <<-G, artifice: "compact_index_extra_api", raise_on_error: false - source "https://global.source" - - source "https://scoped.source/extra" do - gem "depends_on_myrack" - end - - source "https://scoped.source" do - gem "thin" - end - G - expect(err).to eq <<~EOS.strip - Warning: The gem 'myrack' was found in multiple relevant sources. - * rubygems repository https://scoped.source/ - * rubygems repository https://scoped.source/extra/ - 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: "4" do it "raises, suggesting a source block" do build_repo4 do build_gem "depends_on_myrack" do |s| @@ -1645,83 +814,6 @@ RSpec.describe "bundle install with gems on multiple sources" do end end - context "when upgrading a lockfile suffering from dependency confusion" do - before do - build_repo4 do - build_gem "mime-types", "3.0.0" - end - - build_repo2 do - build_gem "capybara", "2.5.0" do |s| - s.add_dependency "mime-types", ">= 1.16" - end - - build_gem "mime-types", "3.3.1" - end - - gemfile <<~G - source "https://gem.repo2" - - gem "capybara", "~> 2.5.0" - - source "https://gem.repo4" do - gem "mime-types", "~> 3.0" - end - G - - lockfile <<-L - GEM - remote: https://gem.repo2/ - remote: https://gem.repo4/ - specs: - capybara (2.5.0) - mime-types (>= 1.16) - mime-types (3.3.1) - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - capybara (~> 2.5.0) - mime-types (~> 3.0)! - - CHECKSUMS - L - end - - it "upgrades the lockfile correctly" do - bundle "lock --update", artifice: "compact_index" - - checksums = checksums_section_when_enabled do |c| - c.checksum gem_repo2, "capybara", "2.5.0" - c.checksum gem_repo4, "mime-types", "3.0.0" - end - - expect(lockfile).to eq <<~L - GEM - remote: https://gem.repo2/ - specs: - capybara (2.5.0) - mime-types (>= 1.16) - - GEM - remote: https://gem.repo4/ - specs: - mime-types (3.0.0) - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - capybara (~> 2.5.0) - mime-types (~> 3.0)! - #{checksums} - BUNDLED WITH - #{Bundler::VERSION} - L - end - end - context "when default source includes old gems with nil required_ruby_version" do before do build_repo2 do diff --git a/spec/bundler/install/gems/compact_index_spec.rb b/spec/bundler/install/gems/compact_index_spec.rb index 3e4b18a188..64c59d4826 100644 --- a/spec/bundler/install/gems/compact_index_spec.rb +++ b/spec/bundler/install/gems/compact_index_spec.rb @@ -324,24 +324,6 @@ RSpec.describe "compact index api" do FileUtils.rm_r Dir[gem_repo2("gems/foo-*.gem")] end - gemfile <<-G - source "#{source_uri}" - source "#{source_uri}/extra" - gem "back_deps" - G - - bundle :install, artifice: "compact_index_extra" - expect(the_bundle).to include_gems "back_deps 1.0", "foo 1.0" - end - - it "fetches again when more dependencies are found in subsequent sources with source blocks" do - build_repo2 do - build_gem "back_deps" do |s| - s.add_dependency "foo" - end - FileUtils.rm_r Dir[gem_repo2("gems/foo-*.gem")] - end - install_gemfile <<-G, artifice: "compact_index_extra", verbose: true source "#{source_uri}" source "#{source_uri}/extra" do @@ -375,11 +357,13 @@ RSpec.describe "compact index api" do expect(the_bundle).to include_gems "myrack 1.2" end - it "considers all possible versions of dependencies from all api gem sources" 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. + it "resolves indirect dependencies to the most scoped source that includes them" 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 tries to + # use the version in the most scoped source, even if not compatible, and + # gives a resolution error build_repo4 do build_gem "activesupport", "1.2.0" build_gem "somegem", "1.0.0" do |s| @@ -389,14 +373,14 @@ RSpec.describe "compact index api" do gemfile <<-G source "#{source_uri}" - source "#{source_uri}/extra" - gem 'somegem', '1.0.0' + source "#{source_uri}/extra" do + gem 'somegem', '1.0.0' + end G - bundle :install, artifice: "compact_index_extra_api" + bundle :install, artifice: "compact_index_extra_api", raise_on_error: false - expect(the_bundle).to include_gems "somegem 1.0.0" - expect(the_bundle).to include_gems "activesupport 1.2.3" + expect(err).to include("Could not find compatible versions") end it "prints API output properly with back deps" do @@ -481,26 +465,6 @@ RSpec.describe "compact index api" do gemfile <<-G source "#{source_uri}" - source "#{source_uri}/extra" - gem "back_deps" - G - - bundle :install, 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 - - it "fetches again when more dependencies are found in subsequent sources using deployment mode with blocks" do - build_repo2 do - build_gem "back_deps" do |s| - s.add_dependency "foo" - end - FileUtils.rm_r Dir[gem_repo2("gems/foo-*.gem")] - end - - gemfile <<-G - source "#{source_uri}" source "#{source_uri}/extra" do gem "back_deps" end @@ -583,19 +547,6 @@ RSpec.describe "compact index api" do expect(the_bundle).to include_gems "myrack 1.0.0" end - it "strips http basic auth creds when warning about ambiguous sources" do - gemfile <<-G - source "#{basic_auth_source_uri}" - source "#{file_uri_for(gem_repo1)}" - gem "myrack" - G - - bundle :install, artifice: "compact_index_basic_authentication" - expect(err).to include("Warning: the gem 'myrack' was found in multiple sources.") - expect(err).not_to include("#{user}:#{password}") - expect(the_bundle).to include_gems "myrack 1.0.0" - end - it "does not pass the user / password to different hosts on redirect" do gemfile <<-G source "#{basic_auth_source_uri}" diff --git a/spec/bundler/install/gems/dependency_api_spec.rb b/spec/bundler/install/gems/dependency_api_spec.rb index 012e2d3995..1650df3dfb 100644 --- a/spec/bundler/install/gems/dependency_api_spec.rb +++ b/spec/bundler/install/gems/dependency_api_spec.rb @@ -264,24 +264,6 @@ RSpec.describe "gemcutter's dependency API" do gemfile <<-G source "#{source_uri}" - source "#{source_uri}/extra" - gem "back_deps" - G - - bundle :install, artifice: "endpoint_extra" - expect(the_bundle).to include_gems "back_deps 1.0", "foo 1.0" - end - - it "fetches again when more dependencies are found in subsequent sources using blocks" do - build_repo2 do - build_gem "back_deps" do |s| - s.add_dependency "foo" - end - FileUtils.rm_r Dir[gem_repo2("gems/foo-*.gem")] - end - - gemfile <<-G - source "#{source_uri}" source "#{source_uri}/extra" do gem "back_deps" end @@ -313,11 +295,13 @@ RSpec.describe "gemcutter's dependency API" do expect(the_bundle).to include_gems "myrack 1.2" end - it "considers all possible versions of dependencies from all api gem sources" 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. + it "resolves indirect dependencies to the most scoped source that includes them" 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 tries to + # use the version in the most scoped source, even if not compatible, and + # gives a resolution error build_repo4 do build_gem "activesupport", "1.2.0" build_gem "somegem", "1.0.0" do |s| @@ -327,14 +311,14 @@ RSpec.describe "gemcutter's dependency API" do gemfile <<-G source "#{source_uri}" - source "#{source_uri}/extra" - gem 'somegem', '1.0.0' + source "#{source_uri}/extra" do + gem 'somegem', '1.0.0' + end G - bundle :install, artifice: "endpoint_extra_api" + bundle :install, artifice: "compact_index_extra_api", raise_on_error: false - expect(the_bundle).to include_gems "somegem 1.0.0" - expect(the_bundle).to include_gems "activesupport 1.2.3" + expect(err).to include("Could not find compatible versions") end it "prints API output properly with back deps" do @@ -370,25 +354,6 @@ RSpec.describe "gemcutter's dependency API" do install_gemfile <<-G, artifice: "endpoint_extra_missing" source "#{source_uri}" - source "#{source_uri}/extra" - gem "back_deps" - G - - expect(the_bundle).to include_gems "back_deps 1.0" - end - - it "does not fetch every spec when doing back deps using blocks" do - build_repo2 do - build_gem "back_deps" do |s| - s.add_dependency "foo" - end - build_gem "missing" - - FileUtils.rm_r Dir[gem_repo2("gems/foo-*.gem")] - end - - install_gemfile <<-G, artifice: "endpoint_extra_missing" - source "#{source_uri}" source "#{source_uri}/extra" do gem "back_deps" end @@ -407,26 +372,6 @@ RSpec.describe "gemcutter's dependency API" do gemfile <<-G source "#{source_uri}" - source "#{source_uri}/extra" - gem "back_deps" - 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" - end - - it "fetches again when more dependencies are found in subsequent sources using deployment mode with blocks" do - build_repo2 do - build_gem "back_deps" do |s| - s.add_dependency "foo" - end - FileUtils.rm_r Dir[gem_repo2("gems/foo-*.gem")] - end - - gemfile <<-G - source "#{source_uri}" source "#{source_uri}/extra" do gem "back_deps" end @@ -546,19 +491,6 @@ RSpec.describe "gemcutter's dependency API" do expect(out).not_to include("#{user}:#{password}") end - it "strips http basic auth creds when warning about ambiguous sources" do - gemfile <<-G - source "#{basic_auth_source_uri}" - source "#{file_uri_for(gem_repo1)}" - gem "myrack" - G - - bundle :install, artifice: "endpoint_basic_authentication" - expect(err).to include("Warning: the gem 'myrack' was found in multiple sources.") - expect(err).not_to include("#{user}:#{password}") - expect(the_bundle).to include_gems "myrack 1.0.0" - end - it "does not pass the user / password to different hosts on redirect" do gemfile <<-G source "#{basic_auth_source_uri}" diff --git a/spec/bundler/other/major_deprecation_spec.rb b/spec/bundler/other/major_deprecation_spec.rb index bf0fca5ddd..e9d62bc3b8 100644 --- a/spec/bundler/other/major_deprecation_spec.rb +++ b/spec/bundler/other/major_deprecation_spec.rb @@ -484,53 +484,62 @@ RSpec.describe "major deprecations" do context "bundle install with multiple sources" do before do - install_gemfile <<-G + install_gemfile <<-G, raise_on_error: false source "https://gem.repo3" source "https://gem.repo1" G end - it "shows a deprecation" do - expect(deprecations).to include( - "Your Gemfile contains multiple global 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." + it "fails with a helpful error" do + expect(err).to include( + "This Gemfile contains multiple global sources. " \ + "Each source after the first must include a block to indicate which gems " \ + "should come from that source" ) end it "doesn't show lockfile deprecations if there's a lockfile" do - bundle "install" + lockfile <<~L + GEM + remote: https://gem.repo3/ + remote: https://gem.repo1/ + specs: + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES - expect(deprecations).to include( - "Your Gemfile contains multiple global 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." + BUNDLED WITH + #{Bundler::VERSION} + L + bundle "install", raise_on_error: false + + expect(err).to include( + "This Gemfile contains multiple global sources. " \ + "Each source after the first must include a block to indicate which gems " \ + "should come from that source" ) - expect(deprecations).not_to include( + expect(err).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" + bundle "install", raise_on_error: false - expect(deprecations).to include( - "Your Gemfile contains multiple global 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(err).to include( + "This Gemfile contains multiple global sources. " \ + "Each source after the first must include a block to indicate which gems " \ + "should come from that source" ) - expect(deprecations).not_to include( + expect(err).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: "4" end - context "bundle install in frozen mode with a lockfile with a single rubygems section with multiple remotes" do + context "bundle install with a lockfile with a single rubygems section with multiple remotes" do before do build_repo3 do build_gem "myrack", "0.9.1" @@ -559,17 +568,13 @@ RSpec.describe "major deprecations" do BUNDLED WITH #{Bundler::VERSION} L - - bundle "config set --local frozen true" end - it "shows a deprecation" do - bundle "install" + it "shows an error" do + bundle "install", raise_on_error: false - 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.") + expect(err).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: "4" end context "when Bundler.setup is run in a ruby script" do |
