# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# See LICENSE.txt for permissions.
# Must be first since it unloads the prelude from 1.9.2
require 'rubygems/compatibility'
require 'rubygems/defaults'
require 'rubygems/deprecate'
require 'rubygems/errors'
# RubyGems is the Ruby standard for publishing and managing third party
# For user documentation, see:
# * <tt>gem help</tt> and <tt>gem help [command]</tt>
# * {RubyGems User Guide}[http://docs.rubygems.org/read/book/1]
# * {Frequently Asked Questions}[http://docs.rubygems.org/read/book/3]
# For gem developer documentation see:
# * {Creating Gems}[http://docs.rubygems.org/read/chapter/5]
# * Gem::Version for version dependency notes
# Further RubyGems documentation can be found at:
# * {RubyGems Guides}[http://guides.rubygems.org]
# * {RubyGems API}[http://rubygems.rubyforge.org/rdoc] (also available from
# As of RubyGems 1.3.2, RubyGems will load plugins installed in gems or
# $LOAD_PATH. Plugins must be named 'rubygems_plugin' (.rb, .so, etc) and
# placed at the root of your gem's #require_path. Plugins are discovered via
# Gem::find_files then loaded. Take care when implementing a plugin as your
# plugin file may be loaded multiple times if multiple versions of your gem
# For an example plugin, see the graph gem which adds a `gem graph` command.
# == RubyGems Defaults, Packaging
# RubyGems defaults are stored in rubygems/defaults.rb. If you're packaging
# RubyGems or implementing Ruby you can change RubyGems' defaults.
# For RubyGems packagers, provide lib/rubygems/defaults/operating_system.rb
# and override any defaults from lib/rubygems/defaults.rb.
# For Ruby implementers, provide lib/rubygems/defaults/#{RUBY_ENGINE}.rb and
# override any defaults from lib/rubygems/defaults.rb.
# If you need RubyGems to perform extra work on install or uninstall, your
# defaults override file can set pre and post install and uninstall hooks.
# See Gem::pre_install, Gem::pre_uninstall, Gem::post_install,
# You can submit bugs to the
# {RubyGems bug tracker}[https://github.com/rubygems/rubygems/issues]
# RubyGems is currently maintained by Eric Hodel.
# RubyGems was originally developed at RubyConf 2003 by:
# * Rich Kilmer -- rich(at)infoether.com
# * Chad Fowler -- chad(at)chadfowler.com
# * David Black -- dblack(at)wobblini.net
# * Paul Brannan -- paul(at)atdesk.com
# * Jim Weirich -- jim(at)weirichhouse.org
# * Gavin Sinclair -- gsinclair(at)soyabean.com.au
# * George Marrows -- george.marrows(at)ntlworld.com
# * Dick Davies -- rasputnik(at)hellooperator.net
# * Mauricio Fernandez -- batsman.geo(at)yahoo.com
# * Simon Strandgaard -- neoneye(at)adslhome.dk
# * Dave Glasser -- glasser(at)mit.edu
# * Paul Duncan -- pabs(at)pablotron.org
# * Ville Aine -- vaine(at)cs.helsinki.fi
# * Eric Hodel -- drbrain(at)segment7.net
# * Daniel Berger -- djberg96(at)gmail.com
# * Phil Hagelberg -- technomancy(at)gmail.com
# * Ryan Davis -- ryand-ruby(at)zenspider.com
# * Evan Phoenix -- evan(at)fallingsnow.net
# * Steve Klabnik -- steve(at)steveklabnik.com
# (If your name is missing, PLEASE let us know!)
# See {LICENSE.txt}[rdoc-ref:lib/rubygems/LICENSE.txt] for permissions.
RUBYGEMS_DIR = File.dirname File.expand_path(__FILE__)
# An Array of Regexps that match windows Ruby platforms.
# Subdirectories in a gem repository
REPOSITORY_SUBDIRECTORIES = %w[
# Subdirectories in a gem repository for default gems
REPOSITORY_DEFAULT_GEM_SUBDIRECTORIES = %w[
LOADED_SPECS_MUTEX = Mutex.new
@path_to_default_spec_map = {}
@post_install_hooks ||= []
@post_uninstall_hooks ||= []
@pre_uninstall_hooks ||= []
@pre_install_hooks ||= []
# Try to activate a gem containing +path+. Returns true if
# activation succeeded or wasn't needed because it was already
# activated. Returns false if it can't find the path in a gem.
def self.try_activate path
# finds the _latest_ version... regardless of loaded specs and their deps
# if another gem had a requirement that would mean we shouldn't
# activate the latest version, then either it would already be activated
# or if it was ambiguous (and thus unresolved) the code in our custom
# require will try to activate the more specific version.
spec = Gem::Specification.find_inactive_by_path path
spec = Gem::Specification.find_by_path path
return true if spec && spec.activated?
rescue Gem::LoadError # this could fail due to gem dep collisions, go lax
Gem::Specification.find_by_name(spec.name).activate
def self.finish_resolve(request_set=Gem::RequestSet.new)
request_set.import Gem::Specification.unresolved_deps.values
request_set.resolve_current.each do |s|
# Find the full path to the executable for gem +name+. If the +exec_name+
# is not given, the gem's default_executable is chosen, otherwise the
# specified executable's path is returned. +requirements+ allows
# you to specify specific gem versions.
def self.bin_path(name, exec_name = nil, *requirements)
# TODO: fails test_self_bin_path_bin_file_gone_in_latest
# Gem::Specification.find_by_name(name, *requirements).bin_file exec_name
raise ArgumentError, "you must supply exec_name" unless exec_name
requirements = Gem::Requirement.default if
dep = Gem::Dependency.new name, requirements
loaded = Gem.loaded_specs[name]
return loaded.bin_file exec_name if loaded && dep.matches_spec?(loaded)
specs = dep.matching_specs(true)
raise Gem::GemNotFoundException,
"can't find gem #{name} (#{requirements})" if specs.empty?
specs = specs.find_all { |spec|
spec.executables.include? exec_name
msg = "can't find gem #{name} (#{requirements}) with executable #{exec_name}"
raise Gem::GemNotFoundException, msg
# The mode needed to read a file as straight binary.
# The path where gem executables are to be installed.
def self.bindir(install_dir=Gem.dir)
return File.join install_dir, 'bin' unless
install_dir.to_s == Gem.default_dir.to_s
# Reset the +dir+ and +path+ values. The next time +dir+ or +path+
# is requested, the values will be calculated from scratch. This is
# mainly used by the unit tests to provide test isolation.
Gem::Security.reset if defined?(Gem::Security)
# The path to standard location of the user's .gemrc file.
@config_file ||= File.join Gem.user_home, '.gemrc'
# The standard configuration object for gems.
@configuration ||= Gem::ConfigFile.new []
# Use the given configuration object (which implements the ConfigFile
# protocol) as the standard configuration object.
def self.configuration=(config)
# The path to the data directory specified by the gem name. If the
# package is not available as a gem, return nil.
def self.datadir(gem_name)
# TODO: deprecate and move to Gem::Specification
# and drop the extra ", gem_name" which is uselessly redundant
spec = @loaded_specs[gem_name]
File.join spec.full_gem_path, "data", gem_name
# A Zlib::Deflate.deflate wrapper
Zlib::Deflate.deflate data
# Retrieve the PathSupport object that RubyGems uses to
@paths ||= Gem::PathSupport.new
# Initialize the filesystem paths to use from +env+.
# +env+ is a hash-like object (typically ENV) that
# is queried for 'GEM_HOME', 'GEM_PATH', and 'GEM_SPEC_CACHE'
@paths = Gem::PathSupport.new env
Gem::Specification.dirs = @paths.path
# The path where gems are to be installed.
# FIXME deprecate these once everything else has been done -ebh
# Quietly ensure the Gem directory +dir+ contains all the proper
# subdirectories. If we can't create a directory due to a permission
# problem, then we will silently continue.
# If +mode+ is given, missing directories are created with this mode.
# World-writable directories will never be created.
def self.ensure_gem_subdirectories dir = Gem.dir, mode = nil
ensure_subdirectories(dir, mode, REPOSITORY_SUBDIRECTORIES)
# Quietly ensure the Gem directory +dir+ contains all the proper
# subdirectories for handling default gems. If we can't create a
# directory due to a permission problem, then we will silently continue.
# If +mode+ is given, missing directories are created with this mode.
# World-writable directories will never be created.
def self.ensure_default_gem_subdirectories dir = Gem.dir, mode = nil
ensure_subdirectories(dir, mode, REPOSITORY_DEFAULT_GEM_SUBDIRECTORIES)
def self.ensure_subdirectories dir, mode, subdirs # :nodoc:
File.umask old_umask | 002
options[:mode] = mode if mode
subdir = File.join dir, name
next if File.exist? subdir
FileUtils.mkdir_p subdir, options rescue nil
# The extension API version of ruby. This includes the static vs non-static
# distinction as extensions cannot be shared between the two.
def self.extension_api_version # :nodoc:
if 'no' == RbConfig::CONFIG['ENABLE_SHARED'] then
"#{ruby_api_version}-static"
# Returns a list of paths matching +glob+ that can be used by a gem to pick
# up features from other gems. For example:
# Gem.find_files('rdoc/discover').each do |path| load path end
# if +check_load_path+ is true (the default), then find_files also searches
# $LOAD_PATH for files as well as gems.
# Note that find_files will return all files even if they are from different
# versions of the same gem. See also find_latest_files
def self.find_files(glob, check_load_path=true)
files = find_files_from_load_path glob if check_load_path
files.concat Gem::Specification.map { |spec|
spec.matches_for_glob("#{glob}#{Gem.suffix_pattern}")
# $LOAD_PATH might contain duplicate entries or reference
# the spec dirs directly, so we prune.
files.uniq! if check_load_path
def self.find_files_from_load_path glob # :nodoc:
$LOAD_PATH.map { |load_path|
Dir["#{File.expand_path glob, load_path}#{Gem.suffix_pattern}"]
}.flatten.select { |file| File.file? file.untaint }
# Returns a list of paths matching +glob+ from the latest gems that can be
# used by a gem to pick up features from other gems. For example:
# Gem.find_latest_files('rdoc/discover').each do |path| load path end
# if +check_load_path+ is true (the default), then find_latest_files also
# searches $LOAD_PATH for files as well as gems.
# Unlike find_files, find_latest_files will return only files from the
# latest version of a gem.
def self.find_latest_files(glob, check_load_path=true)
files = find_files_from_load_path glob if check_load_path
files.concat Gem::Specification.latest_specs(true).map { |spec|
spec.matches_for_glob("#{glob}#{Gem.suffix_pattern}")
# $LOAD_PATH might contain duplicate entries or reference
# the spec dirs directly, so we prune.
files.uniq! if check_load_path
# Finds the user's home directory.
# Some comments from the ruby-talk list regarding finding the home
# I have HOME, USERPROFILE and HOMEDRIVE + HOMEPATH. Ruby seems
# to be depending on HOME in those code samples. I propose that
# it should fallback to USERPROFILE and HOMEDRIVE + HOMEPATH (at
# FIXME move to pathsupport
windows = File::ALT_SEPARATOR
if not windows or RUBY_VERSION >= '1.9' then