[rubygems/rubygems] Fix specs with missing extensions getting activated

https://github.com/rubygems/rubygems/commit/c80998a22a
This commit is contained in:
David Rodríguez 2024-10-04 18:21:41 +02:00 committed by git
parent f63873e7a2
commit 3fdf0e7e6d
7 changed files with 88 additions and 37 deletions

View File

@ -269,6 +269,16 @@ module Gem
end end
out out
end end
if Gem.rubygems_version < Gem::Version.new("3.5.22")
module FilterIgnoredSpecs
def matching_specs(platform_only = false)
super.reject(&:ignored?)
end
end
prepend FilterIgnoredSpecs
end
end end
require "rubygems/platform" require "rubygems/platform"
@ -374,6 +384,15 @@ module Gem
end end
end end
end end
remove_method :ignored? if new.respond_to?(:ignored?)
# Same as RubyGems, but without warnings, because Bundler prints its own warnings
def ignored?
return @ignored unless @ignored.nil?
@ignored = missing_extensions?
end
end end
require "rubygems/name_tuple" require "rubygems/name_tuple"

View File

@ -357,10 +357,7 @@ module Bundler
@installed_specs ||= Index.build do |idx| @installed_specs ||= Index.build do |idx|
Bundler.rubygems.installed_specs.reverse_each do |spec| Bundler.rubygems.installed_specs.reverse_each do |spec|
spec.source = self spec.source = self
if spec.missing_extensions? next if spec.ignored?
Bundler.ui.debug "Source #{self} is ignoring #{spec} because it is missing extensions"
next
end
idx << spec idx << spec
end end
end end

View File

@ -28,6 +28,17 @@ module Bundler
# @!group Stub Delegates # @!group Stub Delegates
def ignored?
return @ignored unless @ignored.nil?
@ignored = missing_extensions?
return false unless @ignored
warn "Source #{source} is ignoring #{self} because it is missing extensions"
true
end
def manually_installed? def manually_installed?
# This is for manually installed gems which are gems that were fixed in place after a # This is for manually installed gems which are gems that were fixed in place after a
# failed installation. Once the issue was resolved, the user then manually created # failed installation. Once the issue was resolved, the user then manually created

View File

@ -71,18 +71,7 @@ class Gem::BasicSpecification
# Return true if this spec can require +file+. # Return true if this spec can require +file+.
def contains_requirable_file?(file) def contains_requirable_file?(file)
if @ignored return false if ignored?
return false
elsif missing_extensions?
@ignored = true
if platform == Gem::Platform::RUBY || Gem::Platform.local === platform
warn "Ignoring #{full_name} because its extensions are not built. " \
"Try: gem pristine #{name} --version #{version}"
end
return false
end
is_soext = file.end_with?(".so", ".o") is_soext = file.end_with?(".so", ".o")
@ -93,6 +82,23 @@ class Gem::BasicSpecification
end end
end end
##
# Return true if this spec should be ignored because it's missing extensions.
def ignored?
return @ignored unless @ignored.nil?
@ignored = missing_extensions?
return false unless @ignored
if platform == Gem::Platform::RUBY || Gem::Platform.local === platform
warn "Ignoring #{full_name} because its extensions are not built. " \
"Try: gem pristine #{name} --version #{version}"
end
true
end
def default_gem? def default_gem?
loaded_from && loaded_from &&
File.dirname(loaded_from) == Gem.default_specifications_dir File.dirname(loaded_from) == Gem.default_specifications_dir

View File

@ -279,7 +279,7 @@ class Gem::Dependency
end end
end end
matches matches.reject(&:ignored?)
end end
## ##

View File

