Skip to content

Commit ba6e29b

Browse files
authored
Merge pull request #9554 from ruby/release/4.0.12
Prepare RubyGems 4.0.12 and Bundler 4.0.12
2 parents bcb9a94 + 665f998 commit ba6e29b

31 files changed

Lines changed: 432 additions & 43 deletions

CHANGELOG.md

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

3+
## 4.0.12 / 2026-05-20
4+
5+
### Enhancements:
6+
7+
* Remove cygwin from WIN_PATTERNS. Pull request [#9527](https://github.com/ruby/rubygems/pull/9527) by fd00
8+
* Installs bundler 4.0.12 as a default gem.
9+
10+
### Bug fixes:
11+
12+
* Fall back to lockfile version when `BUNDLE_VERSION` is "lockfile". Pull request [#9545](https://github.com/ruby/rubygems/pull/9545) by hsbt
13+
* Read `BUNDLE_VERSION` env var in `BundlerVersionFinder`. Pull request [#9538](https://github.com/ruby/rubygems/pull/9538) by hsbt
14+
315
## 4.0.11 / 2026-04-30
416

517
### Enhancements:

bundler/CHANGELOG.md

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

3+
## 4.0.12 / 2026-05-20
4+
5+
### Enhancements:
6+
7+
* Make `bundle config get` return status 1 when the value is not set. Pull request [#9505](https://github.com/ruby/rubygems/pull/9505) by willnet
8+
* Use Pathname#absolute?. Pull request [#9529](https://github.com/ruby/rubygems/pull/9529) by nobu
9+
* Deprecate parsing non-lockfile content in LockfileParser. Pull request [#9502](https://github.com/ruby/rubygems/pull/9502) by kurotaky
10+
* Print a warning for a potential confusion from the indirect dependencies. Pull request [#5029](https://github.com/ruby/rubygems/pull/5029) by junaruga
11+
* Respect Gemfile bundler setting in `Bundler.setup`. Pull request [#4892](https://github.com/ruby/rubygems/pull/4892) by godfat
12+
13+
### Bug fixes:
14+
15+
* Gracefully handle missing checksums in Compact Index. Pull request [#9492](https://github.com/ruby/rubygems/pull/9492) by jneen
16+
* Skip git source exclusion when lockfile cannot backfill. Pull request [#9544](https://github.com/ruby/rubygems/pull/9544) by yahonda
17+
* Fix bundle config gemfile unset behavior. Pull request [#9514](https://github.com/ruby/rubygems/pull/9514) by afurm
18+
319
## 4.0.11 / 2026-04-30
420

521
### Enhancements:

bundler/lib/bundler.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ def setup(*groups)
156156
# Return if all groups are already loaded
157157
return @setup if defined?(@setup) && @setup
158158

159+
configure_custom_gemfile
159160
definition.validate_runtime!
160161

161162
SharedHelpers.print_major_deprecations!
@@ -586,6 +587,15 @@ def configure_gem_home_and_path(path = bundle_path)
586587
Bundler.rubygems.clear_paths
587588
end
588589

590+
def configure_custom_gemfile(custom_gemfile = nil)
591+
custom_gemfile ||= Bundler.settings[:gemfile]
592+
593+
if custom_gemfile && !custom_gemfile.empty?
594+
Bundler::SharedHelpers.set_env "BUNDLE_GEMFILE", File.expand_path(custom_gemfile)
595+
reset_settings_and_root!
596+
end
597+
end
598+
589599
def self_manager
590600
@self_manager ||= begin
591601
require_relative "bundler/self_manager"

bundler/lib/bundler/cli.rb

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,18 +61,18 @@ def initialize(*args)
6161

6262
current_cmd = args.last[:current_command].name
6363

64-
custom_gemfile = options[:gemfile] || Bundler.settings[:gemfile]
65-
if custom_gemfile && !custom_gemfile.empty?
66-
Bundler::SharedHelpers.set_env "BUNDLE_GEMFILE", File.expand_path(custom_gemfile)
67-
reset_settings = true
68-
end
69-
70-
# lock --lockfile works differently than install --lockfile
71-
unless current_cmd == "lock"
72-
custom_lockfile = options[:lockfile] || ENV["BUNDLE_LOCKFILE"] || Bundler.settings[:lockfile]
73-
if custom_lockfile && !custom_lockfile.empty?
74-
Bundler::SharedHelpers.set_env "BUNDLE_LOCKFILE", File.expand_path(custom_lockfile)
75-
reset_settings = true
64+
# `bundle config` manages stored settings, so avoid promoting settings
65+
# like `gemfile` or `lockfile` to environment variables before it runs.
66+
unless current_cmd == "config"
67+
Bundler.configure_custom_gemfile(options[:gemfile])
68+
69+
# lock --lockfile works differently than install --lockfile
70+
unless current_cmd == "lock"
71+
custom_lockfile = options[:lockfile] || ENV["BUNDLE_LOCKFILE"] || Bundler.settings[:lockfile]
72+
if custom_lockfile && !custom_lockfile.empty?
73+
Bundler::SharedHelpers.set_env "BUNDLE_LOCKFILE", File.expand_path(custom_lockfile)
74+
reset_settings = true
75+
end
7676
end
7777
end
7878

bundler/lib/bundler/cli/config.rb

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,16 +87,21 @@ def run
8787

8888
if value.nil?
8989
warn_unused_scope "Ignoring --#{scope} since no value to set was given"
90+
current_value = Bundler.settings[name]
9091

9192
if options[:parseable]
9293
if value = Bundler.settings[name]
9394
Bundler.ui.info("#{name}=#{value}")
9495
end
95-
return
96+
else
97+
confirm(name)
9698
end
9799

98-
confirm(name)
99-
return
100+
if current_value.nil?
101+
exit 1
102+
else
103+
return
104+
end
100105
end
101106

102107
Bundler.ui.info(message) if message

bundler/lib/bundler/compact_index_client/parser.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,10 @@ def gem_parser
7171
# This method gets called at least once for every gem when parsing versions.
7272
def parse_version_checksum(line, checksums)
7373
return unless (name_end = line.index(" ")) # Artifactory bug causes blank lines in artifactor index files
74-
return unless (checksum_start = line.index(" ", name_end + 1) + 1)
74+
checksum_start = line.index(" ", name_end + 1)
75+
return unless checksum_start
76+
checksum_start += 1
77+
7578
checksum_end = line.size - checksum_start
7679

7780
line.freeze # allows slicing into the string to not allocate a copy of the line

bundler/lib/bundler/definition.rb

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -783,7 +783,25 @@ def start_resolution
783783
end
784784

785785
def precompute_source_requirements_for_indirect_dependencies?
786-
sources.non_global_rubygems_sources.all?(&:dependency_api_available?)
786+
if sources.non_global_rubygems_sources.all?(&:dependency_api_available?)
787+
true
788+
else
789+
non_dependency_api_warning
790+
false
791+
end
792+
end
793+
794+
def non_dependency_api_warning
795+
non_api_sources = sources.non_global_rubygems_sources.reject(&:dependency_api_available?)
796+
non_api_source_names = non_api_sources.map {|d| " * #{d}" }.join("\n")
797+
798+
msg = String.new
799+
msg << "Your Gemfile contains scoped sources that don't implement a dependency API, namely:\n\n"
800+
msg << non_api_source_names
801+
msg << "\n\nUsing the above gem servers may result in installing unexpected gems. " \
802+
"To resolve this warning, make sure you use gem servers that implement dependency APIs, " \
803+
"such as gemstash or geminabox gem servers."
804+
Bundler.ui.warn msg
787805
end
788806

789807
def current_platform_locked?
@@ -1159,16 +1177,20 @@ def excluded_git_sources
11591177
def find_source_requirements
11601178
preload_git_sources
11611179

1180+
# Only safe to exclude when locked_requirements (merged below) backfills the gap.
1181+
nothing_changed = nothing_changed?
1182+
excluded = nothing_changed ? excluded_git_sources : []
1183+
11621184
# Record the specs available in each gem's source, so that those
11631185
# specs will be available later when the resolver knows where to
11641186
# look for that gemspec (or its dependencies)
11651187
source_requirements = if precompute_source_requirements_for_indirect_dependencies?
1166-
all_requirements = source_map.all_requirements(excluded_git_sources)
1188+
all_requirements = source_map.all_requirements(excluded)
11671189
{ default: default_source }.merge(all_requirements)
11681190
else
1169-
{ default: Source::RubygemsAggregate.new(sources, source_map, excluded_git_sources) }.merge(source_map.direct_requirements)
1191+
{ default: Source::RubygemsAggregate.new(sources, source_map, excluded) }.merge(source_map.direct_requirements)
11701192
end
1171-
source_requirements.merge!(source_map.locked_requirements) if nothing_changed?
1193+
source_requirements.merge!(source_map.locked_requirements) if nothing_changed
11721194
metadata_dependencies.each do |dep|
11731195
source_requirements[dep.name] = sources.metadata_source
11741196
end

bundler/lib/bundler/lockfile_parser.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,17 @@ def initialize(lockfile, strict: false)
115115
"Run `git checkout HEAD -- #{@lockfile_path}` first to get a clean lock."
116116
end
117117

118+
@valid = lockfile.strip.empty? ||
119+
lockfile.split(/(?:\r?\n)+/).any? {|l| KNOWN_SECTIONS.include?(l) }
120+
121+
unless @valid
122+
SharedHelpers.feature_deprecated!(
123+
"Your #{@lockfile_path} does not appear to be a valid lockfile. " \
124+
"Run `rm #{@lockfile_path}` and then `bundle install` to generate a new lockfile. " \
125+
"This will raise a LockfileError in a future version of Bundler."
126+
)
127+
end
128+
118129
lockfile.split(/((?:\r?\n)+)/) do |line|
119130
# split alternates between the line and the following whitespace
120131
next @pos.advance!(line) if line.match?(/^\s*$/)
@@ -164,6 +175,10 @@ def may_include_redundant_platform_specific_gems?
164175
bundler_version.nil? || bundler_version < Gem::Version.new("1.16.2")
165176
end
166177

178+
def valid?
179+
@valid
180+
end
181+
167182
private
168183

169184
TYPES = {

bundler/lib/bundler/source/path.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,10 +220,11 @@ def generate_bin(spec, options = {})
220220
# Some gem authors put absolute paths in their gemspec
221221
# and we have to save them from themselves
222222
spec.files = spec.files.filter_map do |path|
223-
next path unless /\A#{Pathname::SEPARATOR_PAT}/o.match?(path)
223+
pathname = Pathname.new(path)
224+
next path unless pathname.absolute?
224225
next if File.directory?(path)
225226
begin
226-
Pathname.new(path).relative_path_from(gem_dir).to_s
227+
pathname.relative_path_from(gem_dir).to_s
227228
rescue ArgumentError
228229
path
229230
end

bundler/lib/bundler/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# frozen_string_literal: false
22

33
module Bundler
4-
VERSION = "4.0.11".freeze
4+
VERSION = "4.0.12".freeze
55

66
def self.bundler_major_version
77
@bundler_major_version ||= gem_version.segments.first

0 commit comments

Comments
 (0)