aboutsummaryrefslogtreecommitdiffstats
path: root/lib/bundler/rubygems_ext.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/bundler/rubygems_ext.rb')
-rw-r--r--lib/bundler/rubygems_ext.rb209
1 files changed, 209 insertions, 0 deletions
diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb
new file mode 100644
index 0000000000..a0f8fa848b
--- /dev/null
+++ b/lib/bundler/rubygems_ext.rb
@@ -0,0 +1,209 @@
+# frozen_string_literal: true
+require "pathname"
+
+if defined?(Gem::QuickLoader)
+ # Gem Prelude makes me a sad panda :'(
+ Gem::QuickLoader.load_full_rubygems_library
+end
+
+require "rubygems"
+require "rubygems/specification"
+
+begin
+ # Possible use in Gem::Specification#source below and require
+ # shouldn't be deferred.
+ require "rubygems/source"
+rescue LoadError
+ # Not available before Rubygems 2.0.0, ignore
+ nil
+end
+
+require "bundler/match_platform"
+
+module Gem
+ @loaded_stacks = Hash.new {|h, k| h[k] = [] }
+
+ class Specification
+ attr_accessor :remote, :location, :relative_loaded_from
+
+ if instance_methods(false).map(&:to_sym).include?(:source)
+ remove_method :source
+ attr_writer :source
+ def source
+ (defined?(@source) && @source) || Gem::Source::Installed.new
+ end
+ else
+ attr_accessor :source
+ end
+
+ alias_method :rg_full_gem_path, :full_gem_path
+ alias_method :rg_loaded_from, :loaded_from
+
+ attr_writer :full_gem_path unless instance_methods.include?(:full_gem_path=)
+
+ def full_gem_path
+ # this cannot check source.is_a?(Bundler::Plugin::API::Source)
+ # because that _could_ trip the autoload, and if there are unresolved
+ # gems at that time, this method could be called inside another require,
+ # thus raising with that constant being undefined. Better to check a method
+ if source.respond_to?(:path) || (source.respond_to?(:bundler_plugin_api_source?) && source.bundler_plugin_api_source?)
+ Pathname.new(loaded_from).dirname.expand_path(source.root).to_s.untaint
+ else
+ rg_full_gem_path
+ end
+ end
+
+ def loaded_from
+ if relative_loaded_from
+ source.path.join(relative_loaded_from).to_s
+ else
+ rg_loaded_from
+ end
+ end
+
+ def load_paths
+ return full_require_paths if respond_to?(:full_require_paths)
+
+ require_paths.map do |require_path|
+ if require_path.include?(full_gem_path)
+ require_path
+ else
+ File.join(full_gem_path, require_path)
+ end
+ end
+ end
+
+ if method_defined?(:extension_dir)
+ alias_method :rg_extension_dir, :extension_dir
+ def extension_dir
+ @bundler_extension_dir ||= if source.respond_to?(:extension_dir_name)
+ File.expand_path(File.join(extensions_dir, source.extension_dir_name))
+ else
+ rg_extension_dir
+ end
+ end
+ end
+
+ # RubyGems 1.8+ used only.
+ methods = instance_methods(false)
+ gem_dir = methods.first.is_a?(String) ? "gem_dir" : :gem_dir
+ remove_method :gem_dir if methods.include?(gem_dir)
+ def gem_dir
+ full_gem_path
+ end
+
+ def groups
+ @groups ||= []
+ end
+
+ def git_version
+ return unless loaded_from && source.is_a?(Bundler::Source::Git)
+ " #{source.revision[0..6]}"
+ end
+
+ def to_gemfile(path = nil)
+ gemfile = String.new("source 'https://rubygems.org'\n")
+ gemfile << dependencies_to_gemfile(nondevelopment_dependencies)
+ unless development_dependencies.empty?
+ gemfile << "\n"
+ gemfile << dependencies_to_gemfile(development_dependencies, :development)
+ end
+ gemfile
+ end
+
+ def nondevelopment_dependencies
+ dependencies - development_dependencies
+ end
+
+ private
+
+ def dependencies_to_gemfile(dependencies, group = nil)
+ gemfile = String.new
+ if dependencies.any?
+ gemfile << "group :#{group} do\n" if group
+ dependencies.each do |dependency|
+ gemfile << " " if group
+ gemfile << %(gem "#{dependency.name}")
+ req = dependency.requirements_list.first
+ gemfile << %(, "#{req}") if req
+ gemfile << "\n"
+ end
+ gemfile << "end\n" if group
+ end
+ gemfile
+ end
+ end
+
+ class Dependency
+ attr_accessor :source, :groups
+
+ alias_method :eql?, :==
+
+ def encode_with(coder)
+ to_yaml_properties.each do |ivar|
+ coder[ivar.to_s.sub(/^@/, "")] = instance_variable_get(ivar)
+ end
+ end
+
+ def to_yaml_properties
+ instance_variables.reject {|p| ["@source", "@groups"].include?(p.to_s) }
+ end
+
+ def to_lock
+ out = String.new(" #{name}")
+ unless requirement.none?
+ reqs = requirement.requirements.map {|o, v| "#{o} #{v}" }.sort.reverse
+ out << " (#{reqs.join(", ")})"
+ end
+ out
+ end
+
+ # Backport of performance enhancement added to Rubygems 1.4
+ def matches_spec?(spec)
+ # name can be a Regexp, so use ===
+ return false unless name === spec.name
+ return true if requirement.none?
+
+ requirement.satisfied_by?(spec.version)
+ end unless allocate.respond_to?(:matches_spec?)
+ end
+
+ class Requirement
+ # Backport of performance enhancement added to RubyGems 1.4
+ def none?
+ # note that it might be tempting to replace with with RubyGems 2.0's
+ # improved implementation. Don't. It requires `DefaultRequirement` to be
+ # defined, and more importantantly, these overrides are not used when the
+ # running RubyGems defines these methods
+ to_s == ">= 0"
+ end unless allocate.respond_to?(:none?)
+
+ # Backport of performance enhancement added to RubyGems 2.2
+ def exact?
+ return false unless @requirements.size == 1
+ @requirements[0][0] == "="
+ end unless allocate.respond_to?(:exact?)
+ end
+
+ class Platform
+ JAVA = Gem::Platform.new("java") unless defined?(JAVA)
+ MSWIN = Gem::Platform.new("mswin32") unless defined?(MSWIN)
+ MSWIN64 = Gem::Platform.new("mswin64") unless defined?(MSWIN64)
+ MINGW = Gem::Platform.new("x86-mingw32") unless defined?(MINGW)
+ X64_MINGW = Gem::Platform.new("x64-mingw32") unless defined?(X64_MINGW)
+
+ undef_method :hash if method_defined? :hash
+ def hash
+ @cpu.hash ^ @os.hash ^ @version.hash
+ end
+
+ undef_method :eql? if method_defined? :eql?
+ alias_method :eql?, :==
+ end
+end
+
+module Gem
+ class Specification
+ include ::Bundler::MatchPlatform
+ end
+end