Skip to content

Commit c290263

Browse files
Merge pull request #4385 from rubygems/revert_disable_multisource
Revert disable_multisource changes (cherry picked from commit eb753b9)
1 parent 2fafaad commit c290263

26 files changed

+394
-452
lines changed

.github/workflows/ruby-core.yml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,15 @@ jobs:
4646
- uses: actions/checkout@v2
4747
with:
4848
path: rubygems/rubygems
49-
- name: Sync tools
49+
- name: Test RubyGems
5050
run: |
5151
ruby tool/sync_default_gems.rb rubygems
52-
ruby tool/sync_default_gems.rb bundler
53-
working-directory: ruby/ruby
54-
- name: Test RubyGems
55-
run: make -j2 -s test-all TESTS="rubygems --no-retry"
52+
make -j2 -s test-all TESTS="rubygems --no-retry"
5653
working-directory: ruby/ruby
5754
if: matrix.target == 'Rubygems'
5855
- name: Test Bundler
5956
run: |
57+
ruby tool/sync_default_gems.rb bundler
6058
git checkout lib/bundler/bundler.gemspec
6159
git add .
6260
make test-bundler-parallel

bundler/lib/bundler/definition.rb

Lines changed: 25 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -106,19 +106,6 @@ 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-
122109
@unlock[:gems] ||= []
123110
@unlock[:sources] ||= []
124111
@unlock[:ruby] ||= if @ruby_version && locked_ruby_version_object
@@ -158,14 +145,6 @@ def gem_version_promoter
158145
end
159146
end
160147

161-
def disable_multisource?
162-
@disable_multisource
163-
end
164-
165-
def allow_multisource!
166-
@disable_multisource = false
167-
end
168-
169148
def resolve_with_cache!
170149
raise "Specs already loaded" if @specs
171150
sources.cached!
@@ -285,7 +264,7 @@ def resolve
285264
# Run a resolve against the locally available gems
286265
Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}")
287266
expanded_dependencies = expand_dependencies(dependencies + metadata_dependencies, @remote)
288-
Resolver.resolve(expanded_dependencies, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
267+
Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
289268
end
290269
end
291270
end
@@ -551,9 +530,6 @@ def find_indexed_specs(current_spec)
551530
attr_reader :sources
552531
private :sources
553532

554-
attr_reader :locked_gem_sources
555-
private :locked_gem_sources
556-
557533
def nothing_changed?
558534
!@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes && !@locked_specs_incomplete_for_platform
559535
end
@@ -678,20 +654,21 @@ def converge_path_sources_to_gemspec_sources
678654
end
679655

680656
def converge_rubygems_sources
681-
return false if disable_multisource?
657+
return false if Bundler.feature_flag.disable_multisource?
682658

683-
return false if locked_gem_sources.empty?
659+
changes = false
684660

661+
# Get the RubyGems sources from the Gemfile.lock
662+
locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
685663
# Get the RubyGems remotes from the Gemfile
686664
actual_remotes = sources.rubygems_remotes
687-
return false if actual_remotes.empty?
688-
689-
changes = false
690665

691666
# If there is a RubyGems source in both
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])
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
695672
end
696673

697674
changes
@@ -916,18 +893,30 @@ def source_requirements
916893
# Record the specs available in each gem's source, so that those
917894
# specs will be available later when the resolver knows where to
918895
# look for that gemspec (or its dependencies)
919-
source_requirements = { :default => sources.default_source }.merge(dependency_source_requirements)
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
920903
metadata_dependencies.each do |dep|
921904
source_requirements[dep.name] = sources.metadata_source
922905
end
923-
source_requirements[:global] = index unless disable_multisource?
924906
source_requirements[:default_bundler] = source_requirements["bundler"] || source_requirements[:default]
925907
source_requirements["bundler"] = sources.metadata_source # needs to come last to override
926908
source_requirements
927909
end
928910

929911
def pinned_spec_names(skip = nil)
930-
dependency_source_requirements.reject {|_, source| source == skip }.keys
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
931920
end
932921

933922
def requested_groups
@@ -984,18 +973,5 @@ def equivalent_rubygems_remotes?(source)
984973

985974
Bundler.settings[:allow_deployment_source_credential_changes] && source.equivalent_remotes?(sources.rubygems_remotes)
986975
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
1000976
end
1001977
end

bundler/lib/bundler/dsl.rb

