Skip to content

Commit cc7c333

Browse files
Merge pull request #4377 from rubygems/release/bundler_2.2.10_rubygems_3.2.10
Prepare rubygems 3.2.10 and bundler 2.2.10
2 parents 30e740c + feba8bd commit cc7c333

38 files changed

+649
-430
lines changed

.github/workflows/ruby-core.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,17 @@ jobs:
4646
- uses: actions/checkout@v2
4747
with:
4848
path: rubygems/rubygems
49-
- name: Test RubyGems
49+
- name: Sync tools
5050
run: |
5151
ruby tool/sync_default_gems.rb rubygems
52-
make -j2 -s test-all TESTS="rubygems --no-retry"
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"
5356
working-directory: ruby/ruby
5457
if: matrix.target == 'Rubygems'
5558
- name: Test Bundler
5659
run: |
57-
ruby tool/sync_default_gems.rb bundler
5860
git checkout lib/bundler/bundler.gemspec
5961
git add .
6062
make test-bundler-parallel

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
# 3.2.10 / 2021-02-15
2+
3+
## Documentation:
4+
5+
* Add a `gem push` example to `gem help`. Pull request #4373 by
6+
deivid-rodriguez
7+
* Improve documentation for `required_ruby_version`. Pull request #4343 by
8+
AlexWayfer
9+
110
# 3.2.9 / 2021-02-08
211

312
## Bug fixes:

bundler/CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
# 2.2.10 (February 15, 2021)
2+
3+
## Security fixes:
4+
5+
- Fix source priority for transitive dependencies and split lockfile rubygems source sections [#3655](https://github.com/rubygems/rubygems/pull/3655)
6+
7+
## Bug fixes:
8+
9+
- Fix adding platforms to lockfile sometimes conflicting on ruby requirements [#4371](https://github.com/rubygems/rubygems/pull/4371)
10+
- Fix bundler sometimes choosing ruby variants over java ones [#4367](https://github.com/rubygems/rubygems/pull/4367)
11+
12+
## Documentation:
13+
14+
- Update man pages to reflect to new default for bundle install jobs [#4188](https://github.com/rubygems/rubygems/pull/4188)
15+
116
# 2.2.9 (February 8, 2021)
217

318
## Enhancements:

bundler/lib/bundler/definition.rb

Lines changed: 49 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -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
9771001
end

bundler/lib/bundler/dsl.rb

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ def self.evaluate(gemfile, lockfile, unlock)
2424
def initialize
2525
@source = nil
2626
@sources = SourceList.new
27+
28+
@global_rubygems_sources = []
29+
2730
@git_sources = {}
2831
@dependencies = []
2932
@groups = []
@@ -45,6 +48,7 @@ def eval_gemfile(gemfile, contents = nil)
4548
@gemfiles << expanded_gemfile_path
4649
contents ||= Bundler.read_file(@gemfile.to_s)
4750
instance_eval(contents.dup.tap{|x| x.untaint if RUBY_VERSION < "2.7" }, gemfile.to_s, 1)
51+
check_primary_source_safety
4852
rescue Exception => e # rubocop:disable Lint/RescueException
4953
message = "There was an error " \
5054
"#{e.is_a?(GemfileEvalError) ? "evaluating" : "parsing"} " \
@@ -164,8 +168,7 @@ def source(source, *args, &blk)
164168
elsif block_given?
165169
with_source(@sources.add_rubygems_source("remotes" => source), &blk)
166170
else
167-
check_primary_source_safety(@sources)
168-
@sources.global_rubygems_source = source
171+
@global_rubygems_sources << source
169172
end
170173
end
171174

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

185188
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-
199189
source_options = normalize_hash(options).merge(
200190
"path" => Pathname.new(path),
201191
"root_path" => gemfile_root,
202192
"gemspec" => gemspecs.find {|g| g.name == options["name"] }
203193
)
194+
195+
source_options["global"] = true unless block_given?
196+
204197
source = @sources.add_path_source(source_options)
205198
with_source(source, &blk)
206199
end
@@ -279,6 +272,11 @@ def method_missing(name, *args)
279272
raise GemfileError, "Undefined local variable or method `#{name}' for Gemfile"
280273
end
281274

275+
def check_primary_source_safety
276+
check_path_source_safety
277+
check_rubygems_source_safety
278+
end
279+
282280
private
283281

284282
def add_git_sources
@@ -440,25 +438,40 @@ def normalize_source(source)
440438
end
441439
end
442440

443-
def check_primary_source_safety(source_list)
444-
return if source_list.rubygems_primary_remotes.empty? && source_list.global_rubygems_source.nil?
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"
445451

446-
if Bundler.feature_flag.disable_multisource?
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?
447466
msg = "This Gemfile contains multiple primary sources. " \
448467
"Each source after the first must include a block to indicate which gems " \
449468
"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
454469
raise GemfileEvalError, msg
455470
else
456471
Bundler::SharedHelpers.major_deprecation 2, "Your Gemfile contains multiple primary sources. " \
457472
"Using `source` more than once without a block is a security risk, and " \
458473
"may result in installing unexpected gems. To resolve this warning, use " \
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`."
474+
"a block to indicate which gems should come from the secondary source."
462475
end
463476
end
464477

bundler/lib/bundler/feature_flag.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ 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? }
3635
settings_flag(:forget_cli_options) { bundler_3_mode? }
3736
settings_flag(:global_gem_cache) { bundler_3_mode? }
3837
settings_flag(:only_update_to_newer_versions) { bundler_3_mode? }

bundler/lib/bundler/inline.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ 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
5354

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

bundler/lib/bundler/lockfile_parser.rb

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

67-
@rubygems_aggregate = Source::Rubygems.new
68-
6967
if lockfile.match(/<<<<<<<|=======|>>>>>>>|\|\|\|\|\|\|\|/)
7068
raise LockfileError, "Your #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} contains merge conflicts.\n" \
7169
"Run `git checkout HEAD -- #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)}` first to get a clean lock."
@@ -89,7 +87,6 @@ def initialize(lockfile)
8987
send("parse_#{@state}", line)
9088
end
9189
end
92-
@sources << @rubygems_aggregate unless Bundler.feature_flag.disable_multisource?
9390
@specs = @specs.values.sort_by(&:identifier)
9491
warn_for_outdated_bundler_version
9592
rescue ArgumentError => e
@@ -134,16 +131,19 @@ def parse_source(line)
134131
@sources << @current_source
135132
end
136133
when GEM
137-
if Bundler.feature_flag.disable_multisource?
134+
source_remotes = Array(@opts["remote"])
135+
136+
if source_remotes.size == 1
138137
@opts["remotes"] = @opts.delete("remote")
139138
@current_source = TYPES[@type].from_lock(@opts)
140-
@sources << @current_source
141139
else
142-
Array(@opts["remote"]).each do |url|
143-
@rubygems_aggregate.add_remote(url)
140+
source_remotes.each do |url|
141+
rubygems_aggregate.add_remote(url)
144142
end
145-
@current_source = @rubygems_aggregate
143+
@current_source = rubygems_aggregate
146144
end
145+
146+
@sources << @current_source
147147
when PLUGIN
148148
@current_source = Plugin.source_from_lock(@opts)
149149
@sources << @current_source
@@ -245,5 +245,9 @@ 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
248252
end
249253
end

0 commit comments

Comments
 (0)