2007-11-10 10:48:56 +03:00
|
|
|
#--
|
|
|
|
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
|
|
|
|
# All rights reserved.
|
|
|
|
# See LICENSE.txt for permissions.
|
|
|
|
#++
|
|
|
|
|
|
|
|
require 'rubygems/format'
|
2011-01-19 03:08:49 +03:00
|
|
|
require 'rubygems/exceptions'
|
2007-11-10 10:48:56 +03:00
|
|
|
require 'rubygems/ext'
|
2007-11-25 06:26:36 +03:00
|
|
|
require 'rubygems/require_paths_builder'
|
2011-01-29 02:46:47 +03:00
|
|
|
require 'rubygems/user_interaction'
|
2007-11-10 10:48:56 +03:00
|
|
|
|
|
|
|
##
|
2009-06-10 01:38:59 +04:00
|
|
|
# The installer class processes RubyGem .gem files and installs the files
|
|
|
|
# contained in the .gem into the Gem.path.
|
2007-11-10 10:48:56 +03:00
|
|
|
#
|
|
|
|
# Gem::Installer does the work of putting files in all the right places on the
|
|
|
|
# filesystem including unpacking the gem into its gem dir, installing the
|
|
|
|
# gemspec in the specifications dir, storing the cached gem in the cache dir,
|
|
|
|
# and installing either wrappers or symlinks for executables.
|
2009-06-10 01:38:59 +04:00
|
|
|
#
|
2011-01-20 00:23:04 +03:00
|
|
|
# The installer invokes pre and post install hooks. Hooks can be added either
|
2009-06-10 01:38:59 +04:00
|
|
|
# through a rubygems_plugin.rb file in an installed gem or via a
|
|
|
|
# rubygems/defaults/#{RUBY_ENGINE}.rb or rubygems/defaults/operating_system.rb
|
|
|
|
# file. See Gem.pre_install and Gem.post_install for details.
|
2008-09-25 14:13:50 +04:00
|
|
|
|
2007-11-10 10:48:56 +03:00
|
|
|
class Gem::Installer
|
|
|
|
|
2009-06-10 01:38:59 +04:00
|
|
|
##
|
|
|
|
# Paths where env(1) might live. Some systems are broken and have it in
|
|
|
|
# /bin
|
|
|
|
|
|
|
|
ENV_PATHS = %w[/usr/bin/env /bin/env]
|
|
|
|
|
2007-11-10 10:48:56 +03:00
|
|
|
##
|
|
|
|
# Raised when there is an error while building extensions.
|
|
|
|
#
|
|
|
|
class ExtensionBuildError < Gem::InstallError; end
|
|
|
|
|
|
|
|
include Gem::UserInteraction
|
2007-12-20 11:39:12 +03:00
|
|
|
|
2011-01-29 02:46:47 +03:00
|
|
|
include Gem::RequirePathsBuilder if Gem::QUICKLOADER_SUCKAGE
|
2007-11-10 10:48:56 +03:00
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
attr_reader :gem
|
|
|
|
|
2008-09-25 14:13:50 +04:00
|
|
|
##
|
|
|
|
# The directory a gem's executables will be installed into
|
|
|
|
|
|
|
|
attr_reader :bin_dir
|
|
|
|
|
|
|
|
##
|
|
|
|
# The gem repository the gem will be installed into
|
|
|
|
|
|
|
|
attr_reader :gem_home
|
|
|
|
|
2011-01-20 00:23:04 +03:00
|
|
|
##
|
|
|
|
# The options passed when the Gem::Installer was instantiated.
|
|
|
|
|
|
|
|
attr_reader :options
|
|
|
|
|
2008-09-25 14:13:50 +04:00
|
|
|
@path_warning = false
|
|
|
|
|
2007-12-20 11:39:12 +03:00
|
|
|
class << self
|
|
|
|
|
2008-09-25 14:13:50 +04:00
|
|
|
##
|
|
|
|
# True if we've warned about PATH not including Gem.bindir
|
|
|
|
|
|
|
|
attr_accessor :path_warning
|
|
|
|
|
2007-12-20 11:39:12 +03:00
|
|
|
attr_writer :exec_format
|
|
|
|
|
|
|
|
# Defaults to use Ruby's program prefix and suffix.
|
|
|
|
def exec_format
|
|
|
|
@exec_format ||= Gem.default_exec_format
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
2007-11-10 10:48:56 +03:00
|
|
|
##
|
|
|
|
# Constructs an Installer instance that will install the gem located at
|
|
|
|
# +gem+. +options+ is a Hash with the following keys:
|
|
|
|
#
|
|
|
|
# :env_shebang:: Use /usr/bin/env in bin wrappers.
|
|
|
|
# :force:: Overrides all version checks and security policy checks, except
|
|
|
|
# for a signed-gems-only policy.
|
|
|
|
# :ignore_dependencies:: Don't raise if a dependency is missing.
|
|
|
|
# :install_dir:: The directory to install the gem into.
|
2007-12-20 11:39:12 +03:00
|
|
|
# :format_executable:: Format the executable the same as the ruby executable.
|
|
|
|
# If your ruby is ruby18, foo_exec will be installed as
|
|
|
|
# foo_exec18.
|
2007-11-10 10:48:56 +03:00
|
|
|
# :security_policy:: Use the specified security policy. See Gem::Security
|
|
|
|
# :wrappers:: Install wrappers if true, symlinks if false.
|
2008-06-18 02:04:18 +04:00
|
|
|
|
2007-11-10 10:48:56 +03:00
|
|
|
def initialize(gem, options={})
|
2011-01-19 03:08:49 +03:00
|
|
|
require 'fileutils'
|
|
|
|
|
2007-11-10 10:48:56 +03:00
|
|
|
@gem = gem
|
2011-01-20 00:23:04 +03:00
|
|
|
@options = options
|
|
|
|
process_options
|
2007-11-10 10:48:56 +03:00
|
|
|
|
2008-10-26 02:58:43 +04:00
|
|
|
if options[:user_install] and not options[:unpack] then
|
2008-09-25 14:13:50 +04:00
|
|
|
@gem_home = Gem.user_dir
|
2011-01-20 00:23:04 +03:00
|
|
|
check_that_user_bin_dir_is_in_path
|
2008-06-26 06:06:00 +04:00
|
|
|
end
|
2011-06-01 07:45:05 +04:00
|
|
|
end
|
2008-06-26 06:06:00 +04:00
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
##
|
|
|
|
# Lazy accessor for the spec's gem directory.
|
|
|
|
|
|
|
|
def gem_dir
|
|
|
|
@gem_dir ||= spec.gem_dir.dup.untaint
|
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# Lazy accessor for the installer's Gem::Format instance.
|
|
|
|
|
|
|
|
def format
|
|
|
|
begin
|
|
|
|
@format ||= Gem::Format.from_file_by_path gem, @security_policy
|
|
|
|
rescue Gem::Package::FormatError
|
|
|
|
raise Gem::InstallError, "invalid gem format for #{gem}"
|
|
|
|
end
|
|
|
|
end
|
2010-02-22 05:52:35 +03:00
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
##
|
|
|
|
# Lazy accessor for the installer's spec.
|
2007-11-10 10:48:56 +03:00
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
def spec
|
|
|
|
@spec ||= format.spec
|
2007-11-10 10:48:56 +03:00
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# Installs the gem and returns a loaded Gem::Specification for the installed
|
|
|
|
# gem.
|
|
|
|
#
|
|
|
|
# The gem will be installed with the following structure:
|
|
|
|
#
|
|
|
|
# @gem_home/
|
|
|
|
# cache/<gem-version>.gem #=> a cached copy of the installed gem
|
|
|
|
# gems/<gem-version>/... #=> extracted files
|
|
|
|
# specifications/<gem-version>.gemspec #=> the Gem::Specification
|
2008-06-18 02:04:18 +04:00
|
|
|
|
2007-11-10 10:48:56 +03:00
|
|
|
def install
|
2011-06-01 07:45:05 +04:00
|
|
|
current_home = Gem.dir
|
|
|
|
current_path = Gem.paths.path
|
|
|
|
|
|
|
|
verify_gem_home(options[:unpack])
|
|
|
|
Gem.use_paths gem_home, current_path # HACK: shouldn't need Gem.paths.path
|
|
|
|
|
2007-11-10 10:48:56 +03:00
|
|
|
# If we're forcing the install then disable security unless the security
|
2011-01-20 00:23:04 +03:00
|
|
|
# policy says that we only install signed gems.
|
2007-11-10 10:48:56 +03:00
|
|
|
@security_policy = nil if @force and @security_policy and
|
|
|
|
not @security_policy.only_signed
|
|
|
|
|
2011-01-20 00:23:04 +03:00
|
|
|
unless @force
|
|
|
|
ensure_required_ruby_version_met
|
|
|
|
ensure_required_rubygems_version_met
|
|
|
|
ensure_dependencies_met unless @ignore_dependencies
|
|
|
|
end
|
2007-11-10 10:48:56 +03:00
|
|
|
|
2011-01-20 00:23:04 +03:00
|
|
|
Gem.pre_install_hooks.each do |hook|
|
|
|
|
result = hook.call self
|
2007-11-10 10:48:56 +03:00
|
|
|
|
2011-01-20 00:23:04 +03:00
|
|
|
if result == false then
|
|
|
|
location = " at #{$1}" if hook.inspect =~ /@(.*:\d+)/
|
2008-06-18 02:04:18 +04:00
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
message = "pre-install hook#{location} failed for #{spec.full_name}"
|
2011-01-20 00:23:04 +03:00
|
|
|
raise Gem::InstallError, message
|
2007-11-10 10:48:56 +03:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
Gem.ensure_gem_subdirectories gem_home
|
2007-11-10 10:48:56 +03:00
|
|
|
|
2011-03-01 12:41:32 +03:00
|
|
|
# Completely remove any previous gem files
|
2011-06-01 07:45:05 +04:00
|
|
|
FileUtils.rm_rf(gem_dir) if File.exist? gem_dir
|
2011-03-01 12:41:32 +03:00
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
FileUtils.mkdir_p gem_dir
|
2007-11-10 10:48:56 +03:00
|
|
|
|
|
|
|
extract_files
|
|
|
|
build_extensions
|
2011-01-20 00:23:04 +03:00
|
|
|
|
|
|
|
Gem.post_build_hooks.each do |hook|
|
|
|
|
result = hook.call self
|
|
|
|
|
|
|
|
if result == false then
|
2011-06-01 07:45:05 +04:00
|
|
|
FileUtils.rm_rf gem_dir
|
2011-01-20 00:23:04 +03:00
|
|
|
|
|
|
|
location = " at #{$1}" if hook.inspect =~ /@(.*:\d+)/
|
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
message = "post-build hook#{location} failed for #{spec.full_name}"
|
2011-01-20 00:23:04 +03:00
|
|
|
raise Gem::InstallError, message
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
generate_bin
|
2007-11-10 10:48:56 +03:00
|
|
|
write_spec
|
2007-12-20 11:39:12 +03:00
|
|
|
|
2011-01-29 02:46:47 +03:00
|
|
|
write_require_paths_file_if_needed if Gem::QUICKLOADER_SUCKAGE
|
2007-11-10 10:48:56 +03:00
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
cache_file = spec.cache_file
|
|
|
|
FileUtils.cp gem, cache_file unless File.exist? cache_file
|
2007-11-10 10:48:56 +03:00
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
say spec.post_install_message unless spec.post_install_message.nil?
|
2007-11-10 10:48:56 +03:00
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
spec.loaded_from = spec.spec_file
|
2007-11-10 10:48:56 +03:00
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
Gem::Specification.add_spec spec unless Gem::Specification.include? spec
|
2008-09-25 14:13:50 +04:00
|
|
|
|
|
|
|
Gem.post_install_hooks.each do |hook|
|
|
|
|
hook.call self
|
|
|
|
end
|
2008-06-18 02:04:18 +04:00
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
return spec
|
2007-11-10 10:48:56 +03:00
|
|
|
rescue Zlib::GzipFile::Error
|
2011-06-01 07:45:05 +04:00
|
|
|
raise Gem::InstallError, "gzip error installing #{gem}"
|
|
|
|
ensure
|
|
|
|
# conditional since we might be here because we're erroring out early.
|
|
|
|
if current_path
|
|
|
|
Gem.use_paths current_home, current_path
|
|
|
|
end
|
2007-11-10 10:48:56 +03:00
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# Ensure that the dependency is satisfied by the current installation of
|
|
|
|
# gem. If it is not an exception is raised.
|
|
|
|
#
|
|
|
|
# spec :: Gem::Specification
|
|
|
|
# dependency :: Gem::Dependency
|
2008-06-18 02:04:18 +04:00
|
|
|
|
2007-11-10 10:48:56 +03:00
|
|
|
def ensure_dependency(spec, dependency)
|
|
|
|
unless installation_satisfies_dependency? dependency then
|
|
|
|
raise Gem::InstallError, "#{spec.name} requires #{dependency}"
|
|
|
|
end
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
|
|
|
##
|
2008-09-25 14:13:50 +04:00
|
|
|
# True if the gems in the source_index satisfy +dependency+.
|
2008-06-18 02:04:18 +04:00
|
|
|
|
2007-11-10 10:48:56 +03:00
|
|
|
def installation_satisfies_dependency?(dependency)
|
2011-06-01 07:45:05 +04:00
|
|
|
not dependency.matching_specs.empty?
|
2007-11-10 10:48:56 +03:00
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# Unpacks the gem into the given directory.
|
2008-06-18 02:04:18 +04:00
|
|
|
|
2007-11-10 10:48:56 +03:00
|
|
|
def unpack(directory)
|
|
|
|
@gem_dir = directory
|
2011-06-01 07:45:05 +04:00
|
|
|
@format = Gem::Format.from_file_by_path gem, @security_policy
|
2007-11-10 10:48:56 +03:00
|
|
|
extract_files
|
|
|
|
end
|
|
|
|
|
|
|
|
##
|
2008-12-23 02:11:11 +03:00
|
|
|
# Writes the .gemspec specification (in Ruby) to the gem home's
|
|
|
|
# specifications directory.
|
2008-06-18 02:04:18 +04:00
|
|
|
|
2007-11-10 10:48:56 +03:00
|
|
|
def write_spec
|
2011-06-01 07:45:05 +04:00
|
|
|
file_name = spec.spec_file.untaint
|
2007-11-10 10:48:56 +03:00
|
|
|
|
|
|
|
File.open(file_name, "w") do |file|
|
2011-06-01 07:45:05 +04:00
|
|
|
file.puts spec.to_ruby_for_cache
|
2007-11-10 10:48:56 +03:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# Creates windows .bat files for easy running of commands
|
2008-06-18 02:04:18 +04:00
|
|
|
|
2010-04-22 12:24:42 +04:00
|
|
|
def generate_windows_script(filename, bindir)
|
2007-11-10 10:48:56 +03:00
|
|
|
if Gem.win_platform? then
|
|
|
|
script_name = filename + ".bat"
|
2007-12-20 11:39:12 +03:00
|
|
|
script_path = File.join bindir, File.basename(script_name)
|
|
|
|
File.open script_path, 'w' do |file|
|
2007-11-10 10:48:56 +03:00
|
|
|
file.puts windows_stub_script(bindir, filename)
|
|
|
|
end
|
2007-12-20 11:39:12 +03:00
|
|
|
|
|
|
|
say script_path if Gem.configuration.really_verbose
|
2007-11-10 10:48:56 +03:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def generate_bin
|
2011-06-01 07:45:05 +04:00
|
|
|
return if spec.executables.nil? or spec.executables.empty?
|
2007-11-10 10:48:56 +03:00
|
|
|
|
|
|
|
# If the user has asked for the gem to be installed in a directory that is
|
|
|
|
# the system gem directory, then use the system bin directory, else create
|
|
|
|
# (or use) a new bin dir under the gem_home.
|
2011-06-01 07:45:05 +04:00
|
|
|
bindir = @bin_dir || Gem.bindir(gem_home)
|
2007-11-10 10:48:56 +03:00
|
|
|
|
|
|
|
Dir.mkdir bindir unless File.exist? bindir
|
|
|
|
raise Gem::FilePermissionError.new(bindir) unless File.writable? bindir
|
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
spec.executables.each do |filename|
|
2007-11-10 10:48:56 +03:00
|
|
|
filename.untaint
|
2011-06-01 07:45:05 +04:00
|
|
|
bin_path = File.expand_path File.join(gem_dir, spec.bindir, filename)
|
|
|
|
|
|
|
|
unless File.exist? bin_path
|
|
|
|
warn "Hey?!?! Where did #{bin_path} go??"
|
|
|
|
next
|
2011-03-01 12:41:32 +03:00
|
|
|
end
|
2007-11-10 10:48:56 +03:00
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
mode = File.stat(bin_path).mode | 0111
|
|
|
|
FileUtils.chmod mode, bin_path
|
|
|
|
|
2007-11-10 10:48:56 +03:00
|
|
|
if @wrappers then
|
|
|
|
generate_bin_script filename, bindir
|
|
|
|
else
|
|
|
|
generate_bin_symlink filename, bindir
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# Creates the scripts to run the applications in the gem.
|
|
|
|
#--
|
|
|
|
# The Windows script is generated in addition to the regular one due to a
|
|
|
|
# bug or misfeature in the Windows shell's pipe. See
|
|
|
|
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/193379
|
2008-06-18 02:04:18 +04:00
|
|
|
|
2007-11-10 10:48:56 +03:00
|
|
|
def generate_bin_script(filename, bindir)
|
2007-12-20 11:39:12 +03:00
|
|
|
bin_script_path = File.join bindir, formatted_program_filename(filename)
|
|
|
|
|
2011-01-19 03:08:49 +03:00
|
|
|
FileUtils.rm_f bin_script_path # prior install may have been --no-wrappers
|
2007-12-20 11:39:12 +03:00
|
|
|
|
2011-03-01 12:41:32 +03:00
|
|
|
File.open bin_script_path, 'wb', 0755 do |file|
|
2011-01-19 03:08:49 +03:00
|
|
|
file.print app_script_text(filename)
|
|
|
|
end
|
2007-12-20 11:39:12 +03:00
|
|
|
|
2011-01-19 03:08:49 +03:00
|
|
|
say bin_script_path if Gem.configuration.really_verbose
|
2007-12-20 11:39:12 +03:00
|
|
|
|
2011-01-19 03:08:49 +03:00
|
|
|
generate_windows_script filename, bindir
|
2007-11-10 10:48:56 +03:00
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# Creates the symlinks to run the applications in the gem. Moves
|
|
|
|
# the symlink if the gem being installed has a newer version.
|
2008-06-18 02:04:18 +04:00
|
|
|
|
2007-11-10 10:48:56 +03:00
|
|
|
def generate_bin_symlink(filename, bindir)
|
2007-11-25 06:26:36 +03:00
|
|
|
if Gem.win_platform? then
|
|
|
|
alert_warning "Unable to use symlinks on Windows, installing wrapper"
|
2007-11-10 10:48:56 +03:00
|
|
|
generate_bin_script filename, bindir
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
src = File.join gem_dir, spec.bindir, filename
|
2007-12-20 11:39:12 +03:00
|
|
|
dst = File.join bindir, formatted_program_filename(filename)
|
2007-11-10 10:48:56 +03:00
|
|
|
|
|
|
|
if File.exist? dst then
|
|
|
|
if File.symlink? dst then
|
|
|
|
link = File.readlink(dst).split File::SEPARATOR
|
|
|
|
cur_version = Gem::Version.create(link[-3].sub(/^.*-/, ''))
|
2011-06-01 07:45:05 +04:00
|
|
|
return if spec.version < cur_version
|
2007-11-10 10:48:56 +03:00
|
|
|
end
|
|
|
|
File.unlink dst
|
|
|
|
end
|
|
|
|
|
2007-12-20 11:39:12 +03:00
|
|
|
FileUtils.symlink src, dst, :verbose => Gem.configuration.really_verbose
|
2007-11-10 10:48:56 +03:00
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# Generates a #! line for +bin_file_name+'s wrapper copying arguments if
|
|
|
|
# necessary.
|
2008-06-18 02:04:18 +04:00
|
|
|
|
2007-11-10 10:48:56 +03:00
|
|
|
def shebang(bin_file_name)
|
2009-03-15 06:01:39 +03:00
|
|
|
ruby_name = Gem::ConfigMap[:ruby_install_name] if @env_shebang
|
2011-06-01 07:45:05 +04:00
|
|
|
path = spec.bin_file bin_file_name
|
2009-03-09 10:03:39 +03:00
|
|
|
first_line = File.open(path, "rb") {|file| file.gets}
|
2009-06-10 01:38:59 +04:00
|
|
|
|
2009-03-09 10:03:39 +03:00
|
|
|
if /\A#!/ =~ first_line then
|
|
|
|
# Preserve extra words on shebang line, like "-w". Thanks RPA.
|
2009-03-15 06:01:39 +03:00
|
|
|
shebang = first_line.sub(/\A\#!.*?ruby\S*(?=(\s+\S+))/, "#!#{Gem.ruby}")
|
|
|
|
opts = $1
|
2009-03-09 10:03:39 +03:00
|
|
|
shebang.strip! # Avoid nasty ^M issues.
|
2009-03-15 06:01:39 +03:00
|
|
|
end
|
2009-06-10 01:38:59 +04:00
|
|
|
|
|
|
|
if not ruby_name then
|
2009-03-15 06:01:39 +03:00
|
|
|
"#!#{Gem.ruby}#{opts}"
|
2009-06-10 01:38:59 +04:00
|
|
|
elsif opts then
|
|
|
|
"#!/bin/sh\n'exec' #{ruby_name.dump} '-x' \"$0\" \"$@\"\n#{shebang}"
|
2007-11-10 10:48:56 +03:00
|
|
|
else
|
2009-03-09 10:03:39 +03:00
|
|
|
# Create a plain shebang line.
|
2009-06-10 01:38:59 +04:00
|
|
|
@env_path ||= ENV_PATHS.find {|env_path| File.executable? env_path }
|
2009-03-15 06:01:39 +03:00
|
|
|
"#!#{@env_path} #{ruby_name}"
|
2007-11-10 10:48:56 +03:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2011-01-20 00:23:04 +03:00
|
|
|
def ensure_required_ruby_version_met
|
2011-06-01 07:45:05 +04:00
|
|
|
if rrv = spec.required_ruby_version then
|
2011-01-20 00:23:04 +03:00
|
|
|
unless rrv.satisfied_by? Gem.ruby_version then
|
2011-06-01 07:45:05 +04:00
|
|
|
raise Gem::InstallError, "#{spec.name} requires Ruby version #{rrv}."
|
2011-01-20 00:23:04 +03:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def ensure_required_rubygems_version_met
|
2011-06-01 07:45:05 +04:00
|
|
|
if rrgv = spec.required_rubygems_version then
|
2011-01-20 00:23:04 +03:00
|
|
|
unless rrgv.satisfied_by? Gem::Version.new(Gem::VERSION) then
|
|
|
|
raise Gem::InstallError,
|
2011-06-01 07:45:05 +04:00
|
|
|
"#{spec.name} requires RubyGems version #{rrgv}. " +
|
2011-01-20 00:23:04 +03:00
|
|
|
"Try 'gem update --system' to update RubyGems itself."
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def ensure_dependencies_met
|
2011-06-01 07:45:05 +04:00
|
|
|
deps = spec.runtime_dependencies
|
|
|
|
deps |= spec.development_dependencies if @development
|
2011-01-20 00:23:04 +03:00
|
|
|
|
|
|
|
deps.each do |dep_gem|
|
2011-06-01 07:45:05 +04:00
|
|
|
ensure_dependency spec, dep_gem
|
2011-01-20 00:23:04 +03:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def process_options
|
|
|
|
@options = {
|
|
|
|
:bin_dir => nil,
|
|
|
|
:env_shebang => false,
|
|
|
|
:exec_format => false,
|
|
|
|
:force => false,
|
|
|
|
:install_dir => Gem.dir,
|
2011-02-01 06:11:34 +03:00
|
|
|
}.merge options
|
2011-01-20 00:23:04 +03:00
|
|
|
|
2011-02-01 06:11:34 +03:00
|
|
|
@env_shebang = options[:env_shebang]
|
|
|
|
@force = options[:force]
|
2011-06-01 07:45:05 +04:00
|
|
|
@gem_home = options[:install_dir]
|
2011-02-01 06:11:34 +03:00
|
|
|
@ignore_dependencies = options[:ignore_dependencies]
|
|
|
|
@format_executable = options[:format_executable]
|
|
|
|
@security_policy = options[:security_policy]
|
|
|
|
@wrappers = options[:wrappers]
|
|
|
|
@bin_dir = options[:bin_dir]
|
|
|
|
@development = options[:development]
|
2011-01-20 00:23:04 +03:00
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
raise "NOTE: Installer option :source_index is dead" if
|
|
|
|
options[:source_index]
|
2011-01-20 00:23:04 +03:00
|
|
|
end
|
|
|
|
|
|
|
|
def check_that_user_bin_dir_is_in_path
|
2011-07-27 05:40:07 +04:00
|
|
|
user_bin_dir = @bin_dir || Gem.bindir(gem_home)
|
2011-01-20 00:23:04 +03:00
|
|
|
unless ENV['PATH'].split(File::PATH_SEPARATOR).include? user_bin_dir then
|
|
|
|
unless self.class.path_warning then
|
|
|
|
alert_warning "You don't have #{user_bin_dir} in your PATH,\n\t gem executables will not run."
|
|
|
|
self.class.path_warning = true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def verify_gem_home(unpack = false)
|
2011-06-01 07:45:05 +04:00
|
|
|
FileUtils.mkdir_p gem_home
|
|
|
|
raise Gem::FilePermissionError, gem_home unless
|
|
|
|
unpack or File.writable?(gem_home)
|
2011-01-20 00:23:04 +03:00
|
|
|
end
|
|
|
|
|
2008-06-18 02:04:18 +04:00
|
|
|
##
|
2007-11-10 10:48:56 +03:00
|
|
|
# Return the text for an application file.
|
2008-06-18 02:04:18 +04:00
|
|
|
|
2007-11-10 10:48:56 +03:00
|
|
|
def app_script_text(bin_file_name)
|
2011-06-01 07:45:05 +04:00
|
|
|
return <<-TEXT
|
2007-11-10 10:48:56 +03:00
|
|
|
#{shebang bin_file_name}
|
|
|
|
#
|
|
|
|
# This file was generated by RubyGems.
|
|
|
|
#
|
2011-06-01 07:45:05 +04:00
|
|
|
# The application '#{spec.name}' is installed as part of a gem, and
|
2007-11-10 10:48:56 +03:00
|
|
|
# this file is here to facilitate running it.
|
|
|
|
#
|
|
|
|
|
|
|
|
require 'rubygems'
|
|
|
|
|
|
|
|
version = "#{Gem::Requirement.default}"
|
|
|
|
|
|
|
|
if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
|
|
|
|
version = $1
|
|
|
|
ARGV.shift
|
|
|
|
end
|
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
gem '#{spec.name}', version
|
|
|
|
load Gem.bin_path('#{spec.name}', '#{bin_file_name}', version)
|
2007-11-10 10:48:56 +03:00
|
|
|
TEXT
|
|
|
|
end
|
|
|
|
|
2008-06-18 02:04:18 +04:00
|
|
|
##
|
2007-11-10 10:48:56 +03:00
|
|
|
# return the stub script text used to launch the true ruby script
|
2008-06-18 02:04:18 +04:00
|
|
|
|
2007-11-10 10:48:56 +03:00
|
|
|
def windows_stub_script(bindir, bin_file_name)
|
2011-06-01 07:45:05 +04:00
|
|
|
ruby = File.basename(Gem.ruby).chomp('"')
|
|
|
|
return <<-TEXT
|
2007-11-10 10:48:56 +03:00
|
|
|
@ECHO OFF
|
|
|
|
IF NOT "%~f0" == "~f0" GOTO :WinNT
|
2011-06-01 07:45:05 +04:00
|
|
|
@"#{ruby}" "#{File.join(bindir, bin_file_name)}" %1 %2 %3 %4 %5 %6 %7 %8 %9
|
2007-11-10 10:48:56 +03:00
|
|
|
GOTO :EOF
|
|
|
|
:WinNT
|
2011-06-01 07:45:05 +04:00
|
|
|
@"#{ruby}" "%~dpn0" %*
|
2007-11-10 10:48:56 +03:00
|
|
|
TEXT
|
2011-06-01 07:45:05 +04:00
|
|
|
|
2007-11-10 10:48:56 +03:00
|
|
|
end
|
|
|
|
|
2008-06-18 02:04:18 +04:00
|
|
|
##
|
2007-11-10 10:48:56 +03:00
|
|
|
# Builds extensions. Valid types of extensions are extconf.rb files,
|
|
|
|
# configure scripts and rakefiles or mkrf_conf files.
|
2008-06-18 02:04:18 +04:00
|
|
|
|
2007-11-10 10:48:56 +03:00
|
|
|
def build_extensions
|
2011-06-01 07:45:05 +04:00
|
|
|
return if spec.extensions.empty?
|
2007-11-10 10:48:56 +03:00
|
|
|
say "Building native extensions. This could take a while..."
|
2011-06-01 07:45:05 +04:00
|
|
|
dest_path = File.join gem_dir, spec.require_paths.first
|
2007-11-10 10:48:56 +03:00
|
|
|
ran_rake = false # only run rake once
|
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
spec.extensions.each do |extension|
|
2007-11-10 10:48:56 +03:00
|
|
|
break if ran_rake
|
|
|
|
results = []
|
|
|
|
|
|
|
|
builder = case extension
|
|
|
|
when /extconf/ then
|
|
|
|
Gem::Ext::ExtConfBuilder
|
|
|
|
when /configure/ then
|
|
|
|
Gem::Ext::ConfigureBuilder
|
|
|
|
when /rakefile/i, /mkrf_conf/i then
|
|
|
|
ran_rake = true
|
|
|
|
Gem::Ext::RakeBuilder
|
|
|
|
else
|
|
|
|
results = ["No builder for extension '#{extension}'"]
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
|
2007-12-20 11:39:12 +03:00
|
|
|
|
2011-01-29 02:46:47 +03:00
|
|
|
extension_dir = begin
|
2011-06-01 07:45:05 +04:00
|
|
|
File.join gem_dir, File.dirname(extension)
|
2011-01-29 02:46:47 +03:00
|
|
|
rescue TypeError # extension == nil
|
2011-06-01 07:45:05 +04:00
|
|
|
gem_dir
|
2011-01-29 02:46:47 +03:00
|
|
|
end
|
2011-02-01 06:11:34 +03:00
|
|
|
|
2011-01-29 02:46:47 +03:00
|
|
|
|
|
|
|
begin
|
|
|
|
Dir.chdir extension_dir do
|
2011-06-01 07:45:05 +04:00
|
|
|
results = builder.build(extension, gem_dir, dest_path, results)
|
2007-12-20 11:39:12 +03:00
|
|
|
|
2011-01-29 02:46:47 +03:00
|
|
|
say results.join("\n") if Gem.configuration.really_verbose
|
|
|
|
end
|
2010-11-08 23:58:42 +03:00
|
|
|
rescue
|
2007-11-10 10:48:56 +03:00
|
|
|
results = results.join "\n"
|
|
|
|
|
2011-01-29 02:46:47 +03:00
|
|
|
gem_make_out = File.join extension_dir, 'gem_make.out'
|
|
|
|
|
|
|
|
open gem_make_out, 'wb' do |io| io.puts results end
|
2007-11-10 10:48:56 +03:00
|
|
|
|
|
|
|
message = <<-EOF
|
|
|
|
ERROR: Failed to build gem native extension.
|
|
|
|
|
2011-01-29 02:46:47 +03:00
|
|
|
#{results}
|
2007-11-10 10:48:56 +03:00
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
Gem files will remain installed in #{gem_dir} for inspection.
|
2011-01-29 02:46:47 +03:00
|
|
|
Results logged to #{gem_make_out}
|
|
|
|
EOF
|
2007-11-10 10:48:56 +03:00
|
|
|
|
|
|
|
raise ExtensionBuildError, message
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# Reads the file index and extracts each file into the gem directory.
|
|
|
|
#
|
|
|
|
# Ensures that files can't be installed outside the gem directory.
|
2008-06-18 02:04:18 +04:00
|
|
|
|
2007-11-10 10:48:56 +03:00
|
|
|
def extract_files
|
|
|
|
raise ArgumentError, "format required to extract from" if @format.nil?
|
|
|
|
|
|
|
|
@format.file_entries.each do |entry, file_data|
|
|
|
|
path = entry['path'].untaint
|
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
if path.start_with? "/" then # for extra sanity
|
|
|
|
raise Gem::InstallError, "attempt to install file into #{entry['path']}"
|
2007-11-10 10:48:56 +03:00
|
|
|
end
|
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
path = File.expand_path File.join(gem_dir, path)
|
2007-11-10 10:48:56 +03:00
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
unless path.start_with? gem_dir then
|
|
|
|
msg = "attempt to install file into %p under %s" %
|
|
|
|
[entry['path'], gem_dir]
|
2007-11-10 10:48:56 +03:00
|
|
|
raise Gem::InstallError, msg
|
|
|
|
end
|
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
FileUtils.rm_rf(path) if File.exist? path
|
2011-01-19 03:08:49 +03:00
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
dir = File.dirname path
|
|
|
|
FileUtils.mkdir_p dir unless File.exist? dir
|
2007-11-10 10:48:56 +03:00
|
|
|
|
|
|
|
File.open(path, "wb") do |out|
|
|
|
|
out.write file_data
|
|
|
|
end
|
2007-12-20 11:39:12 +03:00
|
|
|
|
2008-06-18 02:04:18 +04:00
|
|
|
FileUtils.chmod entry['mode'], path
|
|
|
|
|
2007-12-20 11:39:12 +03:00
|
|
|
say path if Gem.configuration.really_verbose
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2008-06-18 02:04:18 +04:00
|
|
|
##
|
2007-12-20 11:39:12 +03:00
|
|
|
# Prefix and suffix the program filename the same as ruby.
|
2008-06-18 02:04:18 +04:00
|
|
|
|
2007-12-20 11:39:12 +03:00
|
|
|
def formatted_program_filename(filename)
|
|
|
|
if @format_executable then
|
|
|
|
self.class.exec_format % File.basename(filename)
|
|
|
|
else
|
|
|
|
filename
|
2007-11-10 10:48:56 +03:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2011-06-01 07:45:05 +04:00
|
|
|
##
|
|
|
|
#
|
|
|
|
# Return the target directory where the gem is to be installed. This
|
|
|
|
# directory is not guaranteed to be populated.
|
|
|
|
#
|
|
|
|
|
|
|
|
def dir
|
|
|
|
gem_dir.to_s
|
|
|
|
end
|
2007-11-10 10:48:56 +03:00
|
|
|
end
|
|
|
|
|