Skip to content

Commit a3d3df0

Browse files
Merge pull request #8968 from rubygems/deivid-rodriguez/remove-global-multisource-support
Remove support for multiple global sources in Gemfile & lockfile
2 parents ad92aba + 6439b89 commit a3d3df0

19 files changed

Lines changed: 100 additions & 1377 deletions

bundler/lib/bundler/cli/install.rb

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,6 @@ def run
6969

7070
Bundler::CLI::Common.output_post_install_messages installer.post_install_messages
7171

72-
warn_ambiguous_gems
73-
7472
if CLI::Common.clean_after_install?
7573
require_relative "clean"
7674
Bundler::CLI::Clean.new(options).run
@@ -126,19 +124,5 @@ def normalize_settings
126124

127125
options[:force] = options[:redownload] if options[:redownload]
128126
end
129-
130-
def warn_ambiguous_gems
131-
# TODO: remove this when we drop Bundler 1.x support
132-
Installer.ambiguous_gems.to_a.each do |name, installed_from_uri, *also_found_in_uris|
133-
Bundler.ui.warn "Warning: the gem '#{name}' was found in multiple sources."
134-
Bundler.ui.warn "Installed from: #{installed_from_uri}"
135-
Bundler.ui.warn "Also found in:"
136-
also_found_in_uris.each {|uri| Bundler.ui.warn " * #{uri}" }
137-
Bundler.ui.warn "You should add a source requirement to restrict this gem to your preferred source."
138-
Bundler.ui.warn "For example:"
139-
Bundler.ui.warn " gem '#{name}', :source => '#{installed_from_uri}'"
140-
Bundler.ui.warn "Then uninstall the gem '#{name}' (or delete all bundled gems) and then install again."
141-
end
142-
end
143127
end
144128
end

bundler/lib/bundler/definition.rb

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,24 @@ def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil, opti
107107
@locked_ruby_version = @locked_gems.ruby_version
108108
@locked_deps = @locked_gems.dependencies
109109
@originally_locked_specs = SpecSet.new(@locked_gems.specs)
110+
@originally_locked_sources = @locked_gems.sources
110111
@locked_checksums = @locked_gems.checksums
111112

112113
if @unlocking_all
113114
@locked_specs = SpecSet.new([])
114115
@locked_sources = []
115116
else
116117
@locked_specs = @originally_locked_specs
117-
@locked_sources = @locked_gems.sources
118+
@locked_sources = @originally_locked_sources
119+
end
120+
121+
locked_gem_sources = @originally_locked_sources.select {|s| s.is_a?(Source::Rubygems) }
122+
multisource_lockfile = locked_gem_sources.size == 1 && locked_gem_sources.first.multiple_remotes?
123+
124+
if multisource_lockfile
125+
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."
126+
127+
Bundler::SharedHelpers.feature_removed! msg
118128
end
119129
else
120130
@locked_gems = nil
@@ -123,24 +133,12 @@ def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil, opti
123133
@platforms = []
124134
@locked_deps = {}
125135
@locked_specs = SpecSet.new([])
126-
@originally_locked_specs = @locked_specs
127136
@locked_sources = []
137+
@originally_locked_specs = @locked_specs
138+
@originally_locked_sources = @locked_sources
128139
@locked_checksums = Bundler.feature_flag.lockfile_checksums?
129140
end
130141

131-
locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
132-
@multisource_allowed = locked_gem_sources.size == 1 && locked_gem_sources.first.multiple_remotes? && Bundler.frozen_bundle?
133-
134-
if @multisource_allowed
135-
unless sources.aggregate_global_source?
136-
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."
137-
138-
Bundler::SharedHelpers.major_deprecation 2, msg
139-
end
140-
141-
@sources.merged_gem_lockfile_sections!(locked_gem_sources.first)
142-
end
143-
144142
@unlocking_ruby ||= if @ruby_version && locked_ruby_version_object
145143
@ruby_version.diff(locked_ruby_version_object)
146144
end
@@ -763,7 +761,7 @@ def start_resolution
763761
end
764762

765763
def precompute_source_requirements_for_indirect_dependencies?
766-
sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && !sources.aggregate_global_source?
764+
sources.non_global_rubygems_sources.all?(&:dependency_api_available?)
767765
end
768766

769767
def current_platform_locked?
@@ -954,7 +952,7 @@ def converge_sources
954952
sources.all_sources.each do |source|
955953
# has to be done separately, because we want to keep the locked checksum
956954
# store for a source, even when doing a full update
957-
if @locked_checksums && @locked_gems && locked_source = @locked_gems.sources.find {|s| s == source && !s.equal?(source) }
955+
if @locked_checksums && @locked_gems && locked_source = @originally_locked_sources.find {|s| s == source && !s.equal?(source) }
958956
source.checksum_store.merge!(locked_source.checksum_store)
959957
end
960958
# If the source is unlockable and the current command allows an unlock of
@@ -1137,7 +1135,7 @@ def lockfiles_equal?(current, proposed, preserve_unknown_sections)
11371135
end
11381136

