Merge RubyGems-3.2.11 and Bundler-2.2.11

This commit is contained in:
Hiroshi SHIBATA 2021-03-02 20:37:31 +09:00 committed by NARUSE, Yui
parent 38f8b8d070
commit f375bc77d2
32 changed files with 478 additions and 459 deletions

View file

@ -106,19 +106,6 @@ module Bundler
@locked_platforms = [] @locked_platforms = []
end end
@locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
@disable_multisource = !Bundler.frozen_bundle? || @locked_gem_sources.none? {|s| s.remotes.size > 1 }
unless @disable_multisource
msg = "Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. " \
"You should regenerate your lockfile in a non frozen environment."
Bundler::SharedHelpers.major_deprecation 2, msg
@sources.allow_multisource!
@locked_gem_sources.each(&:allow_multisource!)
end
@unlock[:gems] ||= [] @unlock[:gems] ||= []
@unlock[:sources] ||= [] @unlock[:sources] ||= []
@unlock[:ruby] ||= if @ruby_version && locked_ruby_version_object @unlock[:ruby] ||= if @ruby_version && locked_ruby_version_object
@ -158,14 +145,6 @@ module Bundler
end end
end end
def disable_multisource?
@disable_multisource
end
def allow_multisource!
@disable_multisource = false
end
def resolve_with_cache! def resolve_with_cache!
raise "Specs already loaded" if @specs raise "Specs already loaded" if @specs
sources.cached! sources.cached!
@ -285,7 +264,7 @@ module Bundler
# Run a resolve against the locally available gems # Run a resolve against the locally available gems
Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}") Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}")
expanded_dependencies = expand_dependencies(dependencies + metadata_dependencies, @remote) expanded_dependencies = expand_dependencies(dependencies + metadata_dependencies, @remote)
Resolver.resolve(expanded_dependencies, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms) Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
end end
end end
end end
@ -551,9 +530,6 @@ module Bundler
attr_reader :sources attr_reader :sources
private :sources private :sources
attr_reader :locked_gem_sources
private :locked_gem_sources
def nothing_changed? def nothing_changed?
!@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes && !@locked_specs_incomplete_for_platform !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes && !@locked_specs_incomplete_for_platform
end end
@ -678,21 +654,22 @@ module Bundler
end end
def converge_rubygems_sources def converge_rubygems_sources
return false if disable_multisource? return false if Bundler.feature_flag.disable_multisource?
return false if locked_gem_sources.empty?
# Get the RubyGems remotes from the Gemfile
actual_remotes = sources.rubygems_remotes
return false if actual_remotes.empty?
changes = false changes = false
# Get the RubyGems sources from the Gemfile.lock
locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
# Get the RubyGems remotes from the Gemfile
actual_remotes = sources.rubygems_remotes
# If there is a RubyGems source in both # If there is a RubyGems source in both
if !locked_gem_sources.empty? && !actual_remotes.empty?
locked_gem_sources.each do |locked_gem| locked_gem_sources.each do |locked_gem|
# Merge the remotes from the Gemfile into the Gemfile.lock # Merge the remotes from the Gemfile into the Gemfile.lock
changes |= locked_gem.replace_remotes(actual_remotes, Bundler.settings[:allow_deployment_source_credential_changes]) changes |= locked_gem.replace_remotes(actual_remotes, Bundler.settings[:allow_deployment_source_credential_changes])
end end
end
changes changes
end end
@ -916,18 +893,30 @@ module Bundler
# Record the specs available in each gem's source, so that those # Record the specs available in each gem's source, so that those
# specs will be available later when the resolver knows where to # specs will be available later when the resolver knows where to
# look for that gemspec (or its dependencies) # look for that gemspec (or its dependencies)
source_requirements = { :default => sources.default_source }.merge(dependency_source_requirements) default = sources.default_source
source_requirements = { :default => default }
default = nil unless Bundler.feature_flag.disable_multisource?
dependencies.each do |dep|
next unless source = dep.source || default
source_requirements[dep.name] = source
end
metadata_dependencies.each do |dep| metadata_dependencies.each do |dep|
source_requirements[dep.name] = sources.metadata_source source_requirements[dep.name] = sources.metadata_source
end end
source_requirements[:global] = index unless disable_multisource?
source_requirements[:default_bundler] = source_requirements["bundler"] || source_requirements[:default] source_requirements[:default_bundler] = source_requirements["bundler"] || source_requirements[:default]
source_requirements["bundler"] = sources.metadata_source # needs to come last to override source_requirements["bundler"] = sources.metadata_source # needs to come last to override
source_requirements source_requirements
end end
def pinned_spec_names(skip = nil) def pinned_spec_names(skip = nil)
dependency_source_requirements.reject {|_, source| source == skip }.keys pinned_names = []
default = Bundler.feature_flag.disable_multisource? && sources.default_source
@dependencies.each do |dep|
next unless dep_source = dep.source || default
next if dep_source == skip
pinned_names << dep.name
end
pinned_names
end end
def requested_groups def requested_groups
@ -984,18 +973,5 @@ module Bundler
Bundler.settings[:allow_deployment_source_credential_changes] && source.equivalent_remotes?(sources.rubygems_remotes) Bundler.settings[:allow_deployment_source_credential_changes] && source.equivalent_remotes?(sources.rubygems_remotes)
end end
def dependency_source_requirements
@dependency_source_requirements ||= begin
source_requirements = {}
default = disable_multisource? && sources.default_source
dependencies.each do |dep|
dep_source = dep.source || default
next unless dep_source
source_requirements[dep.name] = dep_source
end
source_requirements
end
end
end end
end end

View file

@ -24,9 +24,6 @@ module Bundler
def initialize def initialize
@source = nil @source = nil
@sources = SourceList.new @sources = SourceList.new
@global_rubygems_sources = []
@git_sources = {} @git_sources = {}
@dependencies = [] @dependencies = []
@groups = [] @groups = []
@ -48,7 +45,6 @@ module Bundler
@gemfiles << expanded_gemfile_path @gemfiles << expanded_gemfile_path
contents ||= Bundler.read_file(@gemfile.to_s) contents ||= Bundler.read_file(@gemfile.to_s)
instance_eval(contents.dup.tap{|x| x.untaint if RUBY_VERSION < "2.7" }, gemfile.to_s, 1) instance_eval(contents.dup.tap{|x| x.untaint if RUBY_VERSION < "2.7" }, gemfile.to_s, 1)
check_primary_source_safety
rescue Exception => e # rubocop:disable Lint/RescueException rescue Exception => e # rubocop:disable Lint/RescueException
message = "There was an error " \ message = "There was an error " \
"#{e.is_a?(GemfileEvalError) ? "evaluating" : "parsing"} " \ "#{e.is_a?(GemfileEvalError) ? "evaluating" : "parsing"} " \
@ -168,7 +164,8 @@ module Bundler
elsif block_given? elsif block_given?
with_source(@sources.add_rubygems_source("remotes" => source), &blk) with_source(@sources.add_rubygems_source("remotes" => source), &blk)
else else
@global_rubygems_sources << source check_primary_source_safety(@sources)
@sources.global_rubygems_source = source
end end
end end
@ -186,14 +183,24 @@ module Bundler
end end
def path(path, options = {}, &blk) def path(path, options = {}, &blk)
unless block_given?
msg = "You can no longer specify a path source by itself. Instead, \n" \
"either use the :path option on a gem, or specify the gems that \n" \
"bundler should find in the path source by passing a block to \n" \
"the path method, like: \n\n" \
" path 'dir/containing/rails' do\n" \
" gem 'rails'\n" \
" end\n\n"
raise DeprecatedError, msg if Bundler.feature_flag.disable_multisource?
SharedHelpers.major_deprecation(2, msg.strip)
end
source_options = normalize_hash(options).merge( source_options = normalize_hash(options).merge(
"path" => Pathname.new(path), "path" => Pathname.new(path),
"root_path" => gemfile_root, "root_path" => gemfile_root,
"gemspec" => gemspecs.find {|g| g.name == options["name"] } "gemspec" => gemspecs.find {|g| g.name == options["name"] }
) )
source_options["global"] = true unless block_given?
source = @sources.add_path_source(source_options) source = @sources.add_path_source(source_options)
with_source(source, &blk) with_source(source, &blk)
end end
@ -272,11 +279,6 @@ module Bundler
raise GemfileError, "Undefined local variable or method `#{name}' for Gemfile" raise GemfileError, "Undefined local variable or method `#{name}' for Gemfile"
end end
def check_primary_source_safety
check_path_source_safety
check_rubygems_source_safety
end
private private
def add_git_sources def add_git_sources
@ -438,40 +440,25 @@ repo_name ||= user_name
end end
end end
def check_path_source_safety def check_primary_source_safety(source_list)
return if @sources.global_path_source.nil? return if source_list.rubygems_primary_remotes.empty? && source_list.global_rubygems_source.nil?
msg = "You can no longer specify a path source by itself. Instead, \n" \ if Bundler.feature_flag.disable_multisource?
"either use the :path option on a gem, or specify the gems that \n" \
"bundler should find in the path source by passing a block to \n" \
"the path method, like: \n\n" \
" path 'dir/containing/rails' do\n" \
" gem 'rails'\n" \
" end\n\n"
SharedHelpers.major_deprecation(2, msg.strip)
end
def check_rubygems_source_safety
if @global_rubygems_sources.size <= 1
@sources.global_rubygems_source = @global_rubygems_sources.first
return
end
@global_rubygems_sources.each do |source|
@sources.add_rubygems_remote(source)
end
if Bundler.feature_flag.bundler_3_mode?
msg = "This Gemfile contains multiple primary sources. " \ msg = "This Gemfile contains multiple primary sources. " \
"Each source after the first must include a block to indicate which gems " \ "Each source after the first must include a block to indicate which gems " \
"should come from that source" "should come from that source"
unless Bundler.feature_flag.bundler_2_mode?
msg += ". To downgrade this error to a warning, run " \
"`bundle config unset disable_multisource`"
end
raise GemfileEvalError, msg raise GemfileEvalError, msg
else else
Bundler::SharedHelpers.major_deprecation 2, "Your Gemfile contains multiple primary sources. " \ Bundler::SharedHelpers.major_deprecation 2, "Your Gemfile contains multiple primary sources. " \
"Using `source` more than once without a block is a security risk, and " \ "Using `source` more than once without a block is a security risk, and " \
"may result in installing unexpected gems. To resolve this warning, use " \ "may result in installing unexpected gems. To resolve this warning, use " \
"a block to indicate which gems should come from the secondary source." "a block to indicate which gems should come from the secondary source. " \
"To upgrade this warning to an error, run `bundle config set --local " \
"disable_multisource true`."
end end
end end

