@@ -106,6 +106,19 @@ def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil, opti
106106 @locked_platforms = [ ]
107107 end
108108
109+ @locked_gem_sources = @locked_sources . select { |s | s . is_a? ( Source ::Rubygems ) }
110+ @disable_multisource = !Bundler . frozen_bundle? || @locked_gem_sources . none? { |s | s . remotes . size > 1 }
111+
112+ unless @disable_multisource
113+ msg = "Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. " \
114+ "You should regenerate your lockfile in a non frozen environment."
115+
116+ Bundler ::SharedHelpers . major_deprecation 2 , msg
117+
118+ @sources . allow_multisource!
119+ @locked_gem_sources . each ( &:allow_multisource! )
120+ end
121+
109122 @unlock [ :gems ] ||= [ ]
110123 @unlock [ :sources ] ||= [ ]
111124 @unlock [ :ruby ] ||= if @ruby_version && locked_ruby_version_object
@@ -145,6 +158,14 @@ def gem_version_promoter
145158 end
146159 end
147160
161+ def disable_multisource?
162+ @disable_multisource
163+ end
164+
165+ def allow_multisource!
166+ @disable_multisource = false
167+ end
168+
148169 def resolve_with_cache!
149170 raise "Specs already loaded" if @specs
150171 sources . cached!
@@ -264,7 +285,7 @@ def resolve
264285 # Run a resolve against the locally available gems
265286 Bundler . ui . debug ( "Found changes from the lockfile, re-resolving dependencies because #{ change_reason } " )
266287 expanded_dependencies = expand_dependencies ( dependencies + metadata_dependencies , @remote )
267- Resolver . resolve ( expanded_dependencies , index , source_requirements , last_resolve , gem_version_promoter , additional_base_requirements_for_resolve , platforms )
288+ Resolver . resolve ( expanded_dependencies , source_requirements , last_resolve , gem_version_promoter , additional_base_requirements_for_resolve , platforms )
268289 end
269290 end
270291 end
@@ -530,6 +551,9 @@ def find_indexed_specs(current_spec)
530551 attr_reader :sources
531552 private :sources
532553
554+ attr_reader :locked_gem_sources
555+ private :locked_gem_sources
556+
533557 def nothing_changed?
534558 !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes && !@locked_specs_incomplete_for_platform
535559 end
@@ -654,21 +678,20 @@ def converge_path_sources_to_gemspec_sources
654678 end
655679
656680 def converge_rubygems_sources
657- return false if Bundler . feature_flag . disable_multisource?
681+ return false if disable_multisource?
658682
659- changes = false
683+ return false if locked_gem_sources . empty?
660684
661- # Get the RubyGems sources from the Gemfile.lock
662- locked_gem_sources = @locked_sources . select { |s | s . is_a? ( Source ::Rubygems ) }
663685 # Get the RubyGems remotes from the Gemfile
664686 actual_remotes = sources . rubygems_remotes
687+ return false if actual_remotes . empty?
688+
689+ changes = false
665690
666691 # If there is a RubyGems source in both
667- if !locked_gem_sources . empty? && !actual_remotes . empty?
668- locked_gem_sources . each do |locked_gem |
669- # Merge the remotes from the Gemfile into the Gemfile.lock
670- changes |= locked_gem . replace_remotes ( actual_remotes , Bundler . settings [ :allow_deployment_source_credential_changes ] )
671- end
692+ locked_gem_sources . each do |locked_gem |
693+ # Merge the remotes from the Gemfile into the Gemfile.lock
694+ changes |= locked_gem . replace_remotes ( actual_remotes , Bundler . settings [ :allow_deployment_source_credential_changes ] )
672695 end
673696
674697 changes
@@ -893,30 +916,18 @@ def source_requirements
893916 # Record the specs available in each gem's source, so that those
894917 # specs will be available later when the resolver knows where to
895918 # look for that gemspec (or its dependencies)
896- default = sources . default_source
897- source_requirements = { :default => default }
898- default = nil unless Bundler . feature_flag . disable_multisource?
899- dependencies . each do |dep |
900- next unless source = dep . source || default
901- source_requirements [ dep . name ] = source
902- end
919+ source_requirements = { :default => sources . default_source } . merge ( dependency_source_requirements )
903920 metadata_dependencies . each do |dep |
904921 source_requirements [ dep . name ] = sources . metadata_source
905922 end
923+ source_requirements [ :global ] = index unless disable_multisource?
906924 source_requirements [ :default_bundler ] = source_requirements [ "bundler" ] || source_requirements [ :default ]
907925 source_requirements [ "bundler" ] = sources . metadata_source # needs to come last to override
908926 source_requirements
909927 end
910928
911929 def pinned_spec_names ( skip = nil )
912- pinned_names = [ ]
913- default = Bundler . feature_flag . disable_multisource? && sources . default_source
914- @dependencies . each do |dep |
915- next unless dep_source = dep . source || default
916- next if dep_source == skip
917- pinned_names << dep . name
918- end
919- pinned_names
930+ dependency_source_requirements . reject { |_ , source | source == skip } . keys
920931 end
921932
922933 def requested_groups
@@ -973,5 +984,18 @@ def equivalent_rubygems_remotes?(source)
973984
974985 Bundler . settings [ :allow_deployment_source_credential_changes ] && source . equivalent_remotes? ( sources . rubygems_remotes )
975986 end
987+
988+ def dependency_source_requirements
989+ @dependency_source_requirements ||= begin
990+ source_requirements = { }
991+ default = disable_multisource? && sources . default_source
992+ dependencies . each do |dep |
993+ dep_source = dep . source || default
994+ next unless dep_source
995+ source_requirements [ dep . name ] = dep_source
996+ end
997+ source_requirements
998+ end
999+ end
9761000 end
9771001end
0 commit comments