1. Gem::
  2. Installer

class Gem::Installer

The installer installs the files contained in the .gem into the Gem.home.

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.

The installer invokes pre and post install hooks. Hooks can be added either 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. SeeGem.pre_install andGem.post_install for details.

Constants

ENV_PATHS

Paths where env(1) might live. Some systems are broken and have it in /bin

Attributes

exec_format[W]

Overrides the executable format.

This is a sprintf format with a “%s” which will be replaced with the executable name. It is based off the ruby executable name’s difference from “ruby”.

bin_dir[R]

The directory a gem’s executables will be installed into

gem_home[R]

The gem repository the gem will be installed into

options[R]

The options passed when theGem::Installer was instantiated.

package[R]

The gem package instance.

Public Class Methods

Source
# File lib/rubygems/installer.rb, line 88defself.at(path,options = {})security_policy =options[:security_policy]package =Gem::Package.newpath,security_policynewpackage,optionsend

Construct an installer object for the gem file located atpath

Source
# File lib/rubygems/installer.rb, line 80defexec_format@exec_format||=Gem.default_exec_formatend

Defaults to use Ruby’s program prefix and suffix.

Source
# File lib/rubygems/installer.rb, line 126defself.for_spec(spec,options = {})# FIXME: we should have a real Package class for thisnewFakePackage.new(spec),optionsend

Construct an installer object for an ephemeral gem (one where we don’t actually have a .gem file, just a spec)

Source
# File lib/rubygems/installer.rb, line 156definitialize(package,options = {})require"fileutils"@options =options@package =packageprocess_options@package.dir_mode =options[:dir_mode]@package.prog_mode =options[:prog_mode]@package.data_mode =options[:data_mode]end

Constructs anInstaller instance that will install the gem atpackage which can either be a path or an instance ofGem::Package.options is aHash with the following keys:

:bin_dir

Where to put a bin wrapper if needed.

:development

Whether or not development dependencies should be installed.

: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.

:format_executable

Format the executable the same as the Ruby executable. If your Ruby is ruby18, foo_exec will be installed as foo_exec18.

:ignore_dependencies

Don’t raise if a dependency is missing.

:install_dir

The directory to install the gem into.

:security_policy

Use the specified security policy. SeeGem::Security

:user_install

Indicate that the gem should be unpacked into the users personal gem directory.

:only_install_dir

Only validate dependencies against what is in the install_dir

:wrappers

Install wrappers if true, symlinks if false.

:build_args

AnArray of arguments to pass to the extension builder process. If not set, thenGem::Command.build_args is used

:post_install_message

Print gem post install message if true

Public Instance Methods

Source
# File lib/rubygems/installer.rb, line 726defapp_script_text(bin_file_name)# NOTE: that the `load` lines cannot be indented, as old RG versions match# against the beginning of the line<<~TEXT      #{shebang bin_file_name}      #      # This file was generated by RubyGems.      #      # The application '#{spec.name}' is installed as part of a gem, and      # this file is here to facilitate running it.      #      require 'rubygems'      #{gemdeps_load(spec.name)}      version = "#{Gem::Requirement.default_prerelease}"      str = ARGV.first      if str        str = str.b[/\\A_(.*)_\\z/, 1]        if str and Gem::Version.correct?(str)          #{explicit_version_requirement(spec.name)}          ARGV.shift        end      end      if Gem.respond_to?(:activate_and_load_bin_path)        Gem.activate_and_load_bin_path('#{spec.name}', '#{bin_file_name}', version)      else        load Gem.activate_bin_path('#{spec.name}', '#{bin_file_name}', version)      end    TEXTend

Return the text for an application file.

Source
# File lib/rubygems/installer.rb, line 817defbuild_extensionsbuilder =Gem::Ext::Builder.newspec,build_args,Gem.target_rbconfigbuilder.build_extensionsend

Builds extensions. Valid types of extensions are extconf.rb files, configure scripts and rakefiles or mkrf_conf files.

Source
# File lib/rubygems/installer.rb, line 401defdefault_spec_dirdir =File.join(gem_home,"specifications","default")FileUtils.mkdir_pdirdirend
Source
# File lib/rubygems/installer.rb, line 411defdefault_spec_fileFile.joindefault_spec_dir,"#{spec.full_name}.gemspec"end

The location of the default spec file for default gems.

Source
# File lib/rubygems/installer.rb, line 858defdirgem_dir.to_send

Return the target directory where the gem is to be installed. This directory is not guaranteed to be populated.

