summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHiroshi SHIBATA <hsbt@ruby-lang.org>2026-04-08 17:07:30 +0900
committerTakashi Kokubun <takashikkbn@gmail.com>2026-04-08 15:49:38 -0700
commit4edfd93c0ab3c90006564a6e3ae9b4ea4924db07 (patch)
treef9a6d8505843bf13d14b9e6014192cbb4272b7e8
parentdc13b5adc91c91a8d2c35cf6e770390811dbf596 (diff)
Merge RubyGems/Bundler 4.0.10
-rw-r--r--lib/bundler/injector.rb3
-rw-r--r--lib/bundler/resolver.rb18
-rw-r--r--lib/bundler/resolver/strategy.rb9
-rw-r--r--lib/bundler/settings.rb1
-rw-r--r--lib/bundler/settings/validator.rb7
-rw-r--r--lib/bundler/stub_specification.rb1
-rw-r--r--lib/bundler/templates/newgem/newgem.gemspec.tt3
-rw-r--r--lib/bundler/version.rb2
-rw-r--r--lib/rubygems.rb14
-rw-r--r--lib/rubygems/commands/pristine_command.rb5
-rw-r--r--lib/rubygems/package.rb9
-rw-r--r--lib/rubygems/specification.rb1
-rw-r--r--lib/rubygems/stub_specification.rb1
-rw-r--r--lib/rubygems/util/licenses.rb33
-rw-r--r--lib/rubygems/version.rb98
-rw-r--r--spec/bundler/bundler/settings_spec.rb21
-rw-r--r--spec/bundler/bundler/stub_specification_spec.rb8
-rw-r--r--spec/bundler/commands/newgem_spec.rb3
-rw-r--r--spec/bundler/install/gemfile/git_spec.rb2
-rw-r--r--spec/bundler/install/gemfile/specific_platform_spec.rb35
-rw-r--r--spec/bundler/install/gems/resolving_spec.rb4
-rw-r--r--spec/bundler/realworld/fixtures/tapioca/Gemfile.lock2
-rw-r--r--spec/bundler/realworld/fixtures/warbler/Gemfile.lock2
-rw-r--r--test/rubygems/test_gem.rb53
-rw-r--r--test/rubygems/test_gem_commands_owner_command.rb1
-rw-r--r--test/rubygems/test_gem_commands_pristine_command.rb8
-rw-r--r--test/rubygems/test_gem_commands_yank_command.rb1
-rw-r--r--test/rubygems/test_gem_specification.rb22
-rw-r--r--test/rubygems/test_gem_stub_specification.rb22
-rw-r--r--test/rubygems/test_gem_version.rb45
-rw-r--r--tool/bundler/dev_gems.rb.lock2
-rw-r--r--tool/bundler/rubocop_gems.rb.lock2
-rw-r--r--tool/bundler/standard_gems.rb.lock2
-rw-r--r--tool/bundler/test_gems.rb.lock2
34 files changed, 371 insertions, 71 deletions
diff --git a/lib/bundler/injector.rb b/lib/bundler/injector.rb
index 21ff90ad13..3f8bf14e38 100644
--- a/lib/bundler/injector.rb
+++ b/lib/bundler/injector.rb
@@ -80,11 +80,10 @@ module Bundler
def conservative_version(spec)
version = spec.version
return ">= 0" if version.nil?
- segments = version.segments
seg_end_index = version >= Gem::Version.new("1.0") ? 1 : 2
prerelease_suffix = version.to_s.delete_prefix(version.release.to_s) if version.prerelease?
- "#{version_prefix}#{segments[0..seg_end_index].join(".")}#{prerelease_suffix}"
+ "#{version_prefix}#{version.segments[0..seg_end_index].join(".")}#{prerelease_suffix}"
end
def version_prefix
diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb
index 1dbf565d46..3c361d8ea5 100644
--- a/lib/bundler/resolver.rb
+++ b/lib/bundler/resolver.rb
@@ -353,9 +353,27 @@ module Bundler
message << "\n#{other_specs_matching_message(specs, matching_part)}"
end
+ if specs_matching_requirement.any? && (hint = platform_mismatch_hint)
+ message << "\n\n#{hint}"
+ end
+
raise GemNotFound, message
end
+ def platform_mismatch_hint
+ locked_platforms = Bundler.locked_gems&.platforms
+ return unless locked_platforms
+
+ local_platform = Bundler.local_platform
+ return if locked_platforms.include?(local_platform)
+ return if locked_platforms.any? {|p| p == Gem::Platform::RUBY }
+
+ "Your current platform (#{local_platform}) is not included in the lockfile's platforms (#{locked_platforms.join(", ")}). " \
+ "Add the current platform to the lockfile with\n`bundle lock --add-platform #{local_platform}` and try again."
+ rescue GemfileNotFound
+ nil
+ end
+
def filtered_versions_for(package)
@gem_version_promoter.filter_versions(package, @all_versions[package])
end
diff --git a/lib/bundler/resolver/strategy.rb b/lib/bundler/resolver/strategy.rb
index 4f343bf0ce..7519d38968 100644
--- a/lib/bundler/resolver/strategy.rb
+++ b/lib/bundler/resolver/strategy.rb
@@ -5,6 +5,7 @@ module Bundler
class Strategy
def initialize(source)
@source = source
+ @package_priority_cache = {}
end
def next_package_and_version(unsatisfied)
@@ -17,10 +18,12 @@ module Bundler
def next_term_to_try_from(unsatisfied)
unsatisfied.min_by do |package, range|
- matching_versions = @source.versions_for(package, range)
- higher_versions = @source.versions_for(package, range.upper_invert)
+ @package_priority_cache[[package, range]] ||= begin
+ matching_versions = @source.versions_for(package, range)
+ higher_versions = @source.versions_for(package, range.upper_invert)
- [matching_versions.count <= 1 ? 0 : 1, higher_versions.count]
+ [matching_versions.count <= 1 ? 0 : 1, higher_versions.count]
+ end
end
end
diff --git a/lib/bundler/settings.rb b/lib/bundler/settings.rb
index cb48778083..857631a716 100644
--- a/lib/bundler/settings.rb
+++ b/lib/bundler/settings.rb
@@ -59,6 +59,7 @@ module Bundler
bin
cache_path
console
+ default_cli_command
gem.ci
gem.github_username
gem.linter
diff --git a/lib/bundler/settings/validator.rb b/lib/bundler/settings/validator.rb
index 9aa1627fb2..70a0ca36d4 100644
--- a/lib/bundler/settings/validator.rb
+++ b/lib/bundler/settings/validator.rb
@@ -74,6 +74,13 @@ module Bundler
fail!(key, value, "`#{other_key}` is current set to #{other_setting.inspect}", "the `#{conflicting.join("`, `")}` groups conflict")
end
end
+
+ rule %w[default_cli_command], "default_cli_command must be either 'install' or 'cli_help'" do |key, value, _settings|
+ valid_values = %w[install cli_help]
+ if !value.nil? && !valid_values.include?(value.to_s)
+ fail!(key, value, "must be one of: #{valid_values.join(", ")}")
+ end
+ end
end
end
end
diff --git a/lib/bundler/stub_specification.rb b/lib/bundler/stub_specification.rb
index 026f753d41..b353642b40 100644
--- a/lib/bundler/stub_specification.rb
+++ b/lib/bundler/stub_specification.rb
@@ -52,6 +52,7 @@ module Bundler
# This is defined directly to avoid having to loading the full spec
def missing_extensions?
+ return false if RUBY_ENGINE == "jruby"
return false if default_gem?
return false if extensions.empty?
return false if File.exist? gem_build_complete_path
diff --git a/lib/bundler/templates/newgem/newgem.gemspec.tt b/lib/bundler/templates/newgem/newgem.gemspec.tt
index 7799dbfd32..c705f9eac0 100644
--- a/lib/bundler/templates/newgem/newgem.gemspec.tt
+++ b/lib/bundler/templates/newgem/newgem.gemspec.tt
@@ -40,6 +40,9 @@ Gem::Specification.new do |spec|
# Uncomment to register a new dependency of your gem
# spec.add_dependency "example-gem", "~> 1.0"
+<%- if config[:ext] == 'rust' -%>
+ spec.add_dependency "rb_sys", "~> 0.9.91"
+<%- end -%>
<%- if config[:ext] == 'go' -%>
spec.add_dependency "go_gem", "~> 0.2"
<%- end -%>
diff --git a/lib/bundler/version.rb b/lib/bundler/version.rb
index 94fe327a29..7279965f70 100644
--- a/lib/bundler/version.rb
+++ b/lib/bundler/version.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
module Bundler
- VERSION = "4.0.9".freeze
+ VERSION = "4.0.10".freeze
def self.bundler_major_version
@bundler_major_version ||= gem_version.segments.first
diff --git a/lib/rubygems.rb b/lib/rubygems.rb
index 3bb9bf0ce9..d9d0fefdf8 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -9,7 +9,7 @@
require "rbconfig"
module Gem
- VERSION = "4.0.9"
+ VERSION = "4.0.10"
end
require_relative "rubygems/defaults"
@@ -192,8 +192,9 @@ module Gem
begin
spec.activate
rescue Gem::LoadError => e # this could fail due to gem dep collisions, go lax
+ name = spec.name
spec = Gem::Specification.find_unloaded_by_path(path)
- spec ||= Gem::Specification.find_by_name(spec.name)
+ spec ||= Gem::Specification.find_by_name(name)
if spec.nil?
raise e
else
@@ -1284,10 +1285,17 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
prefix_pattern = /^(#{prefix_group})/
end
+ native_extension_suffixes = Gem.dynamic_library_suffixes.reject(&:empty?)
+
spec.files.each do |file|
if new_format
file = file.sub(prefix_pattern, "")
- next unless $~
+ unless $~
+ # Also register native extension files (e.g. date_core.bundle)
+ # that are listed without require path prefix in the gemspec
+ next if file.include?("/")
+ next unless file.end_with?(*native_extension_suffixes)
+ end
end
spec.activate if already_loaded?(file)
diff --git a/lib/rubygems/commands/pristine_command.rb b/lib/rubygems/commands/pristine_command.rb
index 942b75fba1..10978c2af7 100644
--- a/lib/rubygems/commands/pristine_command.rb
+++ b/lib/rubygems/commands/pristine_command.rb
@@ -132,6 +132,11 @@ extensions will be restored.
specs = specs.select {|spec| spec.platform == RUBY_ENGINE || Gem::Platform.local === spec.platform || spec.platform == Gem::Platform::RUBY }
if specs.to_a.empty?
+ if options[:only_missing_extensions]
+ say "No gems with missing extensions to restore"
+ return
+ end
+
raise Gem::Exception,
"Failed to find gems #{options[:args]} #{options[:version]}"
end
diff --git a/lib/rubygems/package.rb b/lib/rubygems/package.rb
index 6b21ff1b95..f9c5676d80 100644
--- a/lib/rubygems/package.rb
+++ b/lib/rubygems/package.rb
@@ -552,6 +552,15 @@ EOM
tar = Gem::Package::TarReader.new gzio
yield tar
+ ensure
+ # Consume remaining gzip data to prevent the
+ # "attempt to close unfinished zstream; reset forced" warning
+ # when the GzipReader is closed with unconsumed compressed data.
+ begin
+ IO.copy_stream(gzio, IO::NULL)
+ rescue Zlib::GzipFile::Error, IOError
+ nil
+ end
end
end
diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb
index ac92f7f073..2db9352906 100644
--- a/lib/rubygems/specification.rb
+++ b/lib/rubygems/specification.rb
@@ -2071,6 +2071,7 @@ class Gem::Specification < Gem::BasicSpecification
# probably want to build_extensions
def missing_extensions?
+ return false if RUBY_ENGINE == "jruby"
return false if extensions.empty?
return false if default_gem?
return false if File.exist? gem_build_complete_path
diff --git a/lib/rubygems/stub_specification.rb b/lib/rubygems/stub_specification.rb
index 4f6a70ba4b..53b337ed85 100644
--- a/lib/rubygems/stub_specification.rb
+++ b/lib/rubygems/stub_specification.rb
@@ -140,6 +140,7 @@ class Gem::StubSpecification < Gem::BasicSpecification
end
def missing_extensions?
+ return false if RUBY_ENGINE == "jruby"
return false if default_gem?
return false if extensions.empty?
return false if File.exist? gem_build_complete_path
diff --git a/lib/rubygems/util/licenses.rb b/lib/rubygems/util/licenses.rb
index fbb7b55075..caf53d0b7e 100644
--- a/lib/rubygems/util/licenses.rb
+++ b/lib/rubygems/util/licenses.rb
@@ -27,6 +27,7 @@ class Gem::Licenses
AGPL-1.0-or-later
AGPL-3.0-only
AGPL-3.0-or-later
+ ALGLIB-Documentation
AMD-newlib
AMDPLPA
AML
@@ -48,6 +49,7 @@ class Gem::Licenses
Adobe-Display-PostScript
Adobe-Glyph
Adobe-Utopia
+ Advanced-Cryptics-Dictionary
Afmparse
Aladdin
Apache-1.0
@@ -61,6 +63,7 @@ class Gem::Licenses
Artistic-2.0
Artistic-dist
Aspell-RU
+ BOLA-1.1
BSD-1-Clause
BSD-2-Clause
BSD-2-Clause-Darwin
@@ -80,6 +83,7 @@ class Gem::Licenses
BSD-3-Clause-No-Nuclear-Warranty
BSD-3-Clause-Open-MPI
BSD-3-Clause-Sun
+ BSD-3-Clause-Tso
BSD-3-Clause-acpica
BSD-3-Clause-flex
BSD-4-Clause
@@ -90,6 +94,7 @@ class Gem::Licenses
BSD-Advertising-Acknowledgement
BSD-Attribution-HPND-disclaimer
BSD-Inferno-Nettverk
+ BSD-Mark-Modifications
BSD-Protection
BSD-Source-Code
BSD-Source-beginning-file
@@ -111,9 +116,11 @@ class Gem::Licenses
Borceux
Brian-Gladman-2-Clause
Brian-Gladman-3-Clause
+ Buddy
C-UDA-1.0
CAL-1.0
CAL-1.0-Combined-Work-Exception
+ CAPEC-tou
CATOSL-1.1
CC-BY-1.0
CC-BY-2.0
@@ -231,6 +238,9 @@ class Gem::Licenses
EPICS
EPL-1.0
EPL-2.0
+ ESA-PL-permissive-2.4
+ ESA-PL-strong-copyleft-2.4
+ ESA-PL-weak-copyleft-2.4
EUDatagrid
EUPL-1.0
EUPL-1.1
@@ -304,6 +314,7 @@ class Gem::Licenses
HPND-Markus-Kuhn
HPND-Netrek
HPND-Pbmplus
+ HPND-SMC
HPND-UC
HPND-UC-export-US
HPND-doc
@@ -318,6 +329,7 @@ class Gem::Licenses
HPND-sell-variant
HPND-sell-variant-MIT-disclaimer
HPND-sell-variant-MIT-disclaimer-rev
+ HPND-sell-variant-critical-systems
HTMLTIDY
HaskellReport
Hippocratic-2.1
@@ -330,6 +342,7 @@ class Gem::Licenses
IPL-1.0
ISC
ISC-Veillard
+ ISO-permission
ImageMagick
Imlib2
Info-ZIP
@@ -387,6 +400,7 @@ class Gem::Licenses
MIT-Festival
MIT-Khronos-old
MIT-Modern-Variant
+ MIT-STK
MIT-Wu
MIT-advertising
MIT-enna
@@ -395,6 +409,7 @@ class Gem::Licenses
MIT-testregex
MITNFA
MMIXware
+ MMPL-1.0.1
MPEG-SSG
MPL-1.0
MPL-1.1
@@ -426,6 +441,7 @@ class Gem::Licenses
NGPL
NICTA-1.0
NIST-PD
+ NIST-PD-TNT
NIST-PD-fallback
NIST-Software
NLOD-1.0
@@ -485,12 +501,15 @@ class Gem::Licenses
OPL-1.0
OPL-UK-3.0
OPUBL-1.0
+ OSC-1.0
OSET-PL-2.1
OSL-1.0
OSL-1.1
OSL-2.0
OSL-2.1
OSL-3.0
+ OSSP
+ OpenMDW-1.0
OpenPBS-2.3
OpenSSL
OpenSSL-standalone
@@ -501,6 +520,7 @@ class Gem::Licenses
PHP-3.01
PPL
PSF-2.0
+ ParaType-Free-Font-1.3
Parity-6.0.0
Parity-7.0.0
Pixar
@@ -529,6 +549,7 @@ class Gem::Licenses
SGI-B-1.1
SGI-B-2.0
SGI-OpenGL
+ SGMLUG-PM
SGP4
SHL-0.5
SHL-0.51
@@ -576,6 +597,7 @@ class Gem::Licenses
TTYP0
TU-Berlin-1.0
TU-Berlin-2.0
+ TekHVC
TermReadKey
ThirdEye
TrustedQSL
@@ -585,6 +607,7 @@ class Gem::Licenses
UPL-1.0
URT-RLE
Ubuntu-font-1.0
+ UnRAR
Unicode-3.0
Unicode-DFS-2015
Unicode-DFS-2016
@@ -596,15 +619,19 @@ class Gem::Licenses
VOSTROM
VSL-1.0
Vim
+ Vixie-Cron
W3C
W3C-19980720
W3C-20150513
+ WTFNMFPL
WTFPL
Watcom-1.0
Widget-Workshop
+ WordNet
Wsuipa
X11
X11-distribute-modifications-variant
+ X11-no-permit-persons
X11-swapped
XFree86-1.1
XSkat
@@ -645,6 +672,7 @@ class Gem::Licenses
gnuplot
gtkbook
hdparm
+ hyphen-bulgarian
iMatix
jove
libpng-1.6.35
@@ -734,6 +762,7 @@ class Gem::Licenses
CGAL-linking-exception
CLISP-exception-2.0
Classpath-exception-2.0
+ Classpath-exception-2.0-short
DigiRule-FOSS-exception
Digia-Qt-LGPL-exception-1.1
FLTK-exception
@@ -775,6 +804,7 @@ class Gem::Licenses
SHL-2.0
SHL-2.1
SWI-exception
+ Simple-Library-Usage-exception
Swift-exception
Texinfo-exception
UBDL-exception
@@ -788,12 +818,15 @@ class Gem::Licenses
gnu-javamail-exception
harbour-exception
i2p-gpl-java-exception
+ kvirc-openssl-exception
libpri-OpenH323-exception
mif-exception
mxml-exception
openvpn-openssl-exception
polyparse-exception
romic-exception
+ rsync-linking-exception
+ sqlitestudio-OpenSSL-exception
stunnel-exception
u-boot-exception-2.0
vsftpd-openssl-exception
diff --git a/lib/rubygems/version.rb b/lib/rubygems/version.rb
index 091858b757..c864af0b91 100644
--- a/lib/rubygems/version.rb
+++ b/lib/rubygems/version.rb
@@ -158,6 +158,7 @@ class Gem::Version
VERSION_PATTERN = '[0-9]+(?>\.[0-9a-zA-Z]+)*(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?' # :nodoc:
ANCHORED_VERSION_PATTERN = /\A\s*(#{VERSION_PATTERN})?\s*\z/ # :nodoc:
+ RADIX_OPT = [9_500, 3_500, 260_000, 22_227, 24].freeze # :nodoc:
##
# A string representation of this Version.
@@ -222,6 +223,7 @@ class Gem::Version
end
@version = -@version
@segments = nil
+ @sort_key = compute_sort_key
end
##
@@ -344,54 +346,58 @@ class Gem::Version
# other types may raise an exception.
def <=>(other)
- if String === other
- return unless self.class.correct?(other)
- return self <=> self.class.new(other)
- end
-
- return unless Gem::Version === other
- return 0 if @version == other.version || canonical_segments == other.canonical_segments
+ if Gem::Version === other
+ # Fast path for comparison when available.
+ if @sort_key && other.sort_key
+ return @sort_key <=> other.sort_key
+ end
- lhsegments = canonical_segments
- rhsegments = other.canonical_segments
+ return 0 if @version == other.version || canonical_segments == other.canonical_segments
- lhsize = lhsegments.size
- rhsize = rhsegments.size
- limit = (lhsize > rhsize ? rhsize : lhsize)
+ lhsegments = canonical_segments
+ rhsegments = other.canonical_segments
- i = 0
+ lhsize = lhsegments.size
+ rhsize = rhsegments.size
+ limit = (lhsize > rhsize ? rhsize : lhsize)
- while i < limit
- lhs = lhsegments[i]
- rhs = rhsegments[i]
- i += 1
+ i = 0
- next if lhs == rhs
- return -1 if String === lhs && Numeric === rhs
- return 1 if Numeric === lhs && String === rhs
+ while i < limit
+ lhs = lhsegments[i]
+ rhs = rhsegments[i]
+ i += 1
- return lhs <=> rhs
- end
+ next if lhs == rhs
+ return -1 if String === lhs && Numeric === rhs
+ return 1 if Numeric === lhs && String === rhs
- lhs = lhsegments[i]
+ return lhs <=> rhs
+ end
- if lhs.nil?
- rhs = rhsegments[i]
+ lhs = lhsegments[i]
- while i < rhsize
- return 1 if String === rhs
- return -1 unless rhs.zero?
- rhs = rhsegments[i += 1]
- end
- else
- while i < lhsize
- return -1 if String === lhs
- return 1 unless lhs.zero?
- lhs = lhsegments[i += 1]
+ if lhs.nil?
+ rhs = rhsegments[i]
+
+ while i < rhsize
+ return 1 if String === rhs
+ return -1 unless rhs.zero?
+ rhs = rhsegments[i += 1]
+ end
+ else
+ while i < lhsize
+ return -1 if String === lhs
+ return 1 unless lhs.zero?
+ lhs = lhsegments[i += 1]
+ end
end
- end
- 0
+ 0
+ elsif String === other
+ return unless self.class.correct?(other)
+ self <=> self.class.new(other)
+ end
end
# remove trailing zeros segments before first letter or at the end of the version
@@ -415,6 +421,24 @@ class Gem::Version
protected
+ attr_reader :sort_key # :nodoc:
+
+ def compute_sort_key
+ return if prerelease?
+
+ segments = canonical_segments
+ return if segments.size > 5
+
+ key = 0
+ RADIX_OPT.each_with_index do |radix, i|
+ seg = segments.fetch(i, 0)
+ return nil if seg >= radix
+ key = key * radix + seg
+ end
+
+ key
+ end
+
def _segments
# segments is lazy so it can pick up version values that come from
# old marshaled versions, which don't go through marshal_load.
diff --git a/spec/bundler/bundler/settings_spec.rb b/spec/bundler/bundler/settings_spec.rb
index 592db81e9b..39a8b36b3d 100644
--- a/spec/bundler/bundler/settings_spec.rb
+++ b/spec/bundler/bundler/settings_spec.rb
@@ -351,4 +351,25 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow
expect(settings["mirror.https://rubygems.org/"]).to eq("http://example-mirror.rubygems.org")
end
end
+
+ describe "default_cli_command validation" do
+ it "accepts 'install' as a valid value" do
+ expect { settings.set_local("default_cli_command", "install") }.not_to raise_error
+ end
+
+ it "accepts 'cli_help' as a valid value" do
+ expect { settings.set_local("default_cli_command", "cli_help") }.not_to raise_error
+ end
+
+ it "rejects invalid values" do
+ expect { settings.set_local("default_cli_command", "invalid") }.to raise_error(
+ Bundler::InvalidOption,
+ /Setting `default_cli_command` to "invalid" failed:\n - default_cli_command must be either 'install' or 'cli_help'\n - must be one of: install, cli_help/
+ )
+ end
+
+ it "accepts nil values" do
+ expect { settings.set_local("default_cli_command", nil) }.not_to raise_error
+ end
+ end
end
diff --git a/spec/bundler/bundler/stub_specification_spec.rb b/spec/bundler/bundler/stub_specification_spec.rb
index beb966b3ce..f2faa2ea64 100644
--- a/spec/bundler/bundler/stub_specification_spec.rb
+++ b/spec/bundler/bundler/stub_specification_spec.rb
@@ -49,10 +49,14 @@ RSpec.describe Bundler::StubSpecification do
expect(stub.missing_extensions?).to be false
end
- it "returns true if not manually_installed?" do
+ it "returns #{RUBY_ENGINE == "jruby" ? "false" : "true"} if not manually_installed?" do
stub = described_class.from_stub(with_bundler_stub_spec)
stub.installed_by_version = Gem::Version.new(1)
- expect(stub.missing_extensions?).to be true
+ if RUBY_ENGINE == "jruby"
+ expect(stub.missing_extensions?).to be false
+ else
+ expect(stub.missing_extensions?).to be true
+ end
end
end
diff --git a/spec/bundler/commands/newgem_spec.rb b/spec/bundler/commands/newgem_spec.rb
index 754dd3f31f..7a6c05fbb0 100644
--- a/spec/bundler/commands/newgem_spec.rb
+++ b/spec/bundler/commands/newgem_spec.rb
@@ -1736,8 +1736,9 @@ RSpec.describe "bundle gem" do
expect(bundled_app("#{gem_name}/ext/#{gem_name}/build.rs")).to exist
end
- it "includes rake-compiler constraint" do
+ it "includes rake-compiler and rb_sys gems constraint" do
expect(bundled_app("#{gem_name}/Gemfile").read).to include('gem "rake-compiler"')
+ expect(bundled_app("#{gem_name}/#{gem_name}.gemspec").read).to include('spec.add_dependency "rb_sys"')
end
it "depends on compile task for build" do
diff --git a/spec/bundler/install/gemfile/git_spec.rb b/spec/bundler/install/gemfile/git_spec.rb
index ed1c52f099..d31e3f4ba3 100644
--- a/spec/bundler/install/gemfile/git_spec.rb
+++ b/spec/bundler/install/gemfile/git_spec.rb
@@ -1404,7 +1404,7 @@ RSpec.describe "bundle install with git sources" do
File.open(git_reader.path.join("ext/foo.c"), "w") do |file|
file.write <<-C
#include "ruby.h"
- VALUE foo() { return INT2FIX(#{i}); }
+ VALUE foo(VALUE self) { return INT2FIX(#{i}); }
void Init_foo() { rb_define_global_function("foo", &foo, 0); }
C
end
diff --git a/spec/bundler/install/gemfile/specific_platform_spec.rb b/spec/bundler/install/gemfile/specific_platform_spec.rb
index 448800d578..22a3f8214f 100644
--- a/spec/bundler/install/gemfile/specific_platform_spec.rb
+++ b/spec/bundler/install/gemfile/specific_platform_spec.rb
@@ -535,6 +535,41 @@ RSpec.describe "bundle install with specific platforms" do
expect(err).to include(error_message).once
end
+ it "shows a platform mismatch hint when the current platform is not in the lockfile's platforms" do
+ build_repo4 do
+ build_gem("sorbet-static", "0.5.6433") {|s| s.platform = "x86_64-linux-musl" }
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "sorbet-static", "0.5.6433"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ sorbet-static (0.5.6433-x86_64-linux-musl)
+
+ PLATFORMS
+ x86_64-linux-musl
+
+ DEPENDENCIES
+ sorbet-static (= 0.5.6433)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "x86_64-linux" do
+ bundle "install", raise_on_error: false
+ end
+
+ expect(err).to include("Your current platform (x86_64-linux) is not included in the lockfile's platforms (x86_64-linux-musl)")
+ expect(err).to include("bundle lock --add-platform x86_64-linux")
+ end
+
it "does not resolve if the current platform does not match any of available platform specific variants for a transitive dependency" do
build_repo4 do
build_gem("sorbet", "0.5.6433") {|s| s.add_dependency "sorbet-static", "= 0.5.6433" }
diff --git a/spec/bundler/install/gems/resolving_spec.rb b/spec/bundler/install/gems/resolving_spec.rb
index f59bb70c7b..e6a395a669 100644
--- a/spec/bundler/install/gems/resolving_spec.rb
+++ b/spec/bundler/install/gems/resolving_spec.rb
@@ -440,7 +440,9 @@ RSpec.describe "bundle install with install-time dependencies" do
The source contains the following gems matching 'sorbet-static (= 0.5.10554)':
* sorbet-static-0.5.10554-universal-darwin-21
E
- expect(err).to end_with(nice_error)
+ expect(err).to include(nice_error)
+ expect(err).to include("Your current platform (aarch64-linux) is not included in the lockfile's platforms (arm64-darwin-21)")
+ expect(err).to include("bundle lock --add-platform aarch64-linux")
end
end
diff --git a/spec/bundler/realworld/fixtures/tapioca/Gemfile.lock b/spec/bundler/realworld/fixtures/tapioca/Gemfile.lock
index f98b1b01da..c1de0f7769 100644
--- a/spec/bundler/realworld/fixtures/tapioca/Gemfile.lock
+++ b/spec/bundler/realworld/fixtures/tapioca/Gemfile.lock
@@ -46,4 +46,4 @@ DEPENDENCIES
tapioca
BUNDLED WITH
- 4.0.9
+ 4.0.10
diff --git a/spec/bundler/realworld/fixtures/warbler/Gemfile.lock b/spec/bundler/realworld/fixtures/warbler/Gemfile.lock
index 9d797c2547..a27690c593 100644
--- a/spec/bundler/realworld/fixtures/warbler/Gemfile.lock
+++ b/spec/bundler/realworld/fixtures/warbler/Gemfile.lock
@@ -36,4 +36,4 @@ DEPENDENCIES
warbler!
BUNDLED WITH
- 4.0.9
+ 4.0.10
diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb
index 74c8953904..f3d9ef95d6 100644
--- a/test/rubygems/test_gem.rb
+++ b/test/rubygems/test_gem.rb
@@ -1213,6 +1213,28 @@ class TestGem < Gem::TestCase
assert Gem.try_activate("b"), "try_activate should still return true"
end
+ def test_try_activate_does_not_raise_no_method_error_on_activation_conflict
+ a1 = util_spec "a", "1.0" do |s|
+ s.files << "lib/a/old.rb"
+ end
+
+ a2 = util_spec "a", "2.0" do |s|
+ s.files << "lib/a/old.rb"
+ s.files << "lib/a/new_file.rb"
+ end
+
+ install_specs a1, a2
+
+ # Activate the older version
+ gem "a", "= 1.0"
+
+ # try_activate a file only in the newer version should not raise
+ # NoMethodError on nil (https://bugs.ruby-lang.org/issues/21954)
+ assert_nothing_raised do
+ Gem.try_activate("a/new_file")
+ end
+ end
+
def test_spec_order_is_consistent
b1 = util_spec "b", "1.0"
b2 = util_spec "b", "2.0"
@@ -1282,10 +1304,14 @@ class TestGem < Gem::TestCase
refute Gem.try_activate "nonexistent"
end
- expected = "Ignoring ext-1 because its extensions are not built. " \
- "Try: gem pristine ext --version 1\n"
+ if RUBY_ENGINE == "jruby"
+ assert_equal "", err
+ else
+ expected = "Ignoring ext-1 because its extensions are not built. " \
+ "Try: gem pristine ext --version 1\n"
- assert_equal expected, err
+ assert_equal expected, err
+ end
end
def test_self_use_paths_with_nils
@@ -1633,6 +1659,27 @@ class TestGem < Gem::TestCase
assert_nil Gem.find_unresolved_default_spec("README")
end
+ def test_register_default_spec_new_style_with_native_extension
+ Gem.clear_default_specs
+
+ dlext = RbConfig::CONFIG["DLEXT"]
+
+ new_style = Gem::Specification.new do |spec|
+ spec.name = "my_ext"
+ spec.version = "1.0"
+ spec.files = ["lib/my_ext.rb", "my_ext_core.#{dlext}", "ext/my_ext/my_ext_core.c", "README.md"]
+ spec.require_paths = ["lib"]
+ end
+
+ Gem.register_default_spec new_style
+
+ assert_equal new_style, Gem.find_unresolved_default_spec("my_ext.rb")
+ assert_equal new_style, Gem.find_unresolved_default_spec("my_ext_core")
+ assert_equal new_style, Gem.find_unresolved_default_spec("my_ext_core.#{dlext}")
+ assert_nil Gem.find_unresolved_default_spec("ext/my_ext/my_ext_core.c")
+ assert_nil Gem.find_unresolved_default_spec("README.md")
+ end
+
def test_register_default_spec_old_style_with_folder_starting_with_lib
Gem.clear_default_specs
diff --git a/test/rubygems/test_gem_commands_owner_command.rb b/test/rubygems/test_gem_commands_owner_command.rb
index d8d220243c..dc3391fd42 100644
--- a/test/rubygems/test_gem_commands_owner_command.rb
+++ b/test/rubygems/test_gem_commands_owner_command.rb
@@ -399,6 +399,7 @@ EOF
end
def test_with_webauthn_enabled_failure
+ pend "Flaky on TruffleRuby" if RUBY_ENGINE == "truffleruby"
response_success = "Owner added successfully."
server = Gem::MockTCPServer.new
error = Gem::WebauthnVerificationError.new("Something went wrong")
diff --git a/test/rubygems/test_gem_commands_pristine_command.rb b/test/rubygems/test_gem_commands_pristine_command.rb
index e9c4d32945..0ea140897c 100644
--- a/test/rubygems/test_gem_commands_pristine_command.rb
+++ b/test/rubygems/test_gem_commands_pristine_command.rb
@@ -248,7 +248,13 @@ class TestGemCommandsPristineCommand < Gem::TestCase
end
refute_includes @ui.output, "Restored #{a.full_name}"
- assert_includes @ui.output, "Restored #{b.full_name}"
+
+ if Gem.java_platform?
+ refute_includes @ui.output, "Restored #{b.full_name}"
+ assert_includes @ui.output, "No gems with missing extensions to restore"
+ else
+ assert_includes @ui.output, "Restored #{b.full_name}"
+ end
end
def test_execute_no_extension
diff --git a/test/rubygems/test_gem_commands_yank_command.rb b/test/rubygems/test_gem_commands_yank_command.rb
index 73fd177243..457a0e65c8 100644
--- a/test/rubygems/test_gem_commands_yank_command.rb
+++ b/test/rubygems/test_gem_commands_yank_command.rb
@@ -141,6 +141,7 @@ class TestGemCommandsYankCommand < Gem::TestCase
end
def test_with_webauthn_enabled_failure
+ pend "Flaky on TruffleRuby" if RUBY_ENGINE == "truffleruby"
server = Gem::MockTCPServer.new
error = Gem::WebauthnVerificationError.new("Something went wrong")
diff --git a/test/rubygems/test_gem_specification.rb b/test/rubygems/test_gem_specification.rb
index 7675ade415..f66b05b564 100644
--- a/test/rubygems/test_gem_specification.rb
+++ b/test/rubygems/test_gem_specification.rb
@@ -1578,13 +1578,21 @@ dependencies: []
ext_spec
_, err = capture_output do
- refute @ext.contains_requirable_file? "nonexistent"
+ if RUBY_ENGINE == "jruby"
+ refute @ext.ignored?
+ else
+ refute @ext.contains_requirable_file? "nonexistent"
+ end
end
- expected = "Ignoring ext-1 because its extensions are not built. " \
- "Try: gem pristine ext --version 1\n"
+ if RUBY_ENGINE == "jruby"
+ assert_equal "", err
+ else
+ expected = "Ignoring ext-1 because its extensions are not built. " \
+ "Try: gem pristine ext --version 1\n"
- assert_equal expected, err
+ assert_equal expected, err
+ end
end
def test_contains_requirable_file_eh_extension_java_platform
@@ -3953,7 +3961,11 @@ end
def test_missing_extensions_eh
ext_spec
- assert @ext.missing_extensions?
+ if RUBY_ENGINE == "jruby"
+ refute @ext.missing_extensions?
+ else
+ assert @ext.missing_extensions?
+ end
extconf_rb = File.join @ext.gem_dir, @ext.extensions.first
FileUtils.mkdir_p File.dirname extconf_rb
diff --git a/test/rubygems/test_gem_stub_specification.rb b/test/rubygems/test_gem_stub_specification.rb
index 4b2d4c570a..f04b36dbf8 100644
--- a/test/rubygems/test_gem_stub_specification.rb
+++ b/test/rubygems/test_gem_stub_specification.rb
@@ -68,13 +68,21 @@ class TestStubSpecification < Gem::TestCase
def test_contains_requirable_file_eh_extension
stub_with_extension do |stub|
_, err = capture_output do
- refute stub.contains_requirable_file? "nonexistent"
+ if RUBY_ENGINE == "jruby"
+ refute stub.ignored?
+ else
+ refute stub.contains_requirable_file? "nonexistent"
+ end
end
- expected = "Ignoring stub_e-2 because its extensions are not built. " \
- "Try: gem pristine stub_e --version 2\n"
+ if RUBY_ENGINE == "jruby"
+ assert_equal "", err
+ else
+ expected = "Ignoring stub_e-2 because its extensions are not built. " \
+ "Try: gem pristine stub_e --version 2\n"
- assert_equal expected, err
+ assert_equal expected, err
+ end
end
end
@@ -137,7 +145,11 @@ class TestStubSpecification < Gem::TestCase
end
end
- assert stub.missing_extensions?
+ if RUBY_ENGINE == "jruby"
+ refute stub.missing_extensions?
+ else
+ assert stub.missing_extensions?
+ end
stub.build_extensions
diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb
index 3987c620d0..5cd4228f2f 100644
--- a/test/rubygems/test_gem_version.rb
+++ b/test/rubygems/test_gem_version.rb
@@ -200,6 +200,51 @@ class TestGemVersion < Gem::TestCase
assert_less_than "1.0.0-1", "1"
end
+ def test_sort_key_is_computed_on_regular_release
+ refute_nil v("9.8.7").send(:sort_key)
+ end
+
+ def test_sort_key_is_computed_on_security_release
+ refute_nil v("9.8.7.1").send(:sort_key)
+ end
+
+ def test_sort_key_is_not_computed_on_prerelease
+ assert_nil v("9.8.7.pre1").send(:sort_key)
+ end
+
+ def test_sort_key_is_not_computed_on_version_with_more_segments
+ assert_nil v("1.1.1.1.1.1.1").send(:sort_key)
+ end
+
+ def test_sort_key_is_not_computed_on_huge_numbers
+ assert_nil v("2.30.1.250000").send(:sort_key)
+ end
+
+ def test_sort_key_on_timestamped_version
+ a = v("1.0.0")
+ b = v("0.0.1.20220404083012")
+
+ assert_operator a, :>, b
+ end
+
+ def test_sort_key_when_segment_is_higher_than_radix
+ a = v("0.7.0")
+ b = v("0.6.63000")
+
+ assert_operator(a, :>, b)
+ end
+
+ def test_sort_key_is_used_for_comparison
+ a = v("18.0.1")
+ b = v("18.0.2")
+
+ # Ensure the slow path isn't getting hit
+ a.instance_variable_set(:@version, nil)
+ a.instance_variable_set(:@canonical_segments, nil)
+
+ assert_operator(a, :<, b)
+ end
+
# modifying the segments of a version should not affect the segments of the cached version object
def test_segments
v("9.8.7").segments[2] += 1
diff --git a/tool/bundler/dev_gems.rb.lock b/tool/bundler/dev_gems.rb.lock
index 7212b75fde..f6c13704ad 100644
--- a/tool/bundler/dev_gems.rb.lock
+++ b/tool/bundler/dev_gems.rb.lock
@@ -129,4 +129,4 @@ CHECKSUMS
turbo_tests (2.2.5) sha256=3fa31497d12976d11ccc298add29107b92bda94a90d8a0a5783f06f05102509f
BUNDLED WITH
- 4.0.9
+ 4.0.10
diff --git a/tool/bundler/rubocop_gems.rb.lock b/tool/bundler/rubocop_gems.rb.lock
index 8d5a6f25cd..422a886911 100644
--- a/tool/bundler/rubocop_gems.rb.lock
+++ b/tool/bundler/rubocop_gems.rb.lock
@@ -156,4 +156,4 @@ CHECKSUMS
unicode-emoji (4.2.0) sha256=519e69150f75652e40bf736106cfbc8f0f73aa3fb6a65afe62fefa7f80b0f80f
BUNDLED WITH
- 4.0.9
+ 4.0.10
diff --git a/tool/bundler/standard_gems.rb.lock b/tool/bundler/standard_gems.rb.lock
index b6f7aa209e..bbc83b79ce 100644
--- a/tool/bundler/standard_gems.rb.lock
+++ b/tool/bundler/standard_gems.rb.lock
@@ -176,4 +176,4 @@ CHECKSUMS
unicode-emoji (4.2.0) sha256=519e69150f75652e40bf736106cfbc8f0f73aa3fb6a65afe62fefa7f80b0f80f
BUNDLED WITH
- 4.0.9
+ 4.0.10
diff --git a/tool/bundler/test_gems.rb.lock b/tool/bundler/test_gems.rb.lock
index 8a257ffd78..0688ecb31b 100644
--- a/tool/bundler/test_gems.rb.lock
+++ b/tool/bundler/test_gems.rb.lock
@@ -103,4 +103,4 @@ CHECKSUMS
tilt (2.6.1) sha256=35a99bba2adf7c1e362f5b48f9b581cce4edfba98117e34696dde6d308d84770
BUNDLED WITH
- 4.0.9
+ 4.0.10