summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornagachika <nagachika@ruby-lang.org>2021-01-30 20:43:44 +0900
committernagachika <nagachika@ruby-lang.org>2021-01-30 20:43:44 +0900
commit99b4f20fd65075d2d9ee02f8c7a6b5d6a914ce31 (patch)
tree873aba7eced9f3ec7938c2ef4efe1dff8f171b40
parentd0693391103672b7fc3976e5ae8ae414059b3e97 (diff)
Merge RubyGems-3.1.6 [Bug #16926]
https://github.com/ruby/ruby/pull/4122
-rw-r--r--lib/rubygems.rb23
-rw-r--r--lib/rubygems/core_ext/kernel_require.rb60
-rw-r--r--lib/rubygems/test_case.rb1
-rw-r--r--test/rubygems/test_bundled_ca.rb1
-rw-r--r--test/rubygems/test_kernel.rb19
-rw-r--r--test/rubygems/test_require.rb104
-rw-r--r--version.h8
7 files changed, 167 insertions, 49 deletions
diff --git a/lib/rubygems.rb b/lib/rubygems.rb
index d8b4dc74f2..f8ca70385e 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -9,7 +9,7 @@
require 'rbconfig'
module Gem
- VERSION = "3.1.5".freeze
+ VERSION = "3.1.6".freeze
end
# Must be first since it unloads the prelude from 1.9.2
@@ -659,22 +659,25 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
index = $LOAD_PATH.index RbConfig::CONFIG['sitelibdir']
- index
+ index || 0
+ end
+
+ ##
+ # The number of paths in the `$LOAD_PATH` from activated gems. Used to
+ # prioritize `-I` and `ENV['RUBYLIB`]` entries during `require`.
+
+ def self.activated_gem_paths
+ @activated_gem_paths ||= 0
end
##
# Add a list of paths to the $LOAD_PATH at the proper place.
def self.add_to_load_path(*paths)
- insert_index = load_path_insert_index
+ @activated_gem_paths = activated_gem_paths + paths.size
- if insert_index
- # gem directories must come after -I and ENV['RUBYLIB']
- $LOAD_PATH.insert(insert_index, *paths)
- else
- # we are probably testing in core, -I and RUBYLIB don't apply
- $LOAD_PATH.unshift(*paths)
- end
+ # gem directories must come after -I and ENV['RUBYLIB']
+ $LOAD_PATH.insert(Gem.load_path_insert_index, *paths)
end
@yaml_loaded = false
diff --git a/lib/rubygems/core_ext/kernel_require.rb b/lib/rubygems/core_ext/kernel_require.rb
index 60f4d18712..115ae0cb50 100644
--- a/lib/rubygems/core_ext/kernel_require.rb
+++ b/lib/rubygems/core_ext/kernel_require.rb
@@ -39,49 +39,40 @@ module Kernel
path = path.to_path if path.respond_to? :to_path
- # Ensure -I beats a default gem
- # https://github.com/rubygems/rubygems/pull/1868
- resolved_path = begin
- rp = nil
- $LOAD_PATH[0...Gem.load_path_insert_index || -1].each do |lp|
- safe_lp = lp.dup.tap(&Gem::UNTAINT)
- begin
- if File.symlink? safe_lp # for backward compatibility
- next
- end
- rescue SecurityError
- RUBYGEMS_ACTIVATION_MONITOR.exit
- raise
- end
-
+ if spec = Gem.find_unresolved_default_spec(path)
+ # Ensure -I beats a default gem
+ resolved_path = begin
+ rp = nil
+ load_path_check_index = Gem.load_path_insert_index - Gem.activated_gem_paths
Gem.suffixes.each do |s|
- full_path = File.expand_path(File.join(safe_lp, "#{path}#{s}"))
- if File.file?(full_path)
- rp = full_path
- break
+ $LOAD_PATH[0...load_path_check_index].each do |lp|
+ safe_lp = lp.dup.tap(&Gem::UNTAINT)
+ begin
+ if File.symlink? safe_lp # for backward compatibility
+ next
+ end
+ rescue SecurityError
+ RUBYGEMS_ACTIVATION_MONITOR.exit
+ raise
+ end
+
+ full_path = File.expand_path(File.join(safe_lp, "#{path}#{s}"))
+ if File.file?(full_path)
+ rp = full_path
+ break
+ end
end
+ break if rp
end
- break if rp
- end
- rp
- end
-
- if resolved_path
- begin
- RUBYGEMS_ACTIVATION_MONITOR.exit
- return gem_original_require(resolved_path)
- rescue LoadError
- RUBYGEMS_ACTIVATION_MONITOR.enter
+ rp
end
- end
- if spec = Gem.find_unresolved_default_spec(path)
begin
Kernel.send(:gem, spec.name, Gem::Requirement.default_prerelease)
rescue Exception
RUBYGEMS_ACTIVATION_MONITOR.exit
raise
- end
+ end unless resolved_path
end
# If there are no unresolved deps, then we can use just try
@@ -157,8 +148,7 @@ module Kernel
RUBYGEMS_ACTIVATION_MONITOR.enter
begin
- if load_error.message.start_with?("Could not find") or
- (load_error.message.end_with?(path) and Gem.try_activate(path))
+ if load_error.message.end_with?(path) and Gem.try_activate(path)
require_again = true
end
ensure
diff --git a/lib/rubygems/test_case.rb b/lib/rubygems/test_case.rb
index 89403206f9..c6f5f29d4e 100644
--- a/lib/rubygems/test_case.rb
+++ b/lib/rubygems/test_case.rb
@@ -385,6 +385,7 @@ class Gem::TestCase < (defined?(Minitest::Test) ? Minitest::Test : MiniTest::Uni
Gem::Security.reset
Gem.loaded_specs.clear
+ Gem.instance_variable_set(:@activated_gem_paths, 0)
Gem.clear_default_specs
Bundler.reset!
diff --git a/test/rubygems/test_bundled_ca.rb b/test/rubygems/test_bundled_ca.rb
index 9538d6b898..4224755562 100644
--- a/test/rubygems/test_bundled_ca.rb
+++ b/test/rubygems/test_bundled_ca.rb
@@ -62,5 +62,6 @@ if ENV["CI"] || ENV["TEST_SSL"]
def test_accessing_new_index
assert_https('index.rubygems.org')
end
+
end
end
diff --git a/test/rubygems/test_kernel.rb b/test/rubygems/test_kernel.rb
index b9f9b5e254..daf9b57d7c 100644
--- a/test/rubygems/test_kernel.rb
+++ b/test/rubygems/test_kernel.rb
@@ -91,6 +91,25 @@ class TestKernel < Gem::TestCase
refute $:.any? { |p| %r{a-1/bin} =~ p }
end
+ def test_gem_failing_inside_require_doesnt_cause_double_exceptions
+ File.write("activate.rb", "gem('a', '= 999')\n")
+
+ require "open3"
+
+ output, _ = Open3.capture2e(
+ { "GEM_HOME" => Gem.paths.home },
+ Gem.ruby,
+ "-I",
+ File.expand_path("../../lib", __dir__),
+ "-r",
+ "./activate.rb"
+ )
+
+ load_errors = output.split("\n").select { |line| line.include?("Could not find")}
+
+ assert_equal 1, load_errors.size
+ end
+
def test_gem_bundler
quick_gem 'bundler', '1'
quick_gem 'bundler', '2.a'
diff --git a/test/rubygems/test_require.rb b/test/rubygems/test_require.rb
index aa2675af5d..392ede7ba0 100644
--- a/test/rubygems/test_require.rb
+++ b/test/rubygems/test_require.rb
@@ -45,6 +45,35 @@ class TestGemRequire < Gem::TestCase
refute require(path), "'#{path}' was not yet required"
end
+ def test_respect_loaded_features_caching_like_standard_require
+ dir = Dir.mktmpdir("test_require", @tempdir)
+
+ lp1 = File.join dir, 'foo1'
+ foo1 = File.join lp1, 'foo.rb'
+
+ FileUtils.mkdir_p lp1
+ File.open(foo1, 'w') { |f| f.write "class Object; HELLO = 'foo1' end" }
+
+ lp = $LOAD_PATH.dup
+
+ $LOAD_PATH.unshift lp1
+ assert_require 'foo'
+ assert_equal "foo1", ::Object::HELLO
+
+ lp2 = File.join dir, 'foo2'
+ foo2 = File.join lp2, 'foo.rb'
+
+ FileUtils.mkdir_p lp2
+ File.open(foo2, 'w') { |f| f.write "class Object; HELLO = 'foo2' end" }
+
+ $LOAD_PATH.unshift lp2
+ refute_require 'foo'
+ assert_equal "foo1", ::Object::HELLO
+ ensure
+ $LOAD_PATH.replace lp
+ Object.send :remove_const, :HELLO if Object.const_defined? :HELLO
+ end
+
# Providing -I on the commandline should always beat gems
def test_dash_i_beats_gems
a1 = util_spec "a", "1", {"b" => "= 1"}, "lib/test_gem_require_a.rb"
@@ -120,6 +149,24 @@ class TestGemRequire < Gem::TestCase
Object.send :remove_const, :HELLO if Object.const_defined? :HELLO
end
+ def test_dash_i_respects_default_library_extension_priority
+ skip "extensions don't quite work on jruby" if Gem.java_platform?
+
+ dash_i_ext_arg = util_install_extension_file('a')
+ dash_i_lib_arg = util_install_ruby_file('a')
+
+ lp = $LOAD_PATH.dup
+
+ begin
+ $LOAD_PATH.unshift dash_i_lib_arg
+ $LOAD_PATH.unshift dash_i_ext_arg
+ assert_require 'a'
+ assert_match(/a\.rb$/, $LOADED_FEATURES.last)
+ ensure
+ $LOAD_PATH.replace lp
+ end
+ end
+
def test_concurrent_require
Object.const_set :FILE_ENTERED_LATCH, Latch.new(2)
Object.const_set :FILE_EXIT_LATCH, Latch.new(1)
@@ -364,6 +411,17 @@ class TestGemRequire < Gem::TestCase
assert_equal 0, times_called
end
+ def test_second_gem_require_does_not_resolve_path_manually_before_going_through_standard_require
+ a1 = util_spec "a", "1", nil, "lib/test_gem_require_a.rb"
+ install_gem a1
+
+ assert_require "test_gem_require_a"
+
+ stub(:gem_original_require, ->(path) { assert_equal "test_gem_require_a", path }) do
+ require "test_gem_require_a"
+ end
+ end
+
def test_realworld_default_gem
testing_ruby_repo = !ENV["GEM_COMMAND"].nil?
skip "this test can't work under ruby-core setup" if testing_ruby_repo || java_platform?
@@ -539,4 +597,50 @@ class TestGemRequire < Gem::TestCase
$VERBOSE = old_verbose
end
+ def util_install_extension_file(name)
+ spec = quick_gem name
+ util_build_gem spec
+
+ spec.extensions << "extconf.rb"
+ write_file File.join(@tempdir, "extconf.rb") do |io|
+ io.write <<-RUBY
+ require "mkmf"
+ CONFIG['LDSHARED'] = '$(TOUCH) $@ ||'
+ create_makefile("#{name}")
+ RUBY
+ end
+
+ write_file File.join(@tempdir, "#{name}.c") do |io|
+ io.write <<-C
+ void Init_#{name}() { }
+ C
+ end
+
+ write_file File.join(@tempdir, "depend")
+
+ spec.files += ["extconf.rb", "depend", "#{name}.c"]
+
+ so = File.join(spec.gem_dir, "#{name}.#{RbConfig::CONFIG["DLEXT"]}")
+ refute_path_exists so
+
+ path = Gem::Package.build spec
+ installer = Gem::Installer.at path
+ installer.install
+ assert_path_exists so
+
+ spec.gem_dir
+ end
+
+ def util_install_ruby_file(name)
+ dir_lib = Dir.mktmpdir("test_require_lib", @tempdir)
+ dash_i_lib_arg = File.join dir_lib
+
+ a_rb = File.join dash_i_lib_arg, "#{name}.rb"
+
+ FileUtils.mkdir_p File.dirname a_rb
+ File.open(a_rb, 'w') { |f| f.write "# #{name}.rb" }
+
+ dash_i_lib_arg
+ end
+
end
diff --git a/version.h b/version.h
index fa6b79c666..40cd5ffde3 100644
--- a/version.h
+++ b/version.h
@@ -2,11 +2,11 @@
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
#define RUBY_VERSION_TEENY 3
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
-#define RUBY_PATCHLEVEL 146
+#define RUBY_PATCHLEVEL 147
-#define RUBY_RELEASE_YEAR 2020
-#define RUBY_RELEASE_MONTH 12
-#define RUBY_RELEASE_DAY 31
+#define RUBY_RELEASE_YEAR 2021
+#define RUBY_RELEASE_MONTH 1
+#define RUBY_RELEASE_DAY 30
#include "ruby/version.h"