summaryrefslogtreecommitdiff
path: root/lib/rubygems
diff options
context:
space:
mode:
authorDavid Rodríguez <deivid.rodriguez@riseup.net>2023-01-30 18:10:56 +0100
committerHiroshi SHIBATA <hsbt@ruby-lang.org>2023-01-31 10:49:08 +0900
commit4cbfd87e5a8464db42657ee0019f9bd78c15c05c (patch)
treede7ad31c04756b2bbf51ec2895522a9d6f522a87 /lib/rubygems
parent022acb9593c09a9e358215a80448b426ee366ac0 (diff)
[rubygems/rubygems] Allow disabling RubyGems require decorations
Currently Bundler needs to do cumbersome operations to revert custom RubyGems require on a `bundler/setup` context. This causes issues when third party gems also monkeypatch require, since Bundler will also undo those decorations. This commit allows it to use the simpler approach of properly telling RubyGems that it needs to default to built-in require without any extra magic. https://github.com/rubygems/rubygems/commit/1df5009e14 Co-authored-by: Xavier Noria <fxn@hashref.com>
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/7203
Diffstat (limited to 'lib/rubygems')
-rw-r--r--lib/rubygems/core_ext/kernel_require.rb222
1 files changed, 113 insertions, 109 deletions
diff --git a/lib/rubygems/core_ext/kernel_require.rb b/lib/rubygems/core_ext/kernel_require.rb
index b92d6f9965..6dcc4a06e4 100644
--- a/lib/rubygems/core_ext/kernel_require.rb
+++ b/lib/rubygems/core_ext/kernel_require.rb
@@ -34,137 +34,141 @@ module Kernel
# that file has already been loaded is preserved.
def require(path) # :doc:
- if RUBYGEMS_ACTIVATION_MONITOR.respond_to?(:mon_owned?)
- monitor_owned = RUBYGEMS_ACTIVATION_MONITOR.mon_owned?
- end
- RUBYGEMS_ACTIVATION_MONITOR.enter
-
- path = path.to_path if path.respond_to? :to_path
-
- 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|
- $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
+ return gem_original_require(path) unless Gem.discover_gems_on_require
+
+ begin
+ if RUBYGEMS_ACTIVATION_MONITOR.respond_to?(:mon_owned?)
+ monitor_owned = RUBYGEMS_ACTIVATION_MONITOR.mon_owned?
+ end
+ RUBYGEMS_ACTIVATION_MONITOR.enter
+
+ path = path.to_path if path.respond_to? :to_path
+
+ 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|
+ $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
- 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
+ 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
+ rp
end
- rp
+
+ begin
+ Kernel.send(:gem, spec.name, Gem::Requirement.default_prerelease)
+ rescue Exception
+ RUBYGEMS_ACTIVATION_MONITOR.exit
+ raise
+ end unless resolved_path
end
- begin
- Kernel.send(:gem, spec.name, Gem::Requirement.default_prerelease)
- rescue Exception
- RUBYGEMS_ACTIVATION_MONITOR.exit
- raise
- end unless resolved_path
- end
+ # If there are no unresolved deps, then we can use just try
+ # normal require handle loading a gem from the rescue below.
- # If there are no unresolved deps, then we can use just try
- # normal require handle loading a gem from the rescue below.
+ if Gem::Specification.unresolved_deps.empty?
+ RUBYGEMS_ACTIVATION_MONITOR.exit
+ return gem_original_require(path)
+ end
- if Gem::Specification.unresolved_deps.empty?
- RUBYGEMS_ACTIVATION_MONITOR.exit
- return gem_original_require(path)
- end
+ # If +path+ is for a gem that has already been loaded, don't
+ # bother trying to find it in an unresolved gem, just go straight
+ # to normal require.
+ #--
+ # TODO request access to the C implementation of this to speed up RubyGems
- # If +path+ is for a gem that has already been loaded, don't
- # bother trying to find it in an unresolved gem, just go straight
- # to normal require.
- #--
- # TODO request access to the C implementation of this to speed up RubyGems
+ if Gem::Specification.find_active_stub_by_path(path)
+ RUBYGEMS_ACTIVATION_MONITOR.exit
+ return gem_original_require(path)
+ end
- if Gem::Specification.find_active_stub_by_path(path)
- RUBYGEMS_ACTIVATION_MONITOR.exit
- return gem_original_require(path)
- end
+ # Attempt to find +path+ in any unresolved gems...
+
+ found_specs = Gem::Specification.find_in_unresolved path
+
+ # If there are no directly unresolved gems, then try and find +path+
+ # in any gems that are available via the currently unresolved gems.
+ # For example, given:
+ #
+ # a => b => c => d
+ #
+ # If a and b are currently active with c being unresolved and d.rb is
+ # requested, then find_in_unresolved_tree will find d.rb in d because
+ # it's a dependency of c.
+ #
+ if found_specs.empty?
+ found_specs = Gem::Specification.find_in_unresolved_tree path
+
+ found_specs.each do |found_spec|
+ found_spec.activate
+ end
- # Attempt to find +path+ in any unresolved gems...
-
- found_specs = Gem::Specification.find_in_unresolved path
-
- # If there are no directly unresolved gems, then try and find +path+
- # in any gems that are available via the currently unresolved gems.
- # For example, given:
- #
- # a => b => c => d
- #
- # If a and b are currently active with c being unresolved and d.rb is
- # requested, then find_in_unresolved_tree will find d.rb in d because
- # it's a dependency of c.
- #
- if found_specs.empty?
- found_specs = Gem::Specification.find_in_unresolved_tree path
-
- found_specs.each do |found_spec|
- found_spec.activate
- end
+ # We found +path+ directly in an unresolved gem. Now we figure out, of
+ # the possible found specs, which one we should activate.
+ else
- # We found +path+ directly in an unresolved gem. Now we figure out, of
- # the possible found specs, which one we should activate.
- else
+ # Check that all the found specs are just different
+ # versions of the same gem
+ names = found_specs.map(&:name).uniq
- # Check that all the found specs are just different
- # versions of the same gem
- names = found_specs.map(&:name).uniq
+ if names.size > 1
+ RUBYGEMS_ACTIVATION_MONITOR.exit
+ raise Gem::LoadError, "#{path} found in multiple gems: #{names.join ', '}"
+ end
- if names.size > 1
- RUBYGEMS_ACTIVATION_MONITOR.exit
- raise Gem::LoadError, "#{path} found in multiple gems: #{names.join ', '}"
- end
+ # Ok, now find a gem that has no conflicts, starting
+ # at the highest version.
+ valid = found_specs.find {|s| !s.has_conflicts? }
- # Ok, now find a gem that has no conflicts, starting
- # at the highest version.
- valid = found_specs.find {|s| !s.has_conflicts? }
+ unless valid
+ le = Gem::LoadError.new "unable to find a version of '#{names.first}' to activate"
+ le.name = names.first
+ RUBYGEMS_ACTIVATION_MONITOR.exit
+ raise le
+ end
- unless valid
- le = Gem::LoadError.new "unable to find a version of '#{names.first}' to activate"
- le.name = names.first
- RUBYGEMS_ACTIVATION_MONITOR.exit
- raise le
+ valid.activate
end
- valid.activate
- end
-
- RUBYGEMS_ACTIVATION_MONITOR.exit
- return gem_original_require(path)
- rescue LoadError => load_error
- if load_error.path == path
- RUBYGEMS_ACTIVATION_MONITOR.enter
+ RUBYGEMS_ACTIVATION_MONITOR.exit
+ return gem_original_require(path)
+ rescue LoadError => load_error
+ if load_error.path == path
+ RUBYGEMS_ACTIVATION_MONITOR.enter
+
+ begin
+ require_again = Gem.try_activate(path)
+ ensure
+ RUBYGEMS_ACTIVATION_MONITOR.exit
+ end
- begin
- require_again = Gem.try_activate(path)
- ensure
- RUBYGEMS_ACTIVATION_MONITOR.exit
+ return gem_original_require(path) if require_again
end
- return gem_original_require(path) if require_again
- end
-
- raise load_error
- ensure
- if RUBYGEMS_ACTIVATION_MONITOR.respond_to?(:mon_owned?)
- if monitor_owned != (ow = RUBYGEMS_ACTIVATION_MONITOR.mon_owned?)
- STDERR.puts [$$, Thread.current, $!, $!.backtrace].inspect if $!
- raise "CRITICAL: RUBYGEMS_ACTIVATION_MONITOR.owned?: before #{monitor_owned} -> after #{ow}"
+ raise load_error
+ ensure
+ if RUBYGEMS_ACTIVATION_MONITOR.respond_to?(:mon_owned?)
+ if monitor_owned != (ow = RUBYGEMS_ACTIVATION_MONITOR.mon_owned?)
+ STDERR.puts [$$, Thread.current, $!, $!.backtrace].inspect if $!
+ raise "CRITICAL: RUBYGEMS_ACTIVATION_MONITOR.owned?: before #{monitor_owned} -> after #{ow}"
+ end
end
end
end