summaryrefslogtreecommitdiff
path: root/jni/ruby/lib/rubygems/core_ext
diff options
context:
space:
mode:
Diffstat (limited to 'jni/ruby/lib/rubygems/core_ext')
-rw-r--r--jni/ruby/lib/rubygems/core_ext/kernel_gem.rb73
-rwxr-xr-xjni/ruby/lib/rubygems/core_ext/kernel_require.rb139
2 files changed, 212 insertions, 0 deletions
diff --git a/jni/ruby/lib/rubygems/core_ext/kernel_gem.rb b/jni/ruby/lib/rubygems/core_ext/kernel_gem.rb
new file mode 100644
index 0000000..61e77fe
--- /dev/null
+++ b/jni/ruby/lib/rubygems/core_ext/kernel_gem.rb
@@ -0,0 +1,73 @@
+##
+# RubyGems adds the #gem method to allow activation of specific gem versions
+# and overrides the #require method on Kernel to make gems appear as if they
+# live on the <code>$LOAD_PATH</code>. See the documentation of these methods
+# for further detail.
+
+module Kernel
+
+ # REFACTOR: This should be pulled out into some kind of hacks file.
+ remove_method :gem if 'method' == defined? gem # from gem_prelude.rb on 1.9
+
+ ##
+ # Use Kernel#gem to activate a specific version of +gem_name+.
+ #
+ # +requirements+ is a list of version requirements that the
+ # specified gem must match, most commonly "= example.version.number". See
+ # Gem::Requirement for how to specify a version requirement.
+ #
+ # If you will be activating the latest version of a gem, there is no need to
+ # call Kernel#gem, Kernel#require will do the right thing for you.
+ #
+ # Kernel#gem returns true if the gem was activated, otherwise false. If the
+ # gem could not be found, didn't match the version requirements, or a
+ # different version was already activated, an exception will be raised.
+ #
+ # Kernel#gem should be called *before* any require statements (otherwise
+ # RubyGems may load a conflicting library version).
+ #
+ # Kernel#gem only loads prerelease versions when prerelease +requirements+
+ # are given:
+ #
+ # gem 'rake', '>= 1.1.a', '< 2'
+ #
+ # In older RubyGems versions, the environment variable GEM_SKIP could be
+ # used to skip activation of specified gems, for example to test out changes
+ # that haven't been installed yet. Now RubyGems defers to -I and the
+ # RUBYLIB environment variable to skip activation of a gem.
+ #
+ # Example:
+ #
+ # GEM_SKIP=libA:libB ruby -I../libA -I../libB ./mycode.rb
+
+ def gem(gem_name, *requirements) # :doc:
+ skip_list = (ENV['GEM_SKIP'] || "").split(/:/)
+ raise Gem::LoadError, "skipping #{gem_name}" if skip_list.include? gem_name
+
+ if gem_name.kind_of? Gem::Dependency
+ unless Gem::Deprecate.skip
+ warn "#{Gem.location_of_caller.join ':'}:Warning: Kernel.gem no longer "\
+ "accepts a Gem::Dependency object, please pass the name "\
+ "and requirements directly"
+ end
+
+ requirements = gem_name.requirement
+ gem_name = gem_name.name
+ end
+
+ dep = Gem::Dependency.new(gem_name, *requirements)
+
+ loaded = Gem.loaded_specs[gem_name]
+
+ return false if loaded && dep.matches_spec?(loaded)
+
+ spec = dep.to_spec
+
+ Gem::LOADED_SPECS_MUTEX.synchronize {
+ spec.activate
+ } if spec
+ end
+
+ private :gem
+
+end
diff --git a/jni/ruby/lib/rubygems/core_ext/kernel_require.rb b/jni/ruby/lib/rubygems/core_ext/kernel_require.rb
new file mode 100755
index 0000000..8f2cdde
--- /dev/null
+++ b/jni/ruby/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
+