summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/rubygems/specification_policy.rb28
-rw-r--r--test/rubygems/test_gem_specification.rb55
2 files changed, 83 insertions, 0 deletions
diff --git a/lib/rubygems/specification_policy.rb b/lib/rubygems/specification_policy.rb
index 0fcb635394..8ab82ee4a9 100644
--- a/lib/rubygems/specification_policy.rb
+++ b/lib/rubygems/specification_policy.rb
@@ -476,6 +476,7 @@ or set it to nil if you don't want to specify a license.
validate_rake_extensions(builder)
validate_rust_extensions(builder)
+ validate_extension_require_relative
end
def validate_rust_extensions(builder) # :nodoc:
@@ -496,6 +497,33 @@ You have specified rake based extension, but rake is not added as runtime depend
WARNING
end
+ def validate_extension_require_relative # :nodoc:
+ return unless @specification.extensions.any?
+
+ require_paths = @specification.require_paths
+
+ @specification.files.each do |rb_file|
+ next unless rb_file.end_with?(".rb")
+ next unless require_paths.any? {|rp| rb_file.start_with?("#{rp}/") }
+ next unless File.file?(rb_file)
+
+ File.foreach(rb_file).with_index(1) do |line, lineno|
+ next unless line =~ /^\s*require_relative\s+["']([^"']+)["']/
+
+ required_path = Regexp.last_match(1)
+ resolved = File.join(File.dirname(rb_file), required_path)
+
+ next if @specification.files.any? {|f| f == "#{resolved}.rb" || f == resolved }
+
+ warning <<~WARNING
+ #{rb_file}:#{lineno} uses `require_relative "#{required_path}"` to load a compiled extension.
+ This will break in RubyGems 4.2, which will stop copying compiled extensions into the gem's lib directory.
+ Use `require` instead of `require_relative` to load compiled extensions.
+ WARNING
+ end
+ end
+ end
+
def validate_unique_links
links = @specification.metadata.slice(*METADATA_LINK_KEYS)
grouped = links.group_by {|_key, uri| uri }
diff --git a/test/rubygems/test_gem_specification.rb b/test/rubygems/test_gem_specification.rb
index 7675ade415..cf01a40b8c 100644
--- a/test/rubygems/test_gem_specification.rb
+++ b/test/rubygems/test_gem_specification.rb
@@ -2887,6 +2887,61 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use:
end
end
+ def test_validate_extension_require_relative_warning
+ util_setup_validate
+
+ Dir.chdir @tempdir do
+ @a1.extensions = ["ext/a/extconf.rb"]
+ @a1.files = %w[lib/code.rb lib/a.rb ext/a/extconf.rb]
+
+ File.write File.join("lib", "a.rb"), 'require_relative "a/a"'
+
+ use_ui @ui do
+ @a1.validate
+ end
+
+ assert_match(%r{require_relative "a/a"}, @ui.error)
+ assert_match(/will break in RubyGems 4\.2/, @ui.error)
+ assert_match(/Use `require` instead of `require_relative`/, @ui.error)
+ end
+ end
+
+ def test_validate_extension_require_relative_no_warning_when_rb_exists
+ util_setup_validate
+
+ Dir.chdir @tempdir do
+ @a1.extensions = ["ext/a/extconf.rb"]
+ @a1.files = %w[lib/code.rb lib/a.rb lib/a/a.rb ext/a/extconf.rb]
+
+ FileUtils.mkdir_p File.join("lib", "a")
+ File.write File.join("lib", "a.rb"), 'require_relative "a/a"'
+ File.write File.join("lib", "a", "a.rb"), ""
+
+ use_ui @ui do
+ @a1.validate
+ end
+
+ refute_match(/require_relative/, @ui.error)
+ end
+ end
+
+ def test_validate_extension_require_relative_no_warning_without_extensions
+ util_setup_validate
+
+ Dir.chdir @tempdir do
+ @a1.extensions = []
+ @a1.files = %w[lib/code.rb lib/a.rb]
+
+ File.write File.join("lib", "a.rb"), 'require_relative "a/a"'
+
+ use_ui @ui do
+ @a1.validate
+ end
+
+ refute_match(/require_relative/, @ui.error)
+ end
+ end
+
def test_validate_description
util_setup_validate