11391137
def additional_base_requirements_to_prevent_downgrades(resolution_base)
1140-
return resolution_base unless @locked_gems && !sources.expired_sources?(@locked_gems.sources)
1138+
return resolution_base unless @locked_gems
11411139
@originally_locked_specs.each do |locked_spec|
11421140
next if locked_spec.source.is_a?(Source::Path) || locked_spec.source_changed?
11431141

bundler/lib/bundler/dsl.rb

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -521,24 +521,10 @@ def check_rubygems_source_safety
521521
end
522522

523523
def multiple_global_source_warning
524-
if Bundler.feature_flag.bundler_4_mode?
525-
msg = "This Gemfile contains multiple global sources. " \
526-
"Each source after the first must include a block to indicate which gems " \
527-
"should come from that source"
528-
raise GemfileEvalError, msg
529-
else
530-
message =
531-
"Your Gemfile contains multiple global sources. " \
532-
"Using `source` more than once without a block is a security risk, and " \
533-
"may result in installing unexpected gems. To resolve this warning, use " \
534-
"a block to indicate which gems should come from the secondary source."
535-
removed_message =
536-
"Your Gemfile contains multiple global sources. " \
537-
"Using `source` more than once without a block is a security risk, and " \
538-
"may result in installing unexpected gems. To resolve this error, use " \
539-
"a block to indicate which gems should come from the secondary source."
540-
Bundler::SharedHelpers.major_deprecation 2, message, removed_message: removed_message
541-
end
524+
msg = "This Gemfile contains multiple global sources. " \
525+
"Each source after the first must include a block to indicate which gems " \
526+
"should come from that source"
527+
raise GemfileEvalError, msg
542528
end
543529

544530
class DSLError < GemfileError

bundler/lib/bundler/errors.rb

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,6 @@ def message
7777
def mismatch_resolution_instructions
7878
removable, remote = [@existing, @checksum].partition(&:removable?)
7979
case removable.size
80-
when 0
81-
msg = +"Mismatched checksums each have an authoritative source:\n"
82-
msg << " 1. #{@existing.sources.reject(&:removable?).map(&:to_s).join(" and ")}\n"
83-
msg << " 2. #{@checksum.sources.reject(&:removable?).map(&:to_s).join(" and ")}\n"
84-
msg << "You may need to alter your Gemfile sources to resolve this issue.\n"
8580
when 1
8681
msg = +"If you trust #{remote.first.sources.first}, to resolve this issue you can:\n"
8782
msg << removable.first.removal_instructions

bundler/lib/bundler/index.rb

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,6 @@ def empty?
4646
true
4747
end
4848

49-
def search_all(name, &blk)
50-
return enum_for(:search_all, name) unless blk
51-
specs_by_name(name).each(&blk)
52-
@duplicates[name]&.each(&blk)
53-
@sources.each {|source| source.search_all(name, &blk) }
54-
end
55-
5649
# Search this index's specs, and any source indexes that this index knows
5750
# about, returning all of the results.
5851
def search(query)

bundler/lib/bundler/installer.rb

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,6 @@
77

88
module Bundler
99
class Installer
10-
class << self
11-
attr_accessor :ambiguous_gems
12-
13-
Installer.ambiguous_gems = []
14-
end
15-
1610
attr_reader :post_install_messages, :definition
1711

1812
# Begins the installation process for Bundler.

bundler/lib/bundler/plugin/source_list.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def all_sources
2323

2424
private
2525

26-
def rubygems_aggregate_class
26+
def source_class
2727
Plugin::Installer::Rubygems
2828
end
2929
end

bundler/lib/bundler/source/rubygems.rb

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -168,12 +168,6 @@ def install(spec, options = {})
168168
return nil # no post-install message
169169
end
170170

171-
if spec.remote
172-
# Check for this spec from other sources
173-
uris = [spec.remote, *remotes_for_spec(spec)].map(&:anonymized_uri).uniq
174-
Installer.ambiguous_gems << [spec.name, *uris] if uris.length > 1
175-
end
176-
177171
path = fetch_gem_if_possible(spec, options[:previous_spec])
178172
raise GemNotFound, "Could not find #{spec.file_name} for installation" unless path
179173

@@ -332,13 +326,6 @@ def credless_remotes
332326
remotes.map(&method(:remove_auth))
333327
end
334328

335-
def remotes_for_spec(spec)
336-
specs.search_all(spec.name).inject([]) do |uris, s|
337-
uris << s.remote if s.remote
338-
uris
339-
end
340-
end
341-
342329
def cached_gem(spec)
343330
global_cache_path = download_cache_path(spec)
344331
caches << global_cache_path if global_cache_path