Lines changed: 25 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@ def self.evaluate(gemfile, lockfile, unlock)
2424
def initialize
2525
@source = nil
2626
@sources = SourceList.new
27-
28-
@global_rubygems_sources = []
29-
3027
@git_sources = {}
3128
@dependencies = []
3229
@groups = []
@@ -48,7 +45,6 @@ def eval_gemfile(gemfile, contents = nil)
4845
@gemfiles << expanded_gemfile_path
4946
contents ||= Bundler.read_file(@gemfile.to_s)
5047
instance_eval(contents.dup.tap{|x| x.untaint if RUBY_VERSION < "2.7" }, gemfile.to_s, 1)
51-
check_primary_source_safety
5248
rescue Exception => e # rubocop:disable Lint/RescueException
5349
message = "There was an error " \
5450
"#{e.is_a?(GemfileEvalError) ? "evaluating" : "parsing"} " \
@@ -168,7 +164,8 @@ def source(source, *args, &blk)
168164
elsif block_given?
169165
with_source(@sources.add_rubygems_source("remotes" => source), &blk)
170166
else
171-
@global_rubygems_sources << source
167+
check_primary_source_safety(@sources)
168+
@sources.global_rubygems_source = source
172169
end
173170
end
174171

@@ -186,14 +183,24 @@ def git_source(name, &block)
186183
end
187184

188185
def path(path, options = {}, &blk)
186+
unless block_given?
187+
msg = "You can no longer specify a path source by itself. Instead, \n" \
188+
"either use the :path option on a gem, or specify the gems that \n" \
189+
"bundler should find in the path source by passing a block to \n" \
190+
"the path method, like: \n\n" \
191+
" path 'dir/containing/rails' do\n" \
192+
" gem 'rails'\n" \
193+
" end\n\n"
194+
195+
raise DeprecatedError, msg if Bundler.feature_flag.disable_multisource?
196+
SharedHelpers.major_deprecation(2, msg.strip)
197+
end
198+
189199
source_options = normalize_hash(options).merge(
190200
"path" => Pathname.new(path),
191201
"root_path" => gemfile_root,
192202
"gemspec" => gemspecs.find {|g| g.name == options["name"] }
193203
)
194-
195-
source_options["global"] = true unless block_given?
196-
197204
source = @sources.add_path_source(source_options)
198205
with_source(source, &blk)
199206
end
@@ -272,11 +279,6 @@ def method_missing(name, *args)
272279
raise GemfileError, "Undefined local variable or method `#{name}' for Gemfile"
273280
end
274281

275-
def check_primary_source_safety
276-
check_path_source_safety
277-
check_rubygems_source_safety
278-
end
279-
280282
private
281283

282284
def add_git_sources
@@ -438,40 +440,25 @@ def normalize_source(source)
438440
end
439441
end
440442

441-
def check_path_source_safety
442-
return if @sources.global_path_source.nil?
443-
444-
msg = "You can no longer specify a path source by itself. Instead, \n" \
445-
"either use the :path option on a gem, or specify the gems that \n" \
446-
"bundler should find in the path source by passing a block to \n" \
447-
"the path method, like: \n\n" \
448-
" path 'dir/containing/rails' do\n" \
449-
" gem 'rails'\n" \
450-
" end\n\n"
443+
def check_primary_source_safety(source_list)
444+
return if source_list.rubygems_primary_remotes.empty? && source_list.global_rubygems_source.nil?
451445

452-
SharedHelpers.major_deprecation(2, msg.strip)
453-
end
454-
455-
def check_rubygems_source_safety
456-
if @global_rubygems_sources.size <= 1
457-
@sources.global_rubygems_source = @global_rubygems_sources.first
458-
return
459-
end
460-
461-
@global_rubygems_sources.each do |source|
462-
@sources.add_rubygems_remote(source)
463-
end
464-
465-
if Bundler.feature_flag.bundler_3_mode?
446+
if Bundler.feature_flag.disable_multisource?
466447
msg = "This Gemfile contains multiple primary sources. " \
467448
"Each source after the first must include a block to indicate which gems " \
468449
"should come from that source"
450+
unless Bundler.feature_flag.bundler_2_mode?
451+
msg += ". To downgrade this error to a warning, run " \
452+
"`bundle config unset disable_multisource`"
453+
end
469454
raise GemfileEvalError, msg
470455
else
471456
Bundler::SharedHelpers.major_deprecation 2, "Your Gemfile contains multiple primary sources. " \
472457
"Using `source` more than once without a block is a security risk, and " \
473458
"may result in installing unexpected gems. To resolve this warning, use " \
474-
"a block to indicate which gems should come from the secondary source."
459+
"a block to indicate which gems should come from the secondary source. " \
460+
"To upgrade this warning to an error, run `bundle config set --local " \
461+
"disable_multisource true`."
475462
end
476463
end
477464

bundler/lib/bundler/feature_flag.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ def self.settings_method(name, key, &default)
3232
settings_flag(:cache_all) { bundler_3_mode? }
3333
settings_flag(:default_install_uses_path) { bundler_3_mode? }
3434
settings_flag(:deployment_means_frozen) { bundler_3_mode? }
35+
settings_flag(:disable_multisource) { bundler_3_mode? }
3536
settings_flag(:forget_cli_options) { bundler_3_mode? }
3637
settings_flag(:global_gem_cache) { bundler_3_mode? }
3738
settings_flag(:only_update_to_newer_versions) { bundler_3_mode? }

