Skip to content

Commit 5682fba

Browse files
authored
Merge pull request #9787 from ruby/release/4.0.19
Prepare RubyGems 4.0.19 and Bundler 4.0.19
2 parents 1b8be36 + 2d0e3df commit 5682fba

42 files changed

Lines changed: 670 additions & 65 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
# Changelog
22

3+
## 4.0.19 / 2026-08-20
4+
5+
### Enhancements:
6+
7+
* Reject SafeMarshal collection lengths longer than the remaining input. Pull request [#9756](https://github.com/ruby/rubygems/pull/9756) by hsbt
8+
* Installs bundler 4.0.19 as a default gem.
9+
10+
### Bug fixes:
11+
12+
* Fix gem uninstall --user-install crash when GEM_HOME does not exist. Pull request [#9749](https://github.com/ruby/rubygems/pull/9749) by hsbt
13+
14+
### Documentation:
15+
16+
* Document SPDX license handling for license= and licenses=. Pull request [#9766](https://github.com/ruby/rubygems/pull/9766) by hsbt
17+
318
## 4.0.18 / 2026-08-05
419

520
### Enhancements:

bundler/CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,25 @@
11
# Changelog
22

3+
## 4.0.19 / 2026-08-20
4+
5+
### Enhancements:
6+
7+
* Validate the platform field in Gem::Installer#verify_spec. Pull request [#9780](https://github.com/ruby/rubygems/pull/9780) by hsbt
8+
* Restrict UserDefined handling to explicit class set for Gem::SafeMashal. Pull request [#9770](https://github.com/ruby/rubygems/pull/9770) by jackorp
9+
* Filter git command output against the configured URI. Pull request [#9778](https://github.com/ruby/rubygems/pull/9778) by hsbt
10+
* Summarize cooldown-skipped versions at the end of install, update, and lock. Pull request [#9762](https://github.com/ruby/rubygems/pull/9762) by hsbt
11+
12+
### Bug fixes:
13+
14+
* Make repeated bundle lock options accumulate. Pull request [#9748](https://github.com/ruby/rubygems/pull/9748) by hsbt
15+
* Fail instead of warning when frozen mode can't update the lockfile. Pull request [#9750](https://github.com/ruby/rubygems/pull/9750) by hsbt
16+
* Fix wrong $LOAD_PATH for gems installed in the same process. Pull request [#9784](https://github.com/ruby/rubygems/pull/9784) by hsbt
17+
18+
### Documentation:
19+
20+
* Fix auto-clean default version in bundle config docs. Pull request [#9783](https://github.com/ruby/rubygems/pull/9783) by hsbt
21+
* Correct Bundler 5 default path documentation. Pull request [#9771](https://github.com/ruby/rubygems/pull/9771) by alloutflo
22+
323
## 4.0.18 / 2026-08-05
424

525
### Enhancements:

bundler/lib/bundler/cli.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -626,15 +626,15 @@ def inject(*)
626626
end
627627

628628
desc "lock", "Creates a lockfile without installing"
629-
method_option "update", type: :array, lazy_default: true, banner: "ignore the existing lockfile, update all gems by default, or update list of given gems"
629+
method_option "update", type: :array, lazy_default: true, repeatable: true, banner: "ignore the existing lockfile, update all gems by default, or update list of given gems"
630630
method_option "local", type: :boolean, default: false, banner: "do not attempt to fetch remote gemspecs and use the local gem cache only"
631631
method_option "print", type: :boolean, default: false, banner: "print the lockfile to STDOUT instead of writing to the file system"
632632
method_option "gemfile", type: :string, banner: "Use the specified gemfile instead of Gemfile"
633633
method_option "lockfile", type: :string, default: nil, banner: "the path the lockfile should be written to"
634634
method_option "full-index", type: :boolean, default: false, banner: "Fall back to using the single-file index of all gems"
635635
method_option "add-checksums", type: :boolean, default: false, banner: "Adds checksums to the lockfile"
636-
method_option "add-platform", type: :array, default: [], banner: "Add a new platform to the lockfile"
637-
method_option "remove-platform", type: :array, default: [], banner: "Remove a platform from the lockfile"
636+
method_option "add-platform", type: :array, default: [], repeatable: true, banner: "Add a new platform to the lockfile"
637+
method_option "remove-platform", type: :array, default: [], repeatable: true, banner: "Remove a platform from the lockfile"
638638
method_option "normalize-platforms", type: :boolean, default: false, banner: "Normalize lockfile platforms"
639639
method_option "patch", type: :boolean, banner: "If updating, prefer updating only to next patch version"
640640
method_option "minor", type: :boolean, banner: "If updating, prefer updating only to next minor version"

bundler/lib/bundler/cli/common.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,17 @@ def self.print_post_install_message(name, msg)
2020
Bundler.ui.info msg
2121
end
2222

23+
def self.output_cooldown_skipped_summary(definition = Bundler.definition)
24+
skipped = definition.cooldown_skipped
25+
return if skipped.empty?
26+
27+
Bundler.ui.info "The following gem versions were skipped by the cooldown setting:"
28+
skipped.each do |entry|
29+
days = entry[:available_in_days]
30+
Bundler.ui.info " * #{entry[:name]} #{entry[:version]} (available in #{days} #{days == 1 ? "day" : "days"}), resolved #{entry[:resolved]} instead"
31+
end
32+
end
33+
2334
def self.output_fund_metadata_summary
2435
return if Bundler.settings["ignore_funding_requests"]
2536
definition = Bundler.definition

bundler/lib/bundler/cli/install.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ def run
6464
end
6565

6666
Bundler::CLI::Common.output_post_install_messages installer.post_install_messages
67+
Bundler::CLI::Common.output_cooldown_skipped_summary(definition)
6768

6869
if CLI::Common.clean_after_install?
6970
require_relative "clean"

bundler/lib/bundler/cli/lock.rb

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ def run
2626
Bundler::Fetcher.disable_endpoint = options["full-index"]
2727

2828
update = options[:update]
29+
# --update is repeatable, so it parses as an array with one entry per
30+
# occurrence, where a bare `--update` produces a `true` entry
31+
update = update.include?(true) ? true : update.flatten if update.is_a?(Array)
2932
conservative = options[:conservative]
3033
bundler = options[:bundler]
3134

@@ -44,12 +47,12 @@ def run
4447

4548
Bundler::CLI::Common.configure_gem_version_promoter(definition, options) if options[:update]
4649

47-
options["remove-platform"].each do |platform_string|
50+
options["remove-platform"].flatten.each do |platform_string|
4851
platform = Gem::Platform.new(platform_string)
4952
definition.remove_platform(platform)
5053
end
5154

52-
options["add-platform"].each do |platform_string|
55+
options["add-platform"].flatten.each do |platform_string|
5356
platform = Gem::Platform.new(platform_string)
5457
if platform.to_s == "unknown"
5558
Bundler.ui.error "The platform `#{platform_string}` is unknown to RubyGems and can't be added to the lockfile."
@@ -77,6 +80,8 @@ def run
7780
puts "Writing lockfile to #{file}"
7881
definition.write_lock(file, false)
7982
end
83+
84+
Bundler::CLI::Common.output_cooldown_skipped_summary(definition)
8085
end
8186

8287
Bundler.ui.output_stream = previous_output_stream

bundler/lib/bundler/cli/update.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ def run
118118
Bundler.ui.confirm "Bundle updated!"
119119
Bundler::CLI::Common.output_without_groups_message(:update)
120120
Bundler::CLI::Common.output_post_install_messages installer.post_install_messages
121+
Bundler::CLI::Common.output_cooldown_skipped_summary
121122

122123
Bundler::CLI::Common.output_fund_metadata_summary
123124
end

bundler/lib/bundler/definition.rb

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,12 @@ def spec_git_paths
366366
sources.git_sources.filter_map {|s| File.realpath(s.path) if File.exist?(s.path) }
367367
end
368368

369+
# Versions excluded by cooldown during the last resolution, one entry per
370+
# gem with the newest skipped version. Empty when no resolution ran.
371+
def cooldown_skipped
372+
@cooldown_skipped || []
373+
end
374+
369375
def groups
370376
dependencies.flat_map(&:groups).uniq
371377
end
@@ -404,7 +410,7 @@ def write_lock(file, preserve_unknown_sections)
404410
updating_major = locked_major < current_major
405411
end
406412

407-
preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler))
413+
preserve_unknown_sections ||= Bundler.frozen_bundle? || (!updating_major && !(unlocking? || @unlocking_bundler))
408414

409415
if File.exist?(file) && lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections)
410416
return if Bundler.frozen_bundle?
@@ -413,8 +419,10 @@ def write_lock(file, preserve_unknown_sections)
413419
end
414420

415421
if Bundler.frozen_bundle?
416-
Bundler.ui.error "Cannot write a changed lockfile while frozen."
417-
return
422+
msg = lockfile_changes_summary("frozen mode is set") ||
423+
"Your lockfile needs to be updated, but it can't be because frozen mode is set.\n\n" \
424+
"Run `bundle install` elsewhere and add the updated #{SharedHelpers.relative_lockfile_path} to version control."
425+
raise ProductionError, msg
418426
end
419427

420428
# Convert to \r\n if the existing lock has them, i.e., Windows with
@@ -770,6 +778,8 @@ def start_resolution
770778

771779
result = SpecSet.new(resolver.start)
772780

781+
@cooldown_skipped = resolver.cooldown_skipped
782+
773783
@resolved_bundler_version = result.find {|spec| spec.name == "bundler" }&.version
774784

775785
@new_platforms.each do |platform|

bundler/lib/bundler/endpoint_specification.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,19 @@ def require_paths
5050
end
5151
end
5252

53+
# `require_paths` is overridden above, but `full_require_paths` (and so
54+
# `load_paths`) is computed from `raw_require_paths`, which would otherwise
55+
# report the default `lib` for every gem
56+
def raw_require_paths
57+
if @remote_specification
58+
@remote_specification.raw_require_paths
59+
elsif _local_specification
60+
_local_specification.raw_require_paths
61+
else
62+
super
63+
end
64+
end
65+
5366
# needed for inline
5467
def load_paths
5568
# remote specs aren't installed, and can't have load_paths

bundler/lib/bundler/installer.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ def run(options)
8383
install(options)
8484

8585
Gem::Specification.reset # invalidate gem specification cache so that installed gems are immediately available
86+
# Drop the source caches too, since releasing resolution memory dropped
87+
# the source indexes. A resolution happening after this point would
88+
# otherwise rebuild them around a snapshot of installed gems taken
89+
# before the install, and materialize against remote specs that don't
90+
# know where the gems they stand for ended up.
91+
@definition.sources.clear_cache
8692

8793
lock
8894
Standalone.new(options[:standalone], @definition).generate if options[:standalone]

0 commit comments

Comments
 (0)