Source
# File lib/rubygems/installer.rb, line 367defensure_dependency(spec,dependency)unlessinstallation_satisfies_dependency?dependencyraiseGem::InstallError,"#{spec.name} requires #{dependency}"endtrueend

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

Source
# File lib/rubygems/installer.rb, line 607defensure_loadable_specruby =spec.to_ruby_for_cachebeginevalrubyrescueStandardError,SyntaxError=>eraiseGem::InstallError,"The specification for #{spec.full_name} is corrupt (#{e.class})"endend

Ensures theGem::Specification written out for this gem is loadable upon installation.

Source
# File lib/rubygems/installer.rb, line 768defexplicit_version_requirement(name)code ="version = str"returncodeunlessname=="bundler"code+=<<~TEXT      ENV['BUNDLER_VERSION'] = str    TEXTend
Source
# File lib/rubygems/installer.rb, line 837defextract_bin@package.extract_filesgem_dir,"#{spec.bindir}/*"end

Extracts only the bin/ files from the gem into the gem directory. This is used by default gems to allow a gem-aware stub to function without the full gem installed.

Source
# File lib/rubygems/installer.rb, line 828defextract_files@package.extract_filesgem_dirend

Reads the file index and extracts each file into the gem directory.

Ensures that files can’t be installed outside the gem directory.

Source
# File lib/rubygems/installer.rb, line 844defformatted_program_filename(filename)if@format_executableself.class.exec_format%File.basename(filename)elsefilenameendend

Prefix and suffix the program filename the same as ruby.

Source
# File lib/rubygems/installer.rb, line 865defgem@package.gem.pathend

Filename of the gem being installed.

Source
# File lib/rubygems/installer.rb, line 249defgem_dir@gem_dir||=File.join(gem_home,"gems",spec.full_name)end

Lazy accessor for the spec’s gem directory.

Source
# File lib/rubygems/installer.rb, line 759defgemdeps_load(name)return""ifname=="bundler"<<~TEXT      Gem.use_gemdeps    TEXTend
Source
# File lib/rubygems/installer.rb, line 509defgenerate_bin_script(filename,bindir)bin_script_path =File.joinbindir,formatted_program_filename(filename)Gem.open_file_with_lock(bin_script_path)dorequire"fileutils"FileUtils.rm_fbin_script_path# prior install may have been --no-wrappersFile.open(bin_script_path,"wb",0o755)do|file|file.writeapp_script_text(filename)file.chmod(options[:prog_mode]||0o755)endendverbosebin_script_pathgenerate_windows_scriptfilename,bindirend

Creates the scripts to run the applications in the gem.

Source
# File lib/rubygems/installer.rb, line 531defgenerate_bin_symlink(filename,bindir)src =File.joingem_dir,spec.bindir,filenamedst =File.joinbindir,formatted_program_filename(filename)ifFile.exist?dstifFile.symlink?dstlink =File.readlink(dst).splitFile::SEPARATORcur_version =Gem::Version.create(link[-3].sub(/^.*-/,""))returnifspec.version<cur_versionendFile.unlinkdstendFileUtils.symlinksrc,dst,verbose:Gem.configuration.really_verboserescueNotImplementedError,SystemCallErroralert_warning"Unable to use symlinks, installing wrapper"generate_bin_scriptfilename,bindirend

Creates the symlinks to run the applications in the gem. Moves the symlink if the gem being installed has a newer version.

Source
# File lib/rubygems/installer.rb, line 439defgenerate_windows_script(filename,bindir)ifGem.win_platform?script_name =formatted_program_filename(filename)+".bat"script_path =File.joinbindir,File.basename(script_name)File.openscript_path,"w"do|file|file.putswindows_stub_script(bindir,filename)endverbosescript_pathendend

Creates windows .bat files for easy running of commands

Source
# File lib/rubygems/installer.rb, line 271definstallpre_install_checksrun_pre_install_hooks# Set loaded_from to ensure extension_dir is correctspec.loaded_from =spec_file# Completely remove any previous gem filesFileUtils.rm_rfgem_dirFileUtils.rm_rfspec.extension_dirdir_mode =options[:dir_mode]FileUtils.mkdir_pgem_dir,mode:dir_mode&&0o755extract_filesbuild_extensionswrite_build_info_filerun_post_build_hooksgenerate_bingenerate_pluginswrite_specwrite_cache_fileFile.chmod(dir_mode,gem_dir)ifdir_modesayspec.post_install_messageifoptions[:post_install_message]&&!spec.post_install_message.nil?Gem::Specification.add_spec(spec)unless@install_dirload_pluginrun_post_install_hooksspecrescueErrno::EACCES=>e# Permission denied - /path/to/fooraiseGem::FilePermissionError,e.message.split(" - ").lastend