@ -142,7 +142,6 @@ RSpec.shared_examples "bundle install --standalone" do
describe "with default gems and a lockfile", :ruby_repo do describe "with default gems and a lockfile", :ruby_repo do
before do before do
necessary_system_gems = ["tsort --version 0.1.0"] necessary_system_gems = ["tsort --version 0.1.0"]
necessary_system_gems += ["etc --version 1.4.3"]
realworld_system_gems(*necessary_system_gems) realworld_system_gems(*necessary_system_gems)
end end
@ -173,7 +172,16 @@ RSpec.shared_examples "bundle install --standalone" do
bundle "lock", dir: cwd bundle "lock", dir: cwd
bundle "config set --local path #{bundled_app("bundle")}" bundle "config set --local path #{bundled_app("bundle")}"
bundle :install, standalone: true, dir: cwd, env: { "BUNDLER_GEM_DEFAULT_DIR" => system_gem_path.to_s }
# Make sure rubyinstaller2 does not activate the etc gem in its
# `operating_system.rb` file, but completely disable that since it's not
# really needed here
if Gem.win_platform?
FileUtils.mkdir_p bundled_app("rubygems/defaults")
FileUtils.touch bundled_app("rubygems/defaults/operating_system.rb")
end
bundle :install, standalone: true, dir: cwd, env: { "BUNDLER_GEM_DEFAULT_DIR" => system_gem_path.to_s }, load_path: bundled_app
load_path_lines = bundled_app("bundle/bundler/setup.rb").read.split("\n").select {|line| line.start_with?("$:.unshift") } load_path_lines = bundled_app("bundle/bundler/setup.rb").read.split("\n").select {|line| line.start_with?("$:.unshift") }
@ -184,27 +192,35 @@ RSpec.shared_examples "bundle install --standalone" do
end end
it "works for gems with extensions and points to the vendored copies, not to the default copies" do it "works for gems with extensions and points to the vendored copies, not to the default copies" do
necessary_gems_in_bundle_path = ["optparse --version 0.1.1", "psych --version 3.3.2", "logger --version 1.4.3", "etc --version 1.4.3", "stringio --version 3.1.0", "shellwords --version 0.2.0", "open3 --version 0.2.1"]
necessary_gems_in_bundle_path += ["yaml --version 0.1.1"] if Gem.rubygems_version < Gem::Version.new("3.4.a")
realworld_system_gems(*necessary_gems_in_bundle_path, path: scoped_gem_path(bundled_app("bundle")))
build_gem "baz", "1.0.0", to_system: true, default: true, &:add_c_extension
build_repo4 do
build_gem "baz", "1.0.0", &:add_c_extension
end
gemfile <<-G
source "https://gem.repo4"
gem "baz"
G
bundle "config set --local path #{bundled_app("bundle")}"
simulate_platform "arm64-darwin-23" do simulate_platform "arm64-darwin-23" do
necessary_gems_in_bundle_path = ["optparse --version 0.1.1", "psych --version 3.3.2", "logger --version 1.4.3", "etc --version 1.4.3", "stringio --version 3.1.0", "shellwords --version 0.2.0", "open3 --version 0.2.1"]
necessary_gems_in_bundle_path += ["yaml --version 0.1.1"] if Gem.rubygems_version < Gem::Version.new("3.4.a")
realworld_system_gems(*necessary_gems_in_bundle_path, path: scoped_gem_path(bundled_app("bundle")))
build_gem "baz", "1.0.0", to_system: true, default: true, &:add_c_extension
build_repo4 do
build_gem "baz", "1.0.0", &:add_c_extension
end
gemfile <<-G
source "https://gem.repo4"
gem "baz"
G
bundle "config set --local path #{bundled_app("bundle")}"
bundle "lock", dir: cwd bundle "lock", dir: cwd
bundle :install, standalone: true, dir: cwd, env: { "BUNDLER_GEM_DEFAULT_DIR" => system_gem_path.to_s } # Make sure rubyinstaller2 does not activate the etc gem in its
# `operating_system.rb` file, but completely disable that since it's not
# really needed here
if Gem.win_platform?
FileUtils.mkdir_p bundled_app("rubygems/defaults")
FileUtils.touch bundled_app("rubygems/defaults/operating_system.rb")
end
bundle :install, standalone: true, dir: cwd, env: { "BUNDLER_GEM_DEFAULT_DIR" => system_gem_path.to_s }, load_path: bundled_app
end end
load_path_lines = bundled_app("bundle/bundler/setup.rb").read.split("\n").select {|line| line.start_with?("$:.unshift") } load_path_lines = bundled_app("bundle/bundler/setup.rb").read.split("\n").select {|line| line.start_with?("$:.unshift") }

View File

@ -76,9 +76,11 @@ module Spec
requires = options.delete(:requires) || [] requires = options.delete(:requires) || []
dir = options.delete(:dir) || bundled_app dir = options.delete(:dir) || bundled_app
custom_load_path = options.delete(:load_path)
load_path = [] load_path = []
load_path << spec_dir load_path << spec_dir
load_path << custom_load_path if custom_load_path
build_ruby_options = { load_path: load_path, requires: requires, env: env } build_ruby_options = { load_path: load_path, requires: requires, env: env }
build_ruby_options.merge!(artifice: options.delete(:artifice)) if options.key?(:artifice) build_ruby_options.merge!(artifice: options.delete(:artifice)) if options.key?(:artifice)