summaryrefslogtreecommitdiff
path: root/ruby_2_2/lib/rubygems/core_ext/kernel_require.rb
diff options
context:
space:
mode:
authorusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-12-14 15:09:35 +0000
committerusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-12-14 15:09:35 +0000
commit1a74fa4b04da04bd2bb33103dd3cf431438df38e (patch)
treef4a1d6c2961339e0c1d653c0f8427a53315080f0 /ruby_2_2/lib/rubygems/core_ext/kernel_require.rb
parenta5b755e50e2d9aabf28ba24bf58644ca22b01a4f (diff)
add tag v2_2_9
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/tags/v2_2_9@61257 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ruby_2_2/lib/rubygems/core_ext/kernel_require.rb')
-rwxr-xr-xruby_2_2/lib/rubygems/core_ext/kernel_require.rb139
1 files changed, 139 insertions, 0 deletions
diff --git a/ruby_2_2/lib/rubygems/core_ext/kernel_require.rb b/ruby_2_2/lib/rubygems/core_ext/kernel_require.rb
new file mode 100755
index 0000000000..8f2cddee4d
--- /dev/null
+++ b/ruby_2_2/lib/rubygems/core_ext/kernel_require.rb
@@ -0,0 +1,139 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'monitor'
+
+module Kernel
+
+ RUBYGEMS_ACTIVATION_MONITOR = Monitor.new # :nodoc:
+
+ if defined?(gem_original_require) then
+ # Ruby ships with a custom_require, override its require
+ remove_method :require
+ else
+ ##
+ # The Kernel#require from before RubyGems was loaded.
+
+ alias gem_original_require require
+ private :gem_original_require
+ end
+
+ ##
+ # When RubyGems is required, Kernel#require is replaced with our own which
+ # is capable of loading gems on demand.
+ #
+ # When you call <tt>require 'x'</tt>, this is what happens:
+ # * If the file can be loaded from the existing Ruby loadpath, it
+ # is.
+ # * Otherwise, installed gems are searched for a file that matches.
+ # If it's found in gem 'y', that gem is activated (added to the
+ # loadpath).
+ #
+ # The normal <tt>require</tt> functionality of returning false if
+ # that file has already been loaded is preserved.
+
+ def require path
+ RUBYGEMS_ACTIVATION_MONITOR.enter
+
+ path = path.to_path if path.respond_to? :to_path
+
+ spec = Gem.find_unresolved_default_spec(path)
+ if spec
+ Gem.remove_unresolved_default_spec(spec)
+ gem(spec.name)
+ end
+
+ # 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? then
+ 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
+
+ spec = Gem::Specification.stubs.find { |s|
+ s.activated? and s.contains_requirable_file? path
+ }
+
+ begin
+ RUBYGEMS_ACTIVATION_MONITOR.exit
+ return gem_original_require(spec.to_fullpath(path) || path)
+ end if spec
+
+ # 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? then
+ 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
+
+ # Check that all the found specs are just different
+ # versions of the same gem
+ names = found_specs.map(&:name).uniq
+
+ if names.size > 1 then
+ 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.select { |s| s.conflicts.empty? }.last
+
+ unless valid then
+ 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
+
+ valid.activate
+ end
+
+ RUBYGEMS_ACTIVATION_MONITOR.exit
+ return gem_original_require(path)
+ rescue LoadError => load_error
+ RUBYGEMS_ACTIVATION_MONITOR.enter
+
+ if load_error.message.start_with?("Could not find") or
+ (load_error.message.end_with?(path) and Gem.try_activate(path)) then
+ RUBYGEMS_ACTIVATION_MONITOR.exit
+ return gem_original_require(path)
+ else
+ RUBYGEMS_ACTIVATION_MONITOR.exit
+ end
+
+ raise load_error
+ end
+
+ private :require
+
+end
+