bundler/lib/bundler/inline.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ def Bundler.root
5050
Bundler::Plugin.gemfile_install(&gemfile) if Bundler.feature_flag.plugins?
5151
builder = Bundler::Dsl.new
5252
builder.instance_eval(&gemfile)
53-
builder.check_primary_source_safety
5453

5554
Bundler.settings.temporary(:frozen => false) do
5655
definition = builder.to_definition(nil, true)

bundler/lib/bundler/lockfile_parser.rb

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ def initialize(lockfile)
6464
@state = nil
6565
@specs = {}
6666

67+
@rubygems_aggregate = Source::Rubygems.new
68+
6769
if lockfile.match(/<<<<<<<|=======|>>>>>>>|\|\|\|\|\|\|\|/)
6870
raise LockfileError, "Your #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} contains merge conflicts.\n" \
6971
"Run `git checkout HEAD -- #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)}` first to get a clean lock."
@@ -87,6 +89,7 @@ def initialize(lockfile)
8789
send("parse_#{@state}", line)
8890
end
8991
end
92+
@sources << @rubygems_aggregate unless Bundler.feature_flag.disable_multisource?
9093
@specs = @specs.values.sort_by(&:identifier)
9194
warn_for_outdated_bundler_version
9295
rescue ArgumentError => e
@@ -131,19 +134,16 @@ def parse_source(line)
131134
@sources << @current_source
132135
end
133136
when GEM
134-
source_remotes = Array(@opts["remote"])
135-
136-
if source_remotes.size == 1
137+
if Bundler.feature_flag.disable_multisource?
137138
@opts["remotes"] = @opts.delete("remote")
138139
@current_source = TYPES[@type].from_lock(@opts)
140+
@sources << @current_source
139141
else
140-
source_remotes.each do |url|
141-
rubygems_aggregate.add_remote(url)
142+
Array(@opts["remote"]).each do |url|
143+
@rubygems_aggregate.add_remote(url)
142144
end
143-
@current_source = rubygems_aggregate
145+
@current_source = @rubygems_aggregate
144146
end
145-
146-
@sources << @current_source
147147
when PLUGIN
148148
@current_source = Plugin.source_from_lock(@opts)
149149
@sources << @current_source
@@ -245,9 +245,5 @@ def parse_bundled_with(line)
245245
def parse_ruby(line)
246246
@ruby_version = line.strip
247247
end
248-
249-
def rubygems_aggregate
250-
@rubygems_aggregate ||= Source::Rubygems.new
251-
end
252248
end
253249
end

bundler/lib/bundler/man/bundle-config.1

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ Executing \fBbundle config unset \-\-local <name> <value>\fR will delete the con
5656
.P
5757
Executing bundle with the \fBBUNDLE_IGNORE_CONFIG\fR environment variable set will cause it to ignore all configuration\.
5858
.
59+
.P
60+
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\.
61+
.
5962
.SH "REMEMBERING OPTIONS"
6063
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)\.
6164
.
@@ -181,6 +184,9 @@ The following is a list of all configuration keys and their purpose\. You can le
181184
\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\.
182185
.
183186
.IP "\(bu" 4
187+
\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\.
188+
.
189+
.IP "\(bu" 4
184190
\fBdisable_shared_gems\fR (\fBBUNDLE_DISABLE_SHARED_GEMS\fR): Stop Bundler from accessing gems installed to RubyGems\' normal location\.
185191
.
186192
.IP "\(bu" 4

bundler/lib/bundler/man/bundle-config.1.ronn

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ configuration only from the local application.
4747
Executing bundle with the `BUNDLE_IGNORE_CONFIG` environment variable set will
4848
cause it to ignore all configuration.
4949

50+
Executing `bundle config set --local disable_multisource true` upgrades the warning about
51+
the Gemfile containing multiple primary sources to an error. Executing `bundle
52+
config unset disable_multisource` downgrades this error to a warning.
53+
5054
## REMEMBERING OPTIONS
5155

5256
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).
174178
* `disable_local_revision_check` (`BUNDLE_DISABLE_LOCAL_REVISION_CHECK`):
175179
Allow Bundler to use a local git override without checking if the revision
176180
present in the lockfile is present in the repository.
181+
* `disable_multisource` (`BUNDLE_DISABLE_MULTISOURCE`):
182+
When set, Gemfiles containing multiple sources will produce errors
183+
instead of warnings.
184+
Use `bundle config unset disable_multisource` to unset.
177185
* `disable_shared_gems` (`BUNDLE_DISABLE_SHARED_GEMS`):
178186
Stop Bundler from accessing gems installed to RubyGems' normal location.
179187
* `disable_version_check` (`BUNDLE_DISABLE_VERSION_CHECK`):

bundler/lib/bundler/plugin.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ def gemfile_install(gemfile = nil, &inline)
105105
else
106106
builder.eval_gemfile(gemfile)
107107
end
108-
builder.check_primary_source_safety
109108
definition = builder.to_definition(nil, true)
110109

111110
return if definition.dependencies.empty?

0 commit comments

Comments
 (0)