View file

@ -32,6 +32,7 @@ module Bundler
settings_flag(:cache_all) { bundler_3_mode? } settings_flag(:cache_all) { bundler_3_mode? }
settings_flag(:default_install_uses_path) { bundler_3_mode? } settings_flag(:default_install_uses_path) { bundler_3_mode? }
settings_flag(:deployment_means_frozen) { bundler_3_mode? } settings_flag(:deployment_means_frozen) { bundler_3_mode? }
settings_flag(:disable_multisource) { bundler_3_mode? }
settings_flag(:forget_cli_options) { bundler_3_mode? } settings_flag(:forget_cli_options) { bundler_3_mode? }
settings_flag(:global_gem_cache) { bundler_3_mode? } settings_flag(:global_gem_cache) { bundler_3_mode? }
settings_flag(:only_update_to_newer_versions) { bundler_3_mode? } settings_flag(:only_update_to_newer_versions) { bundler_3_mode? }

View file

@ -50,7 +50,6 @@ def gemfile(install = false, options = {}, &gemfile)
Bundler::Plugin.gemfile_install(&gemfile) if Bundler.feature_flag.plugins? Bundler::Plugin.gemfile_install(&gemfile) if Bundler.feature_flag.plugins?
builder = Bundler::Dsl.new builder = Bundler::Dsl.new
builder.instance_eval(&gemfile) builder.instance_eval(&gemfile)
builder.check_primary_source_safety
Bundler.settings.temporary(:frozen => false) do Bundler.settings.temporary(:frozen => false) do
definition = builder.to_definition(nil, true) definition = builder.to_definition(nil, true)

View file

@ -64,6 +64,8 @@ module Bundler
@state = nil @state = nil
@specs = {} @specs = {}
@rubygems_aggregate = Source::Rubygems.new
if lockfile.match(/<<<<<<<|=======|>>>>>>>|\|\|\|\|\|\|\|/) if lockfile.match(/<<<<<<<|=======|>>>>>>>|\|\|\|\|\|\|\|/)
raise LockfileError, "Your #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} contains merge conflicts.\n" \ raise LockfileError, "Your #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} contains merge conflicts.\n" \
"Run `git checkout HEAD -- #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)}` first to get a clean lock." "Run `git checkout HEAD -- #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)}` first to get a clean lock."
@ -87,6 +89,7 @@ module Bundler
send("parse_#{@state}", line) send("parse_#{@state}", line)
end end
end end
@sources << @rubygems_aggregate unless Bundler.feature_flag.disable_multisource?
@specs = @specs.values.sort_by(&:identifier) @specs = @specs.values.sort_by(&:identifier)
warn_for_outdated_bundler_version warn_for_outdated_bundler_version
rescue ArgumentError => e rescue ArgumentError => e
@ -131,19 +134,16 @@ module Bundler
@sources << @current_source @sources << @current_source
end end
when GEM when GEM
source_remotes = Array(@opts["remote"]) if Bundler.feature_flag.disable_multisource?
if source_remotes.size == 1
@opts["remotes"] = @opts.delete("remote") @opts["remotes"] = @opts.delete("remote")
@current_source = TYPES[@type].from_lock(@opts) @current_source = TYPES[@type].from_lock(@opts)
else
source_remotes.each do |url|
rubygems_aggregate.add_remote(url)
end
@current_source = rubygems_aggregate
end
@sources << @current_source @sources << @current_source
else
Array(@opts["remote"]).each do |url|
@rubygems_aggregate.add_remote(url)
end
@current_source = @rubygems_aggregate
end
when PLUGIN when PLUGIN
@current_source = Plugin.source_from_lock(@opts) @current_source = Plugin.source_from_lock(@opts)
@sources << @current_source @sources << @current_source
@ -245,9 +245,5 @@ module Bundler
def parse_ruby(line) def parse_ruby(line)
@ruby_version = line.strip @ruby_version = line.strip
end end
def rubygems_aggregate
@rubygems_aggregate ||= Source::Rubygems.new
end
end end
end end

View file

@ -56,6 +56,9 @@ Executing \fBbundle config unset \-\-local <name> <value>\fR will delete the con
.P .P
Executing bundle with the \fBBUNDLE_IGNORE_CONFIG\fR environment variable set will cause it to ignore all configuration\. Executing bundle with the \fBBUNDLE_IGNORE_CONFIG\fR environment variable set will cause it to ignore all configuration\.
. .
.P
Executing \fBbundle config set \-\-local disable_multisource true\fR upgrades the warning about the Gemfile containing multiple primary sources to an error\. Executing \fBbundle config unset disable_multisource\fR downgrades this error to a warning\.
.
.SH "REMEMBERING OPTIONS" .SH "REMEMBERING OPTIONS"
Flags passed to \fBbundle install\fR or the Bundler runtime, such as \fB\-\-path foo\fR or \fB\-\-without production\fR, are remembered between commands and saved to your local application\'s configuration (normally, \fB\./\.bundle/config\fR)\. Flags passed to \fBbundle install\fR or the Bundler runtime, such as \fB\-\-path foo\fR or \fB\-\-without production\fR, are remembered between commands and saved to your local application\'s configuration (normally, \fB\./\.bundle/config\fR)\.
. .
@ -181,6 +184,9 @@ The following is a list of all configuration keys and their purpose\. You can le
\fBdisable_local_revision_check\fR (\fBBUNDLE_DISABLE_LOCAL_REVISION_CHECK\fR): Allow Bundler to use a local git override without checking if the revision present in the lockfile is present in the repository\. \fBdisable_local_revision_check\fR (\fBBUNDLE_DISABLE_LOCAL_REVISION_CHECK\fR): Allow Bundler to use a local git override without checking if the revision present in the lockfile is present in the repository\.
. .
.IP "\(bu" 4 .IP "\(bu" 4
\fBdisable_multisource\fR (\fBBUNDLE_DISABLE_MULTISOURCE\fR): When set, Gemfiles containing multiple sources will produce errors instead of warnings\. Use \fBbundle config unset disable_multisource\fR to unset\.
.
.IP "\(bu" 4
\fBdisable_shared_gems\fR (\fBBUNDLE_DISABLE_SHARED_GEMS\fR): Stop Bundler from accessing gems installed to RubyGems\' normal location\. \fBdisable_shared_gems\fR (\fBBUNDLE_DISABLE_SHARED_GEMS\fR): Stop Bundler from accessing gems installed to RubyGems\' normal location\.
. .
.IP "\(bu" 4 .IP "\(bu" 4

View file

@ -47,6 +47,10 @@ configuration only from the local application.
Executing bundle with the `BUNDLE_IGNORE_CONFIG` environment variable set will Executing bundle with the `BUNDLE_IGNORE_CONFIG` environment variable set will
cause it to ignore all configuration. cause it to ignore all configuration.
Executing `bundle config set --local disable_multisource true` upgrades the warning about
the Gemfile containing multiple primary sources to an error. Executing `bundle
config unset disable_multisource` downgrades this error to a warning.
## REMEMBERING OPTIONS ## REMEMBERING OPTIONS
Flags passed to `bundle install` or the Bundler runtime, such as `--path foo` or Flags passed to `bundle install` or the Bundler runtime, such as `--path foo` or
@ -174,6 +178,10 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
* `disable_local_revision_check` (`BUNDLE_DISABLE_LOCAL_REVISION_CHECK`): * `disable_local_revision_check` (`BUNDLE_DISABLE_LOCAL_REVISION_CHECK`):
Allow Bundler to use a local git override without checking if the revision Allow Bundler to use a local git override without checking if the revision
present in the lockfile is present in the repository. present in the lockfile is present in the repository.
* `disable_multisource` (`BUNDLE_DISABLE_MULTISOURCE`):
When set, Gemfiles containing multiple sources will produce errors
instead of warnings.
Use `bundle config unset disable_multisource` to unset.
* `disable_shared_gems` (`BUNDLE_DISABLE_SHARED_GEMS`): * `disable_shared_gems` (`BUNDLE_DISABLE_SHARED_GEMS`):
Stop Bundler from accessing gems installed to RubyGems' normal location. Stop Bundler from accessing gems installed to RubyGems' normal location.
* `disable_version_check` (`BUNDLE_DISABLE_VERSION_CHECK`): * `disable_version_check` (`BUNDLE_DISABLE_VERSION_CHECK`):

