# == Ruby Version Manager - Ruby API
#
# Provides a wrapper around the command line api implemented as part of the api.
# If you're not familiar with rvm, please read http://rvm.beginrescueend.com/
# first.
#
# == Usage
#
# When using the rvm ruby api, you gain access to most of the commands, including the set
# functionality. As a side node, the RVM module provides access to most of the api
# both via direct api wrappers (of the form _ - e.g. +alias_create+,
# +gemset_use+ and +wrapper+).
#
# == The Environment Model
#
# The RVM ruby api is implemented using an environment model. Each environment maps directly
# to some ruby string interpretable by rvm (e.g. +ree+, +ruby-1.8.7-p174+, +system+, +rbx@rails+
# and so on) and is considered a sandboxed environment (for commands like use etc) in which you
# can deal with rvm. it's worth noting that a single environment can have multiple environment
# instances and for the most part creating of these instances is best handled by the RVM.environment
# and RVM.environments methods.
#
# Each Environment (and instance of RVM::Environment) provides access to the rvm ruby api (in some
# cases, the api may not directly be related to the current ruby - but for simplicity / consistency
# purposes, they are still implemented as methods of RVM::Environment).
#
# When you perform an action with side effects (e.g. RVM::Environment#gemset_use or RVM::Environment#use)
# this will mutate the ruby string of the given environment (hence, an environment is considered mutable).
#
# Lastly, for the actual command line work, RVM::Environment works with an instance of RVM::Shell::AbstractWrapper.
# This performs logic (such as correctly escaping strings, calling the environment and such) in a way that
# is both reusable and simplified.
#
# By default, method_missing is used on the RVM module to proxy method calls to RVM.current (itself
# calling RVM::Environment.current), meaning things like RVM.gemset_name, RVM.alias_create and the like
# work. This is considered the 'global' instance and should be avoided unless needed directly.
#
# RVM::Environment.current will first attempt to use the current ruby string (determined by
# +ENV['GEM_HOME']+ but will fall back to using the rubies load path if that isn't available).
#
# In many cases, (e.g. +alias+, +list+ and the like) there is a more ruby-like wrapper class,
# typically available via RVM::Environment#.
#
# == Side Notes
#
# In the cases this api differs, see the RVM::Environment class for more information.
#
# You can check the name of a given environment in two ways - RVM::Environment#environment_name
# for the short version / the version set by RVM::Environment#use, RVM::Environment#gemset_use
# or RVM.environment. If you wish to get the full, expanded string (which has things such as
# the actual version of the selected ruby), you instead with to use RVM::Environment#expanded_name.
#
# Lastly, If you do need to pass environment variables to a specific environment, please use
# RVM::Environment.new, versus RVM.environment
#
module RVM
require 'rvm/errors'
autoload :Shell, 'rvm/shell'
autoload :Environment, 'rvm/environment'
autoload :Version, 'rvm/version'
class << self
# Returns the current global environment.
def current
Environment.current
end
# Reset the current global environment to the default / what it was
# when the process first started.
def reset_current!
Environment.reset_current!
end
# Returns an array of multiple environments. If given
# a block, will yield each time with the given environment.
#
# RVM.environments("ree@rails3,rbx@rails3") do |env|
# puts "Full environment: #{env.expanded_name}"
# end
#
# Alternatively, you can use the more ruby-like fashion:
#
# RVM.environments("ree@rails3", "rbx@rails3") do |env|
# puts "Full environment: #{env.expanded_name}"
# end
#
def environments(*names, &blk)
# Normalize the names before using them on for the environment.
names.flatten.join(",").split(",").uniq.map do |n|
environment(n, &blk)
end
end
# Returns the environment with the given name.
# If passed a block, will yield with that as the single argument.
#
# RVM.environment("ree@rails3") do |env|
# puts "Gemset is #{env.gemset.name}"
# end
#
def environment(name)
# TODO: Maintain an Environment cache.
# The cache needs to track changes via use etc though.
env = Environment.new(name)
yield env if block_given?
env
end
# Merges items into the default config, essentially
# setting environment variables passed to child processes:
#
# RVM.merge_config!({
# :some_shell_variable => "me",
# })
#
def merge_config!(config = {})
Environment.merge_config!(config)
end
# Returns the current 'best guess' value for rvm_path.
def path
Environment.rvm_path
end
# Shortcut to set rvm_path. Will set it on all new instances
# but wont affect currently running environments.
def path=(value)
Environment.rvm_path = value
end
private
def cache_method_call(name)
class_eval <<-END, __FILE__, __LINE__
def #{name}(*args, &blk)
current.__send__(:#{name}, *args, &blk)
end
END
end
# Proxies methods to the current environment, creating a
# method before dispatching to speed up future calls.
def method_missing(name, *args, &blk)
if current.respond_to?(name)
cache_method_call name
current.__send__ name, *args, &blk
else
super
end
end
end
end