Installs the gem and returns a loadedGem::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
Source
# File lib/rubygems/installer.rb, line 377definstallation_satisfies_dependency?(dependency)returntrueif@options[:development]&&dependency.type==:developmentreturntrueifinstalled_specs.detect {|s|dependency.matches_spec?s }returnfalseif@only_install_dir!dependency.matching_specs.empty?end

True if the gems in the system satisfydependency.

Source
# File lib/rubygems/installer.rb, line 347definstalled_specs@installed_specs||=beginspecs = []Gem::Util.glob_files_in_dir("*.gemspec",File.join(gem_home,"specifications")).eachdo|path|spec =Gem::Specification.loadpathspecs<<specifspecendspecsendend

Return anArray of Specifications contained within thegem_home we’ll be installing into.

Source
# File lib/rubygems/installer.rb, line 878defpre_install_checksverify_gem_home# The name and require_paths must be verified first, since it could contain# ruby code that would be eval'ed in #ensure_loadable_specverify_specensure_loadable_specGem.ensure_gem_subdirectoriesgem_homereturntrueif@forceensure_dependencies_metunless@ignore_dependenciestrueend

Performs various checks before installing the gem such as the install repository is writable and its directories exist, required Ruby and rubygems versions are met and that dependencies are installed.

Version and dependency checks are skipped if this install is forced.

The dependent check will be skipped if the install is ignoring dependencies.

Source
# File lib/rubygems/installer.rb, line 565defshebang(bin_file_name)path =File.joingem_dir,spec.bindir,bin_file_namefirst_line =File.open(path,"rb",&:gets)||""iffirst_line.start_with?("#!")# Preserve extra words on shebang line, like "-w".  Thanks RPA.shebang =first_line.sub(/\A\#!.*?ruby\S*((\s+\S+)+)/,"#!#{Gem.ruby}")opts =$1shebang.strip!# Avoid nasty ^M issues.endifwhich =Gem.configuration[:custom_shebang]# replace bin_file_name with "ruby" to avoid endless loopswhich =which.gsub(/ #{bin_file_name}$/," #{ruby_install_name}")which =which.gsub(/\$(\w+)/)docase$1when"env"@env_path||=ENV_PATHS.find {|env_path|File.executable?env_path }when"ruby""#{Gem.ruby}#{opts}"when"exec"bin_file_namewhen"name"spec.nameendend"#!#{which}"elsif@env_shebang# Create a plain shebang line.@env_path||=ENV_PATHS.find {|env_path|File.executable?env_path }"#!#{@env_path} #{ruby_install_name}"else"#{bash_prolog_script}#!#{Gem.ruby}#{opts}"endend

Generates a! line forbin_file_name‘s wrapper copying arguments if necessary.

If the :custom_shebang config is set, then it is used as a template for how to create the shebang used for to run a gem’s executables.

The template supports 4 expansions:

$env    the path to the unix env utility$ruby   the path to the currently running ruby interpreter$exec   the path to the gem's executable$name   the name of the gem the executable is for
Source
# File lib/rubygems/installer.rb, line 256defspec@package.specend

Lazy accessor for the installer’s spec.

Source
# File lib/rubygems/installer.rb, line 397defspec_fileFile.joingem_home,"specifications","#{spec.full_name}.gemspec"end

The location of the spec file that is installed.

Source
# File lib/rubygems/installer.rb, line 387defunpack(directory)@gem_dir =directoryextract_filesend

Unpacks the gem into the given directory.