View file

@ -105,7 +105,6 @@ module Bundler
else else
builder.eval_gemfile(gemfile) builder.eval_gemfile(gemfile)
end end
builder.check_primary_source_safety
definition = builder.to_definition(nil, true) definition = builder.to_definition(nil, true)
return if definition.dependencies.empty? return if definition.dependencies.empty?

View file

@ -16,6 +16,7 @@ module Bundler
version = options[:version] || [">= 0"] version = options[:version] || [">= 0"]
Bundler.settings.temporary(:disable_multisource => false) do
if options[:git] if options[:git]
install_git(names, version, options) install_git(names, version, options)
elsif options[:local_git] elsif options[:local_git]
@ -25,6 +26,7 @@ module Bundler
install_rubygems(names, version, sources) install_rubygems(names, version, sources)
end end
end end
end
# Installs the plugin from Definition object created by limited parsing of # Installs the plugin from Definition object created by limited parsing of
# Gemfile searching for plugins to be installed # Gemfile searching for plugins to be installed
@ -82,7 +84,6 @@ module Bundler
deps = names.map {|name| Dependency.new name, version } deps = names.map {|name| Dependency.new name, version }
definition = Definition.new(nil, deps, source_list, true) definition = Definition.new(nil, deps, source_list, true)
definition.allow_multisource!
install_definition(definition) install_definition(definition)
end end

View file