bundler/lib/bundler/source_list.rb

Lines changed: 4 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class SourceList
99
:metadata_source
1010

1111
def global_rubygems_source
12-
@global_rubygems_source ||= rubygems_aggregate_class.new("allow_local" => true)
12+
@global_rubygems_source ||= source_class.new("allow_local" => true)
1313
end
1414

1515
def initialize
@@ -21,19 +21,9 @@ def initialize
2121
@rubygems_sources = []
2222
@metadata_source = Source::Metadata.new
2323

24-
@merged_gem_lockfile_sections = false
2524
@local_mode = true
2625
end
2726

28-
def merged_gem_lockfile_sections?
29-
@merged_gem_lockfile_sections
30-
end
31-
32-
def merged_gem_lockfile_sections!(replacement_source)
33-
@merged_gem_lockfile_sections = true
34-
@global_rubygems_source = replacement_source
35-
end
36-
3727
def aggregate_global_source?
3828
global_rubygems_source.multiple_remotes?
3929
end
@@ -90,10 +80,6 @@ def non_global_rubygems_sources
9080
@rubygems_sources
9181
end
9282

93-
def rubygems_remotes
94-
rubygems_sources.flat_map(&:remotes).uniq
95-
end
96-
9783
def all_sources
9884
path_sources + git_sources + plugin_sources + rubygems_sources + [metadata_source]
9985
end
@@ -115,11 +101,7 @@ def lock_other_sources
115101
end
116102

117103
def lock_rubygems_sources
118-
if merged_gem_lockfile_sections?
119-
[combine_rubygems_sources]
120-
else
121-
rubygems_sources.sort_by(&:identifier)
122-
end
104+
rubygems_sources.sort_by(&:identifier)
123105
end
124106

125107
# Returns true if there are changes
@@ -129,16 +111,7 @@ def replace_sources!(replacement_sources)
129111
@rubygems_sources, @path_sources, @git_sources, @plugin_sources = map_sources(replacement_sources)
130112
@global_rubygems_source = global_replacement_source(replacement_sources)
131113

132-
different_sources?(lock_sources, replacement_sources)
133-
end
134-
135-
# Returns true if there are changes
136-
def expired_sources?(replacement_sources)
137-
return false if replacement_sources.empty?
138-
139-
lock_sources = dup_with_replaced_sources(replacement_sources).lock_sources
140-
141-
different_sources?(lock_sources, replacement_sources)
114+
!equivalent_sources?(lock_sources, replacement_sources)
142115
end
143116

144117
def prefer_local!
@@ -165,12 +138,6 @@ def remote!
165138

166139
private
167140

168-
def dup_with_replaced_sources(replacement_sources)
169-
new_source_list = dup
170-
new_source_list.replace_sources!(replacement_sources)
171-
new_source_list
172-
end
173-
174141
def map_sources(replacement_sources)
175142
rubygems = @rubygems_sources.map do |source|
176143
replace_rubygems_source(replacement_sources, source)
@@ -224,11 +191,7 @@ def replace_path_source(replacement_sources, gemfile_source)
224191
end
225192
end
226193

227-
def different_sources?(lock_sources, replacement_sources)
228-
!equivalent_sources?(lock_sources, replacement_sources)
229-
end
230-
231-
def rubygems_aggregate_class
194+
def source_class
232195
Source::Rubygems
233196
end
234197

@@ -247,10 +210,6 @@ def source_list_for(source)
247210
end
248211
end
249212

250-
def combine_rubygems_sources
251-
Source::Rubygems.new("remotes" => rubygems_remotes)
252-
end
253-
254213
def warn_on_git_protocol(source)
255214
return if Bundler.settings["git.allow_insecure"]
256215

bundler/lib/bundler/source_map.rb

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,12 @@ def all_requirements
2323
if previous_source.nil?
2424
requirements[indirect_dependency_name] = source
2525
else
26-
no_ambiguous_sources = Bundler.feature_flag.bundler_4_mode?
27-
2826
msg = ["The gem '#{indirect_dependency_name}' was found in multiple relevant sources."]
2927
msg.concat [previous_source, source].map {|s| " * #{s}" }.sort
30-
msg << "You #{no_ambiguous_sources ? :must : :should} add this gem to the source block for the source you wish it to be installed from."
28+
msg << "You must add this gem to the source block for the source you wish it to be installed from."
3129
msg = msg.join("\n")
3230

33-
raise SecurityError, msg if no_ambiguous_sources
34-
Bundler.ui.warn "Warning: #{msg}"
31+
raise SecurityError, msg
3532
end
3633
end
3734

0 commit comments

Comments
 (0)