Source
# File lib/rubygems/installer.rb, line 693defverify_specunlessGem::Specification::VALID_NAME_PATTERN.match?(spec.name)raiseGem::InstallError,"#{spec} has an invalid name"endifspec.raw_require_paths.any? {|path|path=~/\R/ }raiseGem::InstallError,"#{spec} has an invalid require_paths"endifspec.extensions.any? {|ext|ext=~/\R/ }raiseGem::InstallError,"#{spec} has an invalid extensions"endif/\R/.match?(spec.platform.to_s)raiseGem::InstallError,"#{spec.platform} is an invalid platform"endunless/\A\d+\z/.match?(spec.specification_version.to_s)raiseGem::InstallError,"#{spec} has an invalid specification_version"endifspec.dependencies.any? {|dep|dep.type!=:runtime&&dep.type!=:development }raiseGem::InstallError,"#{spec} has an invalid dependencies"endifspec.dependencies.any? {|dep|dep.name=~/(?:\R|[<>])/ }raiseGem::InstallError,"#{spec} has an invalid dependencies"endend
Source
# File lib/rubygems/installer.rb, line 781defwindows_stub_script(bindir,bin_file_name)rb_topdir =RbConfig::TOPDIR||File.dirname(rb_config["bindir"])# get ruby executable file name from RbConfigruby_exe ="#{rb_config["RUBY_INSTALL_NAME"]}#{rb_config["EXEEXT"]}"ruby_exe ="ruby.exe"ifruby_exe.empty?ifFile.exist?(File.join(bindir,ruby_exe))# stub & ruby.exe within same folder.  Portable<<~TEXT        @ECHO OFF        @"%~dp0#{ruby_exe}" "%~dpn0" %*      TEXTelsifbindir.downcase.start_with?rb_topdir.downcase# stub within ruby folder, but not standard bin.  Portablerequire"pathname"from =Pathname.newbindirto   =Pathname.new"#{rb_topdir}/bin"rel  =to.relative_path_fromfrom<<~TEXT        @ECHO OFF        @"%~dp0#{rel}/#{ruby_exe}" "%~dpn0" %*      TEXTelse# outside ruby folder, maybe -user-install or bundler.  Portable, but ruby# is dependent on PATH<<~TEXT        @ECHO OFF        @#{ruby_exe} "%~dpn0" %*      TEXTendend

return the stub script text used to launch the true Ruby script

Source
# File lib/rubygems/installer.rb, line 900defwrite_build_info_filereturnifbuild_args.empty?build_info_dir =File.joingem_home,"build_info"dir_mode =options[:dir_mode]FileUtils.mkdir_pbuild_info_dir,mode:dir_mode&&0o755build_info_file =File.joinbuild_info_dir,"#{spec.full_name}.info"File.openbuild_info_file,"w"do|io|build_args.eachdo|arg|io.putsargendendFile.chmod(dir_mode,build_info_dir)ifdir_modeend

Writes the file containing the arguments for building this gem’s extensions.

Source
# File lib/rubygems/installer.rb, line 922defwrite_cache_filecache_file =File.joingem_home,"cache",spec.file_name@package.copy_tocache_fileend

Writes the .gem file to the cache directory

Source
# File lib/rubygems/installer.rb, line 432defwrite_default_specGem.write_binary(default_spec_file,spec.to_ruby)end

Writes the full .gemspec specification (in Ruby) to the gem home’s specifications/default directory.

In contrast towrite_spec, this keeps file lists, so the ‘gem contents` command works.

Source
# File lib/rubygems/installer.rb, line 419defwrite_specspec.installed_by_version =Gem.rubygems_versionGem.write_binary(spec_file,spec.to_ruby_for_cache)end

Writes the .gemspec specification (in Ruby) to the gem home’s specifications directory.

Private Instance Methods

Source
# File lib/rubygems/installer.rb, line 968defbash_prolog_scriptifload_relative_enabled?<<~EOS        #!/bin/sh        # -*- ruby -*-        _=_\\        =begin        bindir="${0%/*}"        ruby="$bindir/#{ruby_install_name}"        if [ ! -f "$ruby" ]; then          ruby="#{ruby_install_name}"        fi        exec "$ruby" "-x" "$0" "$@"        =end      EOSelse""endend
Source
# File lib/rubygems/installer.rb, line 949defbuild_args@build_args||=beginrequire_relative"command"Gem::Command.build_argsendend
Source
# File lib/rubygems/installer.rb, line 988defload_pluginspecs =Gem::Specification.find_all_by_name(spec.name)# If old version already exists, this plugin isn't loaded# immediately. It's for avoiding a case that multiple versions# are loaded at the same time.returnunlessspecs.size==1plugin_files =spec.plugins.mapdo|plugin|File.join(@plugins_dir,"#{spec.name}_plugin#{File.extname(plugin)}")endGem.load_plugin_files(plugin_files)end
Source
# File lib/rubygems/installer.rb, line 964defload_relative_enabled?rb_config["LIBRUBY_RELATIVE"]=="yes"end
Source
# File lib/rubygems/installer.rb, line 956defrb_configGem.target_rbconfigend
Source
# File lib/rubygems/installer.rb, line 960defruby_install_namerb_config["ruby_install_name"]end
Source
# File lib/rubygems/installer.rb, line 936defuser_install_dir# never install to user home in --build-root modereturnunless@build_root.nil?# Please note that @user_install might have three states:# * `true`: `--user-install`# * `false`: `--no-user-install` and# * `nil`: option was not specifiedif@user_install|| (@user_install.nil?&&Gem.default_user_install)Gem.user_direndend