@ -17,14 +17,15 @@ module Bundler
# ==== Returns # ==== Returns
# <GemBundle>,nil:: If the list of dependencies can be resolved, a # <GemBundle>,nil:: If the list of dependencies can be resolved, a
# collection of gemspecs is returned. Otherwise, nil is returned. # collection of gemspecs is returned. Otherwise, nil is returned.
def self.resolve(requirements, source_requirements = {}, base = [], gem_version_promoter = GemVersionPromoter.new, additional_base_requirements = [], platforms = nil) def self.resolve(requirements, index, source_requirements = {}, base = [], gem_version_promoter = GemVersionPromoter.new, additional_base_requirements = [], platforms = nil)
base = SpecSet.new(base) unless base.is_a?(SpecSet) base = SpecSet.new(base) unless base.is_a?(SpecSet)
resolver = new(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms) resolver = new(index, source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
result = resolver.start(requirements) result = resolver.start(requirements)
SpecSet.new(result) SpecSet.new(result)
end end
def initialize(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms) def initialize(index, source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
@index = index
@source_requirements = source_requirements @source_requirements = source_requirements
@base = base @base = base
@resolver = Molinillo::Resolver.new(self, self) @resolver = Molinillo::Resolver.new(self, self)
@ -39,7 +40,7 @@ module Bundler
@resolving_only_for_ruby = platforms == [Gem::Platform::RUBY] @resolving_only_for_ruby = platforms == [Gem::Platform::RUBY]
@gem_version_promoter = gem_version_promoter @gem_version_promoter = gem_version_promoter
@use_gvp = Bundler.feature_flag.use_gem_version_promoter_for_major_updates? || !@gem_version_promoter.major? @use_gvp = Bundler.feature_flag.use_gem_version_promoter_for_major_updates? || !@gem_version_promoter.major?
@no_aggregate_global_source = @source_requirements[:global].nil? @lockfile_uses_separate_rubygems_sources = Bundler.feature_flag.disable_multisource?
@variant_specific_names = [] @variant_specific_names = []
@generic_names = ["Ruby\0", "RubyGems\0"] @generic_names = ["Ruby\0", "RubyGems\0"]
@ -124,7 +125,8 @@ module Bundler
dependency = dependency_proxy.dep dependency = dependency_proxy.dep
name = dependency.name name = dependency.name
search_result = @search_for[dependency_proxy] ||= begin search_result = @search_for[dependency_proxy] ||= begin
results = results_for(dependency, @base[name]) index = index_for(dependency)
results = index.search(dependency, @base[name])
if vertex = @base_dg.vertex_named(name) if vertex = @base_dg.vertex_named(name)
locked_requirement = vertex.payload.requirement locked_requirement = vertex.payload.requirement
@ -193,26 +195,23 @@ module Bundler
search_result search_result
end end
def index_for(dependency, base) def index_for(dependency)
source = @source_requirements[dependency.name] source = @source_requirements[dependency.name]
if source if source
source.specs source.specs
elsif @no_aggregate_global_source elsif @lockfile_uses_separate_rubygems_sources
dependency.all_sources.find(-> { Index.new }) do |s| Index.build do |idx|
idx = s.specs if dependency.all_sources
results = idx.search(dependency, base) dependency.all_sources.each {|s| idx.add_source(s.specs) if s }
next if results.empty? || results == base else
return idx idx.add_source @source_requirements[:default].specs
end
end end
else else
@source_requirements[:global] @index
end end
end end
def results_for(dependency, base)
index_for(dependency, base).search(dependency, base)
end
def name_for(dependency) def name_for(dependency)
dependency.name dependency.name
end end
@ -239,13 +238,11 @@ module Bundler
def relevant_sources_for_vertex(vertex) def relevant_sources_for_vertex(vertex)
if vertex.root? if vertex.root?
[@source_requirements[vertex.name]].compact [@source_requirements[vertex.name]]
elsif @no_aggregate_global_source elsif @lockfile_uses_separate_rubygems_sources
vertex.recursive_predecessors.map do |v| vertex.recursive_predecessors.map do |v|
@source_requirements[v.name] @source_requirements[v.name]
end.compact << @source_requirements[:default] end << @source_requirements[:default]
else
[]
end end
end end
@ -286,7 +283,7 @@ module Bundler
if (base = @base[dependency.name]) && !base.empty? if (base = @base[dependency.name]) && !base.empty?
dependency.requirement.satisfied_by?(base.first.version) ? 0 : 1 dependency.requirement.satisfied_by?(base.first.version) ? 0 : 1
else else
all = index_for(dependency, base).search(dependency.name).size all = index_for(dependency).search(dependency.name).size
if all <= 1 if all <= 1
all - 1_000_000 all - 1_000_000
@ -329,7 +326,7 @@ module Bundler
"The source does not contain any versions of '#{name}'" "The source does not contain any versions of '#{name}'"
end end
else else
message = "Could not find gem '#{SharedHelpers.pretty_dependency(requirement)}' in any of the gem sources " \ message = "Could not find gem '#{requirement}' in any of the gem sources " \
"listed in your Gemfile#{cache_message}." "listed in your Gemfile#{cache_message}."
end end
raise GemNotFound, message raise GemNotFound, message
@ -414,8 +411,14 @@ module Bundler
relevant_sources = if conflict.requirement.source relevant_sources = if conflict.requirement.source
[conflict.requirement.source] [conflict.requirement.source]
else elsif conflict.requirement.all_sources
conflict.requirement.all_sources conflict.requirement.all_sources
elsif @lockfile_uses_separate_rubygems_sources
# every conflict should have an explicit group of sources when we
# enforce strict pinning
raise "no source set for #{conflict}"
else
[]
end.compact.map(&:to_s).uniq.sort end.compact.map(&:to_s).uniq.sort
metadata_requirement = name.end_with?("\0") metadata_requirement = name.end_with?("\0")
@ -452,8 +455,7 @@ module Bundler
def validate_resolved_specs!(resolved_specs) def validate_resolved_specs!(resolved_specs)
resolved_specs.each do |v| resolved_specs.each do |v|
name = v.name name = v.name
sources = relevant_sources_for_vertex(v) next unless sources = relevant_sources_for_vertex(v)
next unless sources.any?
sources.compact! sources.compact!
if default_index = sources.index(@source_requirements[:default]) if default_index = sources.index(@source_requirements[:default])
sources.delete_at(default_index) sources.delete_at(default_index)
@ -462,12 +464,14 @@ module Bundler
sources.uniq! sources.uniq!
next if sources.size <= 1 next if sources.size <= 1
multisource_disabled = Bundler.feature_flag.disable_multisource?
msg = ["The gem '#{name}' was found in multiple relevant sources."] msg = ["The gem '#{name}' was found in multiple relevant sources."]
msg.concat sources.map {|s| " * #{s}" }.sort msg.concat sources.map {|s| " * #{s}" }.sort
msg << "You #{@no_aggregate_global_source ? :must : :should} add this gem to the source block for the source you wish it to be installed from." msg << "You #{multisource_disabled ? :must : :should} add this gem to the source block for the source you wish it to be installed from."
msg = msg.join("\n") msg = msg.join("\n")
raise SecurityError, msg if @no_aggregate_global_source raise SecurityError, msg if multisource_disabled
Bundler.ui.warn "Warning: #{msg}" Bundler.ui.warn "Warning: #{msg}"
end end
end end

View file

@ -20,6 +20,7 @@ module Bundler
disable_exec_load disable_exec_load
disable_local_branch_check disable_local_branch_check
disable_local_revision_check disable_local_revision_check
disable_multisource
disable_shared_gems disable_shared_gems
disable_version_check disable_version_check
force_ruby_platform force_ruby_platform

View file

@ -21,7 +21,6 @@ module Bundler
@allow_remote = false @allow_remote = false
@allow_cached = false @allow_cached = false
@caches = [cache_path, *Bundler.rubygems.gem_cache] @caches = [cache_path, *Bundler.rubygems.gem_cache]
@disable_multisource = true
Array(options["remotes"] || []).reverse_each {|r| add_remote(r) } Array(options["remotes"] || []).reverse_each {|r| add_remote(r) }
end end
@ -50,16 +49,8 @@ module Bundler
o.is_a?(Rubygems) && (o.credless_remotes - credless_remotes).empty? o.is_a?(Rubygems) && (o.credless_remotes - credless_remotes).empty?
end end
def disable_multisource?
@disable_multisource
end
def allow_multisource!
@disable_multisource = false
end
def can_lock?(spec) def can_lock?(spec)
return super if disable_multisource? return super if Bundler.feature_flag.disable_multisource?
spec.source.is_a?(Rubygems) spec.source.is_a?(Rubygems)
end end

View file

@ -5,41 +5,24 @@ module Bundler
attr_reader :path_sources, attr_reader :path_sources,
:git_sources, :git_sources,
:plugin_sources, :plugin_sources,
:global_path_source, :global_rubygems_source,
:metadata_source, :metadata_source
:disable_multisource
def global_rubygems_source
@global_rubygems_source ||= rubygems_aggregate_class.new
end
def initialize def initialize
@path_sources = [] @path_sources = []
@git_sources = [] @git_sources = []
@plugin_sources = [] @plugin_sources = []
@global_rubygems_source = nil @global_rubygems_source = nil
@global_path_source = nil @rubygems_aggregate = rubygems_aggregate_class.new
@rubygems_sources = [] @rubygems_sources = []
@metadata_source = Source::Metadata.new @metadata_source = Source::Metadata.new
@disable_multisource = true
end
def disable_multisource?
@disable_multisource
end
def allow_multisource!
rubygems_sources.map(&:allow_multisource!)
@disable_multisource = false
end end
def add_path_source(options = {}) def add_path_source(options = {})
if options["gemspec"] if options["gemspec"]
add_source_to_list Source::Gemspec.new(options), path_sources add_source_to_list Source::Gemspec.new(options), path_sources
else else
path_source = add_source_to_list Source::Path.new(options), path_sources add_source_to_list Source::Path.new(options), path_sources
@global_path_source ||= path_source if options["global"]
path_source
end end
end end
@ -58,20 +41,24 @@ module Bundler
end end
def global_rubygems_source=(uri) def global_rubygems_source=(uri)
if Bundler.feature_flag.disable_multisource?
@global_rubygems_source ||= rubygems_aggregate_class.new("remotes" => uri) @global_rubygems_source ||= rubygems_aggregate_class.new("remotes" => uri)
end end
add_rubygems_remote(uri)
end
def add_rubygems_remote(uri) def add_rubygems_remote(uri)
global_rubygems_source.add_remote(uri) return if Bundler.feature_flag.disable_multisource?
global_rubygems_source @rubygems_aggregate.add_remote(uri)
@rubygems_aggregate
end end
def default_source def default_source
global_path_source || global_rubygems_source global_rubygems_source || @rubygems_aggregate
end end
def rubygems_sources def rubygems_sources
@rubygems_sources + [global_rubygems_source] @rubygems_sources + [default_source]
end end
def rubygems_remotes def rubygems_remotes
@ -88,7 +75,7 @@ module Bundler
def lock_sources def lock_sources
lock_sources = (path_sources + git_sources + plugin_sources).sort_by(&:to_s) lock_sources = (path_sources + git_sources + plugin_sources).sort_by(&:to_s)
if disable_multisource? if Bundler.feature_flag.disable_multisource?
lock_sources + rubygems_sources.sort_by(&:to_s) lock_sources + rubygems_sources.sort_by(&:to_s)
else else
lock_sources << combine_rubygems_sources lock_sources << combine_rubygems_sources
@ -105,9 +92,9 @@ module Bundler
end end
end end
replacement_rubygems = !disable_multisource? && replacement_rubygems = !Bundler.feature_flag.disable_multisource? &&
replacement_sources.detect {|s| s.is_a?(Source::Rubygems) } replacement_sources.detect {|s| s.is_a?(Source::Rubygems) }
@global_rubygems_source = replacement_rubygems if replacement_rubygems @rubygems_aggregate = replacement_rubygems if replacement_rubygems
return true if !equal_sources?(lock_sources, replacement_sources) && !equivalent_sources?(lock_sources, replacement_sources) return true if !equal_sources?(lock_sources, replacement_sources) && !equivalent_sources?(lock_sources, replacement_sources)
return true if replacement_rubygems && rubygems_remotes.sort_by(&:to_s) != replacement_rubygems.remotes.sort_by(&:to_s) return true if replacement_rubygems && rubygems_remotes.sort_by(&:to_s) != replacement_rubygems.remotes.sort_by(&:to_s)
@ -123,6 +110,10 @@ module Bundler
all_sources.each(&:remote!) all_sources.each(&:remote!)
end end
def rubygems_primary_remotes
@rubygems_aggregate.remotes
end
private private
def rubygems_aggregate_class def rubygems_aggregate_class
@ -145,9 +136,7 @@ module Bundler
end end
def combine_rubygems_sources def combine_rubygems_sources
aggregate_source = Source::Rubygems.new("remotes" => rubygems_remotes) Source::Rubygems.new("remotes" => rubygems_remotes)
aggregate_source.allow_multisource! unless disable_multisource?
aggregate_source
end end
def warn_on_git_protocol(source) def warn_on_git_protocol(source)

View file

@ -1,7 +1,7 @@
# frozen_string_literal: false # frozen_string_literal: false
module Bundler module Bundler
VERSION = "2.2.10".freeze VERSION = "2.2.11".freeze
def self.bundler_major_version def self.bundler_major_version
@bundler_major_version ||= VERSION.split(".").first.to_i @bundler_major_version ||= VERSION.split(".").first.to_i

View file

@ -8,7 +8,7 @@
require 'rbconfig' require 'rbconfig'
module Gem module Gem
VERSION = "3.2.10".freeze VERSION = "3.2.11".freeze
end end
# Must be first since it unloads the prelude from 1.9.2 # Must be first since it unloads the prelude from 1.9.2

View file

@ -45,6 +45,7 @@ class Gem::ConfigFile
DEFAULT_UPDATE_SOURCES = true DEFAULT_UPDATE_SOURCES = true
DEFAULT_CONCURRENT_DOWNLOADS = 8 DEFAULT_CONCURRENT_DOWNLOADS = 8
DEFAULT_CERT_EXPIRATION_LENGTH_DAYS = 365 DEFAULT_CERT_EXPIRATION_LENGTH_DAYS = 365
DEFAULT_IPV4_FALLBACK_ENABLED = false
## ##
# For Ruby packagers to set configuration defaults. Set in # For Ruby packagers to set configuration defaults. Set in
@ -140,6 +141,12 @@ class Gem::ConfigFile
attr_accessor :cert_expiration_length_days attr_accessor :cert_expiration_length_days
##
# == Experimental ==
# Fallback to IPv4 when IPv6 is not reachable or slow (default: false)
attr_accessor :ipv4_fallback_enabled
## ##
# Path name of directory or file of openssl client certificate, used for remote https connection with client authentication # Path name of directory or file of openssl client certificate, used for remote https connection with client authentication
@ -175,6 +182,7 @@ class Gem::ConfigFile
@update_sources = DEFAULT_UPDATE_SOURCES @update_sources = DEFAULT_UPDATE_SOURCES
@concurrent_downloads = DEFAULT_CONCURRENT_DOWNLOADS @concurrent_downloads = DEFAULT_CONCURRENT_DOWNLOADS
@cert_expiration_length_days = DEFAULT_CERT_EXPIRATION_LENGTH_DAYS @cert_expiration_length_days = DEFAULT_CERT_EXPIRATION_LENGTH_DAYS
@ipv4_fallback_enabled = ENV['IPV4_FALLBACK_ENABLED'] == 'true' || DEFAULT_IPV4_FALLBACK_ENABLED
operating_system_config = Marshal.load Marshal.dump(OPERATING_SYSTEM_DEFAULTS) operating_system_config = Marshal.load Marshal.dump(OPERATING_SYSTEM_DEFAULTS)
platform_config = Marshal.load Marshal.dump(PLATFORM_DEFAULTS) platform_config = Marshal.load Marshal.dump(PLATFORM_DEFAULTS)
@ -203,6 +211,7 @@ class Gem::ConfigFile
@disable_default_gem_server = @hash[:disable_default_gem_server] if @hash.key? :disable_default_gem_server @disable_default_gem_server = @hash[:disable_default_gem_server] if @hash.key? :disable_default_gem_server
@sources = @hash[:sources] if @hash.key? :sources @sources = @hash[:sources] if @hash.key? :sources
@cert_expiration_length_days = @hash[:cert_expiration_length_days] if @hash.key? :cert_expiration_length_days @cert_expiration_length_days = @hash[:cert_expiration_length_days] if @hash.key? :cert_expiration_length_days
@ipv4_fallback_enabled = @hash[:ipv4_fallback_enabled] if @hash.key? :ipv4_fallback_enabled
@ssl_verify_mode = @hash[:ssl_verify_mode] if @hash.key? :ssl_verify_mode @ssl_verify_mode = @hash[:ssl_verify_mode] if @hash.key? :ssl_verify_mode
@ssl_ca_cert = @hash[:ssl_ca_cert] if @hash.key? :ssl_ca_cert @ssl_ca_cert = @hash[:ssl_ca_cert] if @hash.key? :ssl_ca_cert

View file

@ -0,0 +1,49 @@
require 'socket'
module CoreExtensions
module TCPSocketExt
def self.prepended(base)
base.prepend Initializer
end
module Initializer
CONNECTION_TIMEOUT = 5
IPV4_DELAY_SECONDS = 0.1
def initialize(host, serv, *rest)
mutex = Mutex.new
addrs = []
cond_var = ConditionVariable.new
Addrinfo.foreach(host, serv, nil, :STREAM) do |addr|
Thread.report_on_exception = false if defined? Thread.report_on_exception = ()
Thread.new(addr) do
# give head start to ipv6 addresses
sleep IPV4_DELAY_SECONDS if addr.ipv4?
# raises Errno::ECONNREFUSED when ip:port is unreachable
Socket.tcp(addr.ip_address, serv, connect_timeout: CONNECTION_TIMEOUT).close
mutex.synchronize do
addrs << addr.ip_address
cond_var.signal
end
end
end
mutex.synchronize do
timeout_time = CONNECTION_TIMEOUT + Time.now.to_f
while addrs.empty? && (remaining_time = timeout_time - Time.now.to_f) > 0
cond_var.wait(mutex, remaining_time)
end
host = addrs.shift unless addrs.empty?
end
super(host, serv, *rest)
end
end
end
end
TCPSocket.prepend CoreExtensions::TCPSocketExt

View file

@ -78,6 +78,7 @@ class Gem::RemoteFetcher
# fetching the gem. # fetching the gem.
def initialize(proxy=nil, dns=nil, headers={}) def initialize(proxy=nil, dns=nil, headers={})
require 'rubygems/core_ext/tcpsocket_init' if Gem.configuration.ipv4_fallback_enabled
require 'net/http' require 'net/http'
require 'stringio' require 'stringio'
require 'uri' require 'uri'

View file

@ -25,7 +25,7 @@ RSpec.describe Bundler::Dsl do
expect { subject.git_source(:example) }.to raise_error(Bundler::InvalidOption) expect { subject.git_source(:example) }.to raise_error(Bundler::InvalidOption)
end end
context "default hosts", :bundler => "< 3" do context "default hosts", :bundler => "2" do
it "converts :github to URI using https" do it "converts :github to URI using https" do
subject.gem("sparks", :github => "indirect/sparks") subject.gem("sparks", :github => "indirect/sparks")
github_uri = "https://github.com/indirect/sparks.git" github_uri = "https://github.com/indirect/sparks.git"
@ -195,6 +195,19 @@ RSpec.describe Bundler::Dsl do
# gem 'spree_api' # gem 'spree_api'
# gem 'spree_backend' # gem 'spree_backend'
# end # end
describe "#github", :bundler => "< 3" do
it "from github" do
spree_gems = %w[spree_core spree_api spree_backend]
subject.github "spree" do
spree_gems.each {|spree_gem| subject.send :gem, spree_gem }
end
subject.dependencies.each do |d|
expect(d.source.uri).to eq("https://github.com/spree/spree.git")
end
end
end
describe "#github" do describe "#github" do
it "from github" do it "from github" do
spree_gems = %w[spree_core spree_api spree_backend] spree_gems = %w[spree_core spree_api spree_backend]

View file

@ -112,7 +112,6 @@ RSpec.describe Bundler::Plugin do
before do before do
allow(Plugin::DSL).to receive(:new) { builder } allow(Plugin::DSL).to receive(:new) { builder }
allow(builder).to receive(:eval_gemfile).with(gemfile) allow(builder).to receive(:eval_gemfile).with(gemfile)
allow(builder).to receive(:check_primary_source_safety)
allow(builder).to receive(:to_definition) { definition } allow(builder).to receive(:to_definition) { definition }
allow(builder).to receive(:inferred_plugins) { [] } allow(builder).to receive(:inferred_plugins) { [] }
end end

View file

@ -372,7 +372,26 @@ RSpec.describe Bundler::SourceList do
source_list.add_git_source("uri" => "git://first-git.org/path.git") source_list.add_git_source("uri" => "git://first-git.org/path.git")
end end
it "returns all sources, without combining rubygems sources" do it "combines the rubygems sources into a single instance, removing duplicate remotes from the end", :bundler => "< 3" do
expect(source_list.lock_sources).to eq [
Bundler::Source::Git.new("uri" => "git://first-git.org/path.git"),
Bundler::Source::Git.new("uri" => "git://second-git.org/path.git"),
Bundler::Source::Git.new("uri" => "git://third-git.org/path.git"),
ASourcePlugin.new("uri" => "https://second-plugin.org/random"),
ASourcePlugin.new("uri" => "https://third-bar.org/foo"),
Bundler::Source::Path.new("path" => "/first/path/to/gem"),
Bundler::Source::Path.new("path" => "/second/path/to/gem"),
Bundler::Source::Path.new("path" => "/third/path/to/gem"),
Bundler::Source::Rubygems.new("remotes" => [
"https://duplicate-rubygems.org",
"https://first-rubygems.org",
"https://second-rubygems.org",
"https://third-rubygems.org",
]),
]
end
it "returns all sources, without combining rubygems sources", :bundler => "3" do
expect(source_list.lock_sources).to eq [ expect(source_list.lock_sources).to eq [
Bundler::Source::Git.new("uri" => "git://first-git.org/path.git"), Bundler::Source::Git.new("uri" => "git://first-git.org/path.git"),
Bundler::Source::Git.new("uri" => "git://second-git.org/path.git"), Bundler::Source::Git.new("uri" => "git://second-git.org/path.git"),

View file

@ -762,8 +762,7 @@ RSpec.describe "bundle exec" do
let(:exit_code) { Bundler::GemNotFound.new.status_code } let(:exit_code) { Bundler::GemNotFound.new.status_code }
let(:expected) { "" } let(:expected) { "" }
let(:expected_err) { <<-EOS.strip } let(:expected_err) { <<-EOS.strip }
\e[31mCould not find gem 'rack (= 2)' in locally installed gems. \e[31mCould not find gem 'rack (= 2)' in any of the gem sources listed in your Gemfile.\e[0m
The source contains the following versions of 'rack': 0.9.1, 1.0.0\e[0m
\e[33mRun `bundle install` to install missing gems.\e[0m \e[33mRun `bundle install` to install missing gems.\e[0m
EOS EOS

View file

@ -113,7 +113,16 @@ RSpec.describe "post bundle message" do
bundle "config set force_ruby_platform true" bundle "config set force_ruby_platform true"
end end
it "should report a helpful error message" do it "should report a helpful error message", :bundler => "< 3" do
install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo1)}"
gem "rack"
gem "not-a-gem", :group => :development
G
expect(err).to include("Could not find gem 'not-a-gem' in any of the gem sources listed in your Gemfile.")
end
it "should report a helpful error message", :bundler => "3" do
install_gemfile <<-G, :raise_on_error => false install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo1)}" source "#{file_uri_for(gem_repo1)}"
gem "rack" gem "rack"

View file

@ -422,13 +422,14 @@ RSpec.describe "bundle install from an existing gemspec" do
end end
end end
gemfile <<-G %w[ruby jruby].each do |platform|
simulate_platform(platform) do
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}" source "#{file_uri_for(gem_repo2)}"
gemspec gemspec
G G
end
simulate_platform("ruby") { bundle "install" } end
simulate_platform("jruby") { bundle "install" }
end end
context "on ruby" do context "on ruby" do

View file

@ -27,7 +27,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
G G
end end
it "warns about ambiguous gems, but installs anyway, prioritizing sources last to first", :bundler => "< 3" do it "warns about ambiguous gems, but installs anyway, prioritizing sources last to first", :bundler => "2" do
bundle :install bundle :install
expect(err).to include("Warning: the gem 'rack' was found in multiple sources.") expect(err).to include("Warning: the gem 'rack' was found in multiple sources.")
@ -54,7 +54,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
G G
end end
it "warns about ambiguous gems, but installs anyway", :bundler => "< 3" do it "warns about ambiguous gems, but installs anyway", :bundler => "2" do
bundle :install bundle :install
expect(err).to include("Warning: the gem 'rack' was found in multiple sources.") 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: #{file_uri_for(gem_repo1)}")
@ -96,7 +96,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
it "installs the gems without any warning" do it "installs the gems without any warning" do
bundle :install bundle :install
expect(err).not_to include("Warning") expect(out).not_to include("Warning")
expect(the_bundle).to include_gems("rack-obama 1.0.0") expect(the_bundle).to include_gems("rack-obama 1.0.0")
expect(the_bundle).to include_gems("rack 1.0.0", :source => "remote1") expect(the_bundle).to include_gems("rack 1.0.0", :source => "remote1")
end end
@ -128,7 +128,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
end end
end end
install_gemfile <<-G gemfile <<-G
source "#{file_uri_for(gem_repo3)}" source "#{file_uri_for(gem_repo3)}"
gem "rack-obama" # should come from repo3! gem "rack-obama" # should come from repo3!
gem "rack", :source => "#{file_uri_for(gem_repo1)}" gem "rack", :source => "#{file_uri_for(gem_repo1)}"
@ -136,7 +136,8 @@ RSpec.describe "bundle install with gems on multiple sources" do
end end
it "installs the gems without any warning" do it "installs the gems without any warning" do
expect(err).not_to include("Warning") bundle :install
expect(out).not_to include("Warning")
expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0") expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0")
end end
end end
@ -172,8 +173,8 @@ RSpec.describe "bundle install with gems on multiple sources" do
it "installs from the same source without any warning" do it "installs from the same source without any warning" do
bundle :install bundle :install
expect(err).not_to include("Warning") expect(out).not_to include("Warning")
expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3") expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
end end
end end
@ -187,38 +188,27 @@ RSpec.describe "bundle install with gems on multiple sources" do
end end
end end
context "when disable_multisource is set" do
before do
bundle "config set disable_multisource true"
end
it "installs from the same source without any warning" do it "installs from the same source without any warning" do
bundle :install bundle :install
expect(out).not_to include("Warning: the gem 'rack' was found in multiple sources.")
expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") 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") expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
# 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 # when there is already a lock file, and the gems are missing, so try again
system_gems [] system_gems []
bundle :install bundle :install
expect(out).not_to include("Warning: the gem 'rack' was found in multiple sources.")
expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") 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") expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
end end
end end
context "and in another source with a higher version" do
before do
# need this to be broken to check for correct source ordering
build_repo gem_repo2 do
build_gem "rack", "1.0.1" do |s|
s.write "lib/rack.rb", "RACK = 'FAIL'"
end
end
end
it "installs from the same source without any warning" do
bundle :install
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")
end
end end
end end
@ -232,7 +222,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
context "and not in any other sources" do context "and not in any other sources" do
before do before do
install_gemfile <<-G gemfile <<-G
source "#{file_uri_for(gem_repo2)}" source "#{file_uri_for(gem_repo2)}"
source "#{file_uri_for(gem_repo3)}" do source "#{file_uri_for(gem_repo3)}" do
gem "depends_on_rack" gem "depends_on_rack"
@ -241,7 +231,8 @@ RSpec.describe "bundle install with gems on multiple sources" do
end end
it "installs from the other source without any warning" do it "installs from the other source without any warning" do
expect(err).not_to include("Warning") bundle :install
expect(out).not_to include("Warning")
expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0") expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
end end
end end
@ -257,7 +248,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
G G
end end
it "installs from the other source and warns about ambiguous gems", :bundler => "< 3" do it "installs from the other source and warns about ambiguous gems", :bundler => "2" do
bundle :install bundle :install
expect(err).to include("Warning: the gem 'rack' was found in multiple sources.") 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: #{file_uri_for(gem_repo2)}")
@ -289,7 +280,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
G G
end end
it "installs the dependency from the pinned source without warning", :bundler => "< 3" do it "installs the dependency from the pinned source without warning", :bundler => "2" do
bundle :install bundle :install
expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.")
@ -314,6 +305,11 @@ RSpec.describe "bundle install with gems on multiple sources" do
end end
context "when a top-level gem has an indirect dependency" do 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"
end
before do before do
build_repo gem_repo2 do build_repo gem_repo2 do
build_gem "depends_on_rack", "1.0.1" do |s| build_gem "depends_on_rack", "1.0.1" do |s|
@ -385,6 +381,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
end end
end end
end end
end
context "with a gem that is only found in the wrong source" do context "with a gem that is only found in the wrong source" do
before do before do
@ -392,14 +389,15 @@ RSpec.describe "bundle install with gems on multiple sources" do
build_gem "not_in_repo1", "1.0.0" build_gem "not_in_repo1", "1.0.0"
end end
install_gemfile <<-G, :raise_on_error => false gemfile <<-G
source "#{file_uri_for(gem_repo3)}" source "#{file_uri_for(gem_repo3)}"
gem "not_in_repo1", :source => "#{file_uri_for(gem_repo1)}" gem "not_in_repo1", :source => "#{file_uri_for(gem_repo1)}"
G G
end end
it "does not install the gem" do it "does not install the gem" do
expect(err).to include("Could not find gem 'not_in_repo1") bundle :install, :raise_on_error => false
expect(err).to include("Could not find gem 'not_in_repo1'")
end end
end end
@ -435,92 +433,6 @@ RSpec.describe "bundle install with gems on multiple sources" do
end end
end end
context "with a lockfile with aggregated rubygems sources" do
let(:aggregate_gem_section_lockfile) do
<<~L
GEM
remote: #{file_uri_for(gem_repo1)}/
remote: #{file_uri_for(gem_repo3)}/
specs:
rack (0.9.1)
PLATFORMS
#{specific_local_platform}
DEPENDENCIES
rack!
BUNDLED WITH
#{Bundler::VERSION}
L
end
let(:split_gem_section_lockfile) do
<<~L
GEM
remote: #{file_uri_for(gem_repo1)}/
specs:
GEM
remote: #{file_uri_for(gem_repo3)}/
specs:
rack (0.9.1)
PLATFORMS
#{specific_local_platform}
DEPENDENCIES
rack!
BUNDLED WITH
#{Bundler::VERSION}
L
end
before do
build_repo gem_repo3 do
build_gem "rack", "0.9.1"
end
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
source "#{file_uri_for(gem_repo3)}" do
gem 'rack'
end
G
lockfile aggregate_gem_section_lockfile
end
it "installs a lockfile with separate rubygems source sections if not in frozen mode" do
bundle "install"
expect(lockfile).to eq(split_gem_section_lockfile)
expect(the_bundle).to include_gems("rack 0.9.1", :source => "remote3")
end
it "installs the existing lockfile but prints a warning if in frozen mode", :bundler => "< 3" do
bundle "config set --local deployment true"
bundle "install"
expect(lockfile).to eq(aggregate_gem_section_lockfile)
expect(the_bundle).to include_gems("rack 0.9.1", :source => "remote3")
end
it "refuses to install the existing lockfile and prints an error if in frozen mode", :bundler => "3" do
bundle "config set --local deployment true"
bundle "install", :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 context "with a path gem in the same Gemfile" do
before do before do
build_lib "foo" build_lib "foo"
@ -545,13 +457,14 @@ RSpec.describe "bundle install with gems on multiple sources" do
before do before do
system_gems "rack-0.9.1" system_gems "rack-0.9.1"
install_gemfile <<-G gemfile <<-G
source "#{file_uri_for(gem_repo1)}" source "#{file_uri_for(gem_repo1)}"
gem "rack" # shoud come from repo1! gem "rack" # shoud come from repo1!
G G
end end
it "installs the gems without any warning" do it "installs the gems without any warning" do
bundle :install
expect(err).not_to include("Warning") expect(err).not_to include("Warning")
expect(the_bundle).to include_gems("rack 1.0.0") expect(the_bundle).to include_gems("rack 1.0.0")
end end
@ -702,12 +615,16 @@ RSpec.describe "bundle install with gems on multiple sources" do
G G
end end
it "installs the higher version in the new repo" do it "keeps the old version", :bundler => "2" do
expect(the_bundle).to include_gems("rack 1.0.0")
end
it "installs the higher version in the new repo", :bundler => "3" do
expect(the_bundle).to include_gems("rack 1.2") expect(the_bundle).to include_gems("rack 1.2")
end end
end end
context "when a gem is available from multiple ambiguous sources" do context "when a gem is available from multiple ambiguous sources", :bundler => "3" do
it "raises, suggesting a source block" do it "raises, suggesting a source block" do
build_repo4 do build_repo4 do
build_gem "depends_on_rack" do |s| build_gem "depends_on_rack" do |s|

View file

@ -245,7 +245,37 @@ RSpec.describe "bundle flex_install" do
end end
describe "when adding a new source" do describe "when adding a new source" do
it "updates the lockfile" do it "updates the lockfile", :bundler => "< 3" do
build_repo2
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
source "#{file_uri_for(gem_repo2)}"
gem "rack"
G
lockfile_should_be <<-L
GEM
remote: #{file_uri_for(gem_repo1)}/
remote: #{file_uri_for(gem_repo2)}/
specs:
rack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
rack
BUNDLED WITH
#{Bundler::VERSION}
L
end
it "updates the lockfile", :bundler => "3" do
build_repo2 build_repo2
install_gemfile <<-G install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}" source "#{file_uri_for(gem_repo1)}"

View file

@ -318,7 +318,40 @@ RSpec.describe "the lockfile format" do
G G
end end
it "generates a lockfile without credentials for a configured source" do it "generates a lockfile without credentials for a configured source", :bundler => "< 3" do
bundle "config set http://localgemserver.test/ user:pass"
install_gemfile(<<-G, :artifice => "endpoint_strict_basic_authentication", :quiet => true)
source "http://localgemserver.test/" do
end
source "http://user:pass@othergemserver.test/" do
gem "rack-obama", ">= 1.0"
end
G
lockfile_should_be <<-G
GEM
remote: http://localgemserver.test/
remote: http://user:pass@othergemserver.test/
specs:
rack (1.0.0)
rack-obama (1.0)
rack
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
rack-obama (>= 1.0)!
BUNDLED WITH
#{Bundler::VERSION}
G
end
it "generates a lockfile without credentials for a configured source", :bundler => "3" do
bundle "config set http://localgemserver.test/ user:pass" bundle "config set http://localgemserver.test/ user:pass"
install_gemfile(<<-G, :artifice => "endpoint_strict_basic_authentication", :quiet => true) install_gemfile(<<-G, :artifice => "endpoint_strict_basic_authentication", :quiet => true)

View file

@ -17,7 +17,7 @@ RSpec.describe "major deprecations" do
bundle "exec ruby -e #{source.dump}" bundle "exec ruby -e #{source.dump}"
end end
it "is deprecated in favor of .unbundled_env", :bundler => "< 3" do it "is deprecated in favor of .unbundled_env", :bundler => "2" do
expect(deprecations).to include \ expect(deprecations).to include \
"`Bundler.clean_env` has been deprecated in favor of `Bundler.unbundled_env`. " \ "`Bundler.clean_env` has been deprecated in favor of `Bundler.unbundled_env`. " \
"If you instead want the environment before bundler was originally loaded, use `Bundler.original_env` " \ "If you instead want the environment before bundler was originally loaded, use `Bundler.original_env` " \
@ -33,7 +33,7 @@ RSpec.describe "major deprecations" do
bundle "exec ruby -e #{source.dump}" bundle "exec ruby -e #{source.dump}"
end end
it "is deprecated in favor of .unbundled_env", :bundler => "< 3" do it "is deprecated in favor of .unbundled_env", :bundler => "2" do
expect(deprecations).to include( expect(deprecations).to include(
"`Bundler.with_clean_env` has been deprecated in favor of `Bundler.with_unbundled_env`. " \ "`Bundler.with_clean_env` has been deprecated in favor of `Bundler.with_unbundled_env`. " \
"If you instead want the environment before bundler was originally loaded, use `Bundler.with_original_env` " \ "If you instead want the environment before bundler was originally loaded, use `Bundler.with_original_env` " \
@ -50,7 +50,7 @@ RSpec.describe "major deprecations" do
bundle "exec ruby -e #{source.dump}" bundle "exec ruby -e #{source.dump}"
end end
it "is deprecated in favor of .unbundled_system", :bundler => "< 3" do it "is deprecated in favor of .unbundled_system", :bundler => "2" do
expect(deprecations).to include( expect(deprecations).to include(
"`Bundler.clean_system` has been deprecated in favor of `Bundler.unbundled_system`. " \ "`Bundler.clean_system` has been deprecated in favor of `Bundler.unbundled_system`. " \
"If you instead want to run the command in the environment before bundler was originally loaded, use `Bundler.original_system` " \ "If you instead want to run the command in the environment before bundler was originally loaded, use `Bundler.original_system` " \
@ -67,7 +67,7 @@ RSpec.describe "major deprecations" do
bundle "exec ruby -e #{source.dump}" bundle "exec ruby -e #{source.dump}"
end end
it "is deprecated in favor of .unbundled_exec", :bundler => "< 3" do it "is deprecated in favor of .unbundled_exec", :bundler => "2" do
expect(deprecations).to include( expect(deprecations).to include(
"`Bundler.clean_exec` has been deprecated in favor of `Bundler.unbundled_exec`. " \ "`Bundler.clean_exec` has been deprecated in favor of `Bundler.unbundled_exec`. " \
"If you instead want to exec to a command in the environment before bundler was originally loaded, use `Bundler.original_exec` " \ "If you instead want to exec to a command in the environment before bundler was originally loaded, use `Bundler.original_exec` " \
@ -84,7 +84,7 @@ RSpec.describe "major deprecations" do
bundle "exec ruby -e #{source.dump}" bundle "exec ruby -e #{source.dump}"
end end
it "is deprecated in favor of .load", :bundler => "< 3" do it "is deprecated in favor of .load", :bundler => "2" do
expect(deprecations).to include "Bundler.environment has been removed in favor of Bundler.load (called at -e:1)" expect(deprecations).to include "Bundler.environment has been removed in favor of Bundler.load (called at -e:1)"
end end
@ -109,7 +109,7 @@ RSpec.describe "major deprecations" do
bundle "check --path vendor/bundle", :raise_on_error => false bundle "check --path vendor/bundle", :raise_on_error => false
end end
it "should print a deprecation warning", :bundler => "< 3" do it "should print a deprecation warning", :bundler => "2" do
expect(deprecations).to include( expect(deprecations).to include(
"The `--path` flag is deprecated because it relies on being " \ "The `--path` flag is deprecated because it relies on being " \
"remembered across bundler invocations, which bundler will no " \ "remembered across bundler invocations, which bundler will no " \
@ -118,7 +118,7 @@ RSpec.describe "major deprecations" do
) )
end end
pending "fails with a helpful error", :bundler => "3" pending "should fail with a helpful error", :bundler => "3"
end end
context "bundle check --path=" do context "bundle check --path=" do
@ -131,7 +131,7 @@ RSpec.describe "major deprecations" do
bundle "check --path=vendor/bundle", :raise_on_error => false bundle "check --path=vendor/bundle", :raise_on_error => false
end end
it "should print a deprecation warning", :bundler => "< 3" do it "should print a deprecation warning", :bundler => "2" do
expect(deprecations).to include( expect(deprecations).to include(
"The `--path` flag is deprecated because it relies on being " \ "The `--path` flag is deprecated because it relies on being " \
"remembered across bundler invocations, which bundler will no " \ "remembered across bundler invocations, which bundler will no " \
@ -140,7 +140,7 @@ RSpec.describe "major deprecations" do
) )
end end
pending "fails with a helpful error", :bundler => "3" pending "should fail with a helpful error", :bundler => "3"
end end
context "bundle cache --all" do context "bundle cache --all" do
@ -153,7 +153,7 @@ RSpec.describe "major deprecations" do
bundle "cache --all", :raise_on_error => false bundle "cache --all", :raise_on_error => false
end end
it "should print a deprecation warning", :bundler => "< 3" do it "should print a deprecation warning", :bundler => "2" do
expect(deprecations).to include( expect(deprecations).to include(
"The `--all` flag is deprecated because it relies on being " \ "The `--all` flag is deprecated because it relies on being " \
"remembered across bundler invocations, which bundler will no " \ "remembered across bundler invocations, which bundler will no " \
@ -162,7 +162,7 @@ RSpec.describe "major deprecations" do
) )
end end
pending "fails with a helpful error", :bundler => "3" pending "should fail with a helpful error", :bundler => "3"
end end
describe "bundle config" do describe "bundle config" do
@ -292,7 +292,7 @@ RSpec.describe "major deprecations" do
G G
end end
it "should output a deprecation warning", :bundler => "< 3" do it "should output a deprecation warning", :bundler => "2" do
expect(deprecations).to include("The --binstubs option will be removed in favor of `bundle binstubs --all`") expect(deprecations).to include("The --binstubs option will be removed in favor of `bundle binstubs --all`")
end end
@ -356,7 +356,7 @@ RSpec.describe "major deprecations" do
bundle "install #{flag_name} #{value}" bundle "install #{flag_name} #{value}"
end end
it "should print a deprecation warning", :bundler => "< 3" do it "should print a deprecation warning", :bundler => "2" do
expect(deprecations).to include( expect(deprecations).to include(
"The `#{flag_name}` flag is deprecated because it relies on " \ "The `#{flag_name}` flag is deprecated because it relies on " \
"being remembered across bundler invocations, which bundler " \ "being remembered across bundler invocations, which bundler " \
@ -365,7 +365,7 @@ RSpec.describe "major deprecations" do
) )
end end
pending "fails with a helpful error", :bundler => "3" pending "should fail with a helpful error", :bundler => "3"
end end
end end
end end
@ -378,58 +378,18 @@ RSpec.describe "major deprecations" do
G G
end end
it "shows a deprecation", :bundler => "< 3" do it "shows a deprecation", :bundler => "2" do
expect(deprecations).to include( expect(deprecations).to include(
"Your Gemfile contains multiple primary sources. " \ "Your Gemfile contains multiple primary sources. " \
"Using `source` more than once without a block is a security risk, and " \ "Using `source` more than once without a block is a security risk, and " \
"may result in installing unexpected gems. To resolve this warning, use " \ "may result in installing unexpected gems. To resolve this warning, use " \
"a block to indicate which gems should come from the secondary source." "a block to indicate which gems should come from the secondary source. " \
"To upgrade this warning to an error, run `bundle config set --local " \
"disable_multisource true`."
) )
end end
pending "fails with a helpful error", :bundler => "3" pending "should fail with a helpful error", :bundler => "3"
end
context "bundle install with a lockfile with a single rubygems section with multiple remotes in frozen mode" do
before do
build_repo gem_repo3 do
build_gem "rack", "0.9.1"
end
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
source "#{file_uri_for(gem_repo3)}" do
gem 'rack'
end
G
lockfile <<~L
GEM
remote: #{file_uri_for(gem_repo1)}/
remote: #{file_uri_for(gem_repo3)}/
specs:
rack (0.9.1)
PLATFORMS
ruby
DEPENDENCIES
rack!
BUNDLED WITH
#{Bundler::VERSION}
L
bundle "config set --local deployment 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 regenerate your lockfile in a non frozen environment.")
end
pending "fails with a helpful error", :bundler => "3"
end end
context "when Bundler.setup is run in a ruby script" do context "when Bundler.setup is run in a ruby script" do
@ -462,14 +422,14 @@ RSpec.describe "major deprecations" do
RUBY RUBY
end end
it "should print a capistrano deprecation warning", :bundler => "< 3" do it "should print a capistrano deprecation warning", :bundler => "2" do
expect(deprecations).to include("Bundler no longer integrates " \ expect(deprecations).to include("Bundler no longer integrates " \
"with Capistrano, but Capistrano provides " \ "with Capistrano, but Capistrano provides " \
"its own integration with Bundler via the " \ "its own integration with Bundler via the " \
"capistrano-bundler gem. Use it instead.") "capistrano-bundler gem. Use it instead.")
end end
pending "fails with a helpful error", :bundler => "3" pending "should fail with a helpful error", :bundler => "3"
end end
describe Bundler::Dsl do describe Bundler::Dsl do
@ -479,7 +439,7 @@ RSpec.describe "major deprecations" do
end end
context "with github gems" do context "with github gems" do
it "does not warn about removal", :bundler => "< 3" do it "does not warn about removal", :bundler => "2" do
expect(Bundler.ui).not_to receive(:warn) expect(Bundler.ui).not_to receive(:warn)
subject.gem("sparks", :github => "indirect/sparks") subject.gem("sparks", :github => "indirect/sparks")
github_uri = "https://github.com/indirect/sparks.git" github_uri = "https://github.com/indirect/sparks.git"
@ -501,7 +461,7 @@ The :github git source is deprecated, and will be removed in the future. Change
end end
context "with bitbucket gems" do context "with bitbucket gems" do
it "does not warn about removal", :bundler => "< 3" do it "does not warn about removal", :bundler => "2" do
expect(Bundler.ui).not_to receive(:warn) expect(Bundler.ui).not_to receive(:warn)
subject.gem("not-really-a-gem", :bitbucket => "mcorp/flatlab-rails") subject.gem("not-really-a-gem", :bitbucket => "mcorp/flatlab-rails")
end end
@ -523,7 +483,7 @@ The :bitbucket git source is deprecated, and will be removed in the future. Add
end end
context "with gist gems" do context "with gist gems" do
it "does not warn about removal", :bundler => "< 3" do it "does not warn about removal", :bundler => "2" do
expect(Bundler.ui).not_to receive(:warn) expect(Bundler.ui).not_to receive(:warn)
subject.gem("not-really-a-gem", :gist => "1234") subject.gem("not-really-a-gem", :gist => "1234")
end end
@ -554,7 +514,7 @@ The :gist git source is deprecated, and will be removed in the future. Add this
bundle :show bundle :show
end end
it "prints a deprecation warning recommending `bundle list`", :bundler => "< 3" do it "prints a deprecation warning recommending `bundle list`", :bundler => "2" do
expect(deprecations).to include("use `bundle list` instead of `bundle show`") expect(deprecations).to include("use `bundle list` instead of `bundle show`")
end end
@ -566,7 +526,7 @@ The :gist git source is deprecated, and will be removed in the future. Add this
bundle "show --outdated" bundle "show --outdated"
end end
it "prints a deprecation warning informing about its removal", :bundler => "< 3" do it "prints a deprecation warning informing about its removal", :bundler => "2" do
expect(deprecations).to include("the `--outdated` flag to `bundle show` was undocumented and will be removed without replacement") expect(deprecations).to include("the `--outdated` flag to `bundle show` was undocumented and will be removed without replacement")
end end
@ -578,7 +538,7 @@ The :gist git source is deprecated, and will be removed in the future. Add this
bundle "show --verbose" bundle "show --verbose"
end end
it "prints a deprecation warning informing about its removal", :bundler => "< 3" do it "prints a deprecation warning informing about its removal", :bundler => "2" do
expect(deprecations).to include("the `--verbose` flag to `bundle show` was undocumented and will be removed without replacement") expect(deprecations).to include("the `--verbose` flag to `bundle show` was undocumented and will be removed without replacement")
end end
@ -590,7 +550,7 @@ The :gist git source is deprecated, and will be removed in the future. Add this
bundle "show rack" bundle "show rack"
end end
it "prints a deprecation warning recommending `bundle info`", :bundler => "< 3" do it "prints a deprecation warning recommending `bundle info`", :bundler => "2" do
expect(deprecations).to include("use `bundle info rack` instead of `bundle show rack`") expect(deprecations).to include("use `bundle info rack` instead of `bundle show rack`")
end end
@ -602,7 +562,7 @@ The :gist git source is deprecated, and will be removed in the future. Add this
bundle "show --paths" bundle "show --paths"
end end
it "prints a deprecation warning recommending `bundle list`", :bundler => "< 3" do it "prints a deprecation warning recommending `bundle list`", :bundler => "2" do
expect(deprecations).to include("use `bundle list` instead of `bundle show --paths`") expect(deprecations).to include("use `bundle list` instead of `bundle show --paths`")
end end
@ -614,7 +574,7 @@ The :gist git source is deprecated, and will be removed in the future. Add this
bundle "show rack --paths" bundle "show rack --paths"
end end
it "prints deprecation warning recommending `bundle info`", :bundler => "< 3" do it "prints deprecation warning recommending `bundle info`", :bundler => "2" do
expect(deprecations).to include("use `bundle info rack --path` instead of `bundle show rack --paths`") expect(deprecations).to include("use `bundle info rack --path` instead of `bundle show rack --paths`")
end end
@ -627,7 +587,7 @@ The :gist git source is deprecated, and will be removed in the future. Add this
bundle "console", :raise_on_error => false bundle "console", :raise_on_error => false
end end
it "prints a deprecation warning", :bundler => "< 3" do it "prints a deprecation warning", :bundler => "2" do
expect(deprecations).to include \ expect(deprecations).to include \
"bundle console will be replaced by `bin/console` generated by `bundle gem <name>`" "bundle console will be replaced by `bin/console` generated by `bundle gem <name>`"
end end
@ -643,7 +603,7 @@ The :gist git source is deprecated, and will be removed in the future. Add this
bundle "viz" bundle "viz"
end end
it "prints a deprecation warning", :bundler => "< 3" do it "prints a deprecation warning", :bundler => "2" do
expect(deprecations).to include "The `viz` command has been moved to the `bundle-viz` gem, see https://github.com/bundler/bundler-viz" expect(deprecations).to include "The `viz` command has been moved to the `bundle-viz` gem, see https://github.com/bundler/bundler-viz"
end end

View file

@ -30,7 +30,7 @@ module Spec
args[1] ||= Bundler::GemVersionPromoter.new # gem_version_promoter args[1] ||= Bundler::GemVersionPromoter.new # gem_version_promoter
args[2] ||= [] # additional_base_requirements args[2] ||= [] # additional_base_requirements
args[3] ||= @platforms # platforms args[3] ||= @platforms # platforms
Bundler::Resolver.resolve(deps, source_requirements, *args) Bundler::Resolver.resolve(deps, @index, source_requirements, *args)
end end
def should_resolve_as(specs) def should_resolve_as(specs)

View file

@ -1958,9 +1958,15 @@ class TestGem < Gem::TestCase
io.write 'gem "a"' io.write 'gem "a"'
end end
platform = Bundler::GemHelpers.generic_local_platform
if platform == Gem::Platform::RUBY
platform = ''
else
platform = " #{platform}"
end
expected = <<-EXPECTED expected = <<-EXPECTED
Could not find gem 'a' in locally installed gems. Could not find gem 'a#{platform}' in any of the gem sources listed in your Gemfile.
The source does not contain any versions of 'a'
You may need to `gem install -g` to install missing gems You may need to `gem install -g` to install missing gems
EXPECTED EXPECTED

View file

@ -41,6 +41,7 @@ class TestGemConfigFile < Gem::TestCase
assert_equal true, @cfg.verbose assert_equal true, @cfg.verbose
assert_equal [@gem_repo], Gem.sources assert_equal [@gem_repo], Gem.sources
assert_equal 365, @cfg.cert_expiration_length_days assert_equal 365, @cfg.cert_expiration_length_days
assert_equal false, @cfg.ipv4_fallback_enabled
File.open @temp_conf, 'w' do |fp| File.open @temp_conf, 'w' do |fp|
fp.puts ":backtrace: true" fp.puts ":backtrace: true"
@ -56,6 +57,7 @@ class TestGemConfigFile < Gem::TestCase
fp.puts ":ssl_verify_mode: 0" fp.puts ":ssl_verify_mode: 0"
fp.puts ":ssl_ca_cert: /etc/ssl/certs" fp.puts ":ssl_ca_cert: /etc/ssl/certs"
fp.puts ":cert_expiration_length_days: 28" fp.puts ":cert_expiration_length_days: 28"
fp.puts ":ipv4_fallback_enabled: true"
end end
util_config_file util_config_file
@ -70,6 +72,14 @@ class TestGemConfigFile < Gem::TestCase
assert_equal 0, @cfg.ssl_verify_mode assert_equal 0, @cfg.ssl_verify_mode
assert_equal '/etc/ssl/certs', @cfg.ssl_ca_cert assert_equal '/etc/ssl/certs', @cfg.ssl_ca_cert
assert_equal 28, @cfg.cert_expiration_length_days assert_equal 28, @cfg.cert_expiration_length_days
assert_equal true, @cfg.ipv4_fallback_enabled
end
def test_initialize_ipv4_fallback_enabled_env
ENV['IPV4_FALLBACK_ENABLED'] = 'true'
util_config_file %W[--config-file #{@temp_conf}]
assert_equal true, @cfg.ipv4_fallback_enabled
end end
def test_initialize_handle_arguments_config_file def test_initialize_handle_arguments_config_file

View file

@ -962,6 +962,12 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
end end
end end
def test_tcpsocketext_require
with_configured_fetcher(":ipv4_fallback_enabled: true") do |fetcher|
refute require('rubygems/core_ext/tcpsocket_init')
end
end
def with_configured_fetcher(config_str = nil, &block) def with_configured_fetcher(config_str = nil, &block)
if config_str if config_str
temp_conf = File.join @tempdir, '.gemrc' temp_conf = File.join @tempdir, '.gemrc'