Parent

Class Index [+]

Quicksearch

Gem::Installer

The installer class processes RubyGem .gem files and installs the files contained in the .gem into the Gem.path.

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 fires 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. See Gem.pre_install and Gem.post_install for details.

Constants

ENV_PATHS

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

Attributes

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

spec[R]

The Gem::Specification for the gem being installed

path_warning[RW]

True if we’ve warned about PATH not including Gem.bindir

exec_format[W]

Public Class Methods

exec_format() click to toggle source

Defaults to use Ruby’s program prefix and suffix.

    # File lib/rubygems/installer.rb, line 72
72:     def exec_format
73:       @exec_format ||= Gem.default_exec_format
74:     end
new(gem, options={}) click to toggle source

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.

:format_executable

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

:security_policy

Use the specified security policy. See Gem::Security

:wrappers

Install wrappers if true, symlinks if false.

     # File lib/rubygems/installer.rb, line 93
 93:   def initialize(gem, options={})
 94:     @gem = gem
 95: 
 96:     options = {
 97:       :bin_dir      => nil,
 98:       :env_shebang  => false,
 99:       :exec_format  => false,
100:       :force        => false,
101:       :install_dir  => Gem.dir,
102:       :source_index => Gem.source_index,
103:     }.merge options
104: 
105:     @env_shebang         = options[:env_shebang]
106:     @force               = options[:force]
107:     gem_home             = options[:install_dir]
108:     @gem_home            = File.expand_path(gem_home)
109:     @ignore_dependencies = options[:ignore_dependencies]
110:     @format_executable   = options[:format_executable]
111:     @security_policy     = options[:security_policy]
112:     @wrappers            = options[:wrappers]
113:     @bin_dir             = options[:bin_dir]
114:     @development         = options[:development]
115:     @source_index        = options[:source_index]
116: 
117:     begin
118:       @format = Gem::Format.from_file_by_path @gem, @security_policy
119:     rescue Gem::Package::FormatError
120:       raise Gem::InstallError, "invalid gem format for #{@gem}"
121:     end
122: 
123:     if options[:user_install] and not options[:unpack] then
124:       @gem_home = Gem.user_dir
125: 
126:       user_bin_dir = File.join(@gem_home, 'bin')
127:       unless ENV['PATH'].split(File::PATH_SEPARATOR).include? user_bin_dir then
128:         unless self.class.path_warning then
129:           alert_warning "You don't have #{user_bin_dir} in your PATH,\n\t  gem executables will not run."
130:           self.class.path_warning = true
131:         end
132:       end
133:     end
134: 
135:     FileUtils.mkdir_p @gem_home
136:     raise Gem::FilePermissionError, @gem_home unless
137:       options[:unpack] or File.writable? @gem_home
138: 
139:     @spec = @format.spec
140: 
141:     @gem_dir = File.join(@gem_home, "gems", @spec.full_name).untaint
142:   end

Public Instance Methods

app_script_text(bin_file_name) click to toggle source

Return the text for an application file.

     # File lib/rubygems/installer.rb, line 397
397:   def app_script_text(bin_file_name)
398:     #{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'version = "#{Gem::Requirement.default}"if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then  version = $1  ARGV.shiftendgem '#{@spec.name}', versionload Gem.bin_path('#{@spec.name}', '#{bin_file_name}', version)
399:   end
build_extensions() click to toggle source

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

     # File lib/rubygems/installer.rb, line 439
439:   def build_extensions
440:     return if @spec.extensions.empty?
441:     say "Building native extensions.  This could take a while..."
442:     start_dir = Dir.pwd
443:     dest_path = File.join @gem_dir, @spec.require_paths.first
444:     ran_rake = false # only run rake once
445: 
446:     @spec.extensions.each do |extension|
447:       break if ran_rake
448:       results = []
449: 
450:       builder = case extension
451:                 when /extconf/ then
452:                   Gem::Ext::ExtConfBuilder
453:                 when /configure/ then
454:                   Gem::Ext::ConfigureBuilder
455:                 when /rakefile/, /mkrf_conf/ then
456:                   ran_rake = true
457:                   Gem::Ext::RakeBuilder
458:                 else
459:                   results = ["No builder for extension '#{extension}'"]
460:                   nil
461:                 end
462: 
463:       begin
464:         Dir.chdir File.join(@gem_dir, File.dirname(extension))
465:         results = builder.build(extension, @gem_dir, dest_path, results)
466: 
467:         say results.join("\n") if Gem.configuration.really_verbose
468: 
469:       rescue => ex
470:         results = results.join "\n"
471: 
472:         File.open('gem_make.out', 'wb') { |f| f.puts results }
473: 
474:         message = ERROR: Failed to build gem native extension.#{results}Gem files will remain installed in #{@gem_dir} for inspection.Results logged to #{File.join(Dir.pwd, 'gem_make.out')}
475: 
476:         raise ExtensionBuildError, message
477:       ensure
478:         Dir.chdir start_dir
479:       end
480:     end
481:   end
ensure_dependency(spec, dependency) click to toggle source

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

     # File lib/rubygems/installer.rb, line 231
231:   def ensure_dependency(spec, dependency)
232:     unless installation_satisfies_dependency? dependency then
233:       raise Gem::InstallError, "#{spec.name} requires #{dependency}"
234:     end
235: 
236:     true
237:   end
extract_files() click to toggle source

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

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

     # File lib/rubygems/installer.rb, line 495
495:   def extract_files
496:     @gem_dir = File.expand_path @gem_dir
497: 
498:     raise ArgumentError, "format required to extract from" if @format.nil?
499: 
500:     @format.file_entries.each do |entry, file_data|
501:       path = entry['path'].untaint
502: 
503:       if path =~ /\A\// then # for extra sanity
504:         raise Gem::InstallError,
505:               "attempt to install file into #{entry['path'].inspect}"
506:       end
507: 
508:       path = File.expand_path File.join(@gem_dir, path)
509: 
510:       if path !~ /\A#{Regexp.escape @gem_dir}/ then
511:         msg = "attempt to install file into %p under %p" %
512:                 [entry['path'], @gem_dir]
513:         raise Gem::InstallError, msg
514:       end
515: 
516:       FileUtils.rm_rf(path) if File.exists?(path)
517:       FileUtils.mkdir_p File.dirname(path)
518: 
519:       File.open(path, "wb") do |out|
520:         out.write file_data
521:       end
522: 
523:       FileUtils.chmod entry['mode'], path
524: 
525:       say path if Gem.configuration.really_verbose
526:     end
527:   end
formatted_program_filename(filename) click to toggle source

Prefix and suffix the program filename the same as ruby.

     # File lib/rubygems/installer.rb, line 532
532:   def formatted_program_filename(filename)
533:     if @format_executable then
534:       self.class.exec_format % File.basename(filename)
535:     else
536:       filename
537:     end
538:   end
generate_bin() click to toggle source
     # File lib/rubygems/installer.rb, line 286
286:   def generate_bin
287:     return if @spec.executables.nil? or @spec.executables.empty?
288: 
289:     # If the user has asked for the gem to be installed in a directory that is
290:     # the system gem directory, then use the system bin directory, else create
291:     # (or use) a new bin dir under the gem_home.
292:     bindir = @bin_dir ? @bin_dir : Gem.bindir(@gem_home)
293: 
294:     Dir.mkdir bindir unless File.exist? bindir
295:     raise Gem::FilePermissionError.new(bindir) unless File.writable? bindir
296: 
297:     @spec.executables.each do |filename|
298:       filename.untaint
299:       bin_path = File.expand_path "#{@spec.bindir}/#{filename}", @gem_dir
300:       mode = File.stat(bin_path).mode | 0111
301:       File.chmod mode, bin_path
302: 
303:       if @wrappers then
304:         generate_bin_script filename, bindir
305:       else
306:         generate_bin_symlink filename, bindir
307:       end
308:     end
309:   end
generate_bin_script(filename, bindir) click to toggle source

Creates the scripts to run the applications in the gem.

     # File lib/rubygems/installer.rb, line 318
318:   def generate_bin_script(filename, bindir)
319:     bin_script_path = File.join bindir, formatted_program_filename(filename)
320: 
321:     exec_path = File.join @gem_dir, @spec.bindir, filename
322: 
323:     # HACK some gems don't have #! in their executables, restore 2008/06
324:     #if File.read(exec_path, 2) == '#!' then
325:       FileUtils.rm_f bin_script_path # prior install may have been --no-wrappers
326: 
327:       File.open bin_script_path, 'w', 0755 do |file|
328:         file.print app_script_text(filename)
329:       end
330: 
331:       say bin_script_path if Gem.configuration.really_verbose
332: 
333:       generate_windows_script filename, bindir
334:     #else
335:     #  FileUtils.rm_f bin_script_path
336:     #  FileUtils.cp exec_path, bin_script_path,
337:     #               :verbose => Gem.configuration.really_verbose
338:     #end
339:   end
generate_windows_script(filename, bindir) click to toggle source

Creates windows .bat files for easy running of commands

     # File lib/rubygems/installer.rb, line 274
274:   def generate_windows_script(filename, bindir)
275:     if Gem.win_platform? then
276:       script_name = filename + ".bat"
277:       script_path = File.join bindir, File.basename(script_name)
278:       File.open script_path, 'w' do |file|
279:         file.puts windows_stub_script(bindir, filename)
280:       end
281: 
282:       say script_path if Gem.configuration.really_verbose
283:     end
284:   end
install() click to toggle source

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
     # File lib/rubygems/installer.rb, line 155
155:   def install
156:     # If we're forcing the install then disable security unless the security
157:     # policy says that we only install singed gems.
158:     @security_policy = nil if @force and @security_policy and
159:                               not @security_policy.only_signed
160: 
161:     unless @force then
162:       if rrv = @spec.required_ruby_version then
163:         unless rrv.satisfied_by? Gem.ruby_version then
164:           raise Gem::InstallError, "#{@spec.name} requires Ruby version #{rrv}."
165:         end
166:       end
167: 
168:       if rrgv = @spec.required_rubygems_version then
169:         unless rrgv.satisfied_by? Gem::Version.new(Gem::VERSION) then
170:           raise Gem::InstallError,
171:             "#{@spec.name} requires RubyGems version #{rrgv}. " +
172:             "Try 'gem update --system' to update RubyGems itself."
173:         end
174:       end
175: 
176:       unless @ignore_dependencies then
177:         deps = @spec.runtime_dependencies
178:         deps |= @spec.development_dependencies if @development
179: 
180:         deps.each do |dep_gem|
181:           ensure_dependency @spec, dep_gem
182:         end
183:       end
184:     end
185: 
186:     Gem.pre_install_hooks.each do |hook|
187:       hook.call self
188:     end
189: 
190:     FileUtils.mkdir_p @gem_home unless File.directory? @gem_home
191: 
192:     Gem.ensure_gem_subdirectories @gem_home
193: 
194:     FileUtils.mkdir_p @gem_dir
195: 
196:     extract_files
197:     generate_bin
198:     build_extensions
199:     write_spec
200: 
201:     write_require_paths_file_if_needed
202: 
203:     # HACK remove?  Isn't this done in multiple places?
204:     cached_gem = File.join @gem_home, "cache", @gem.split(/\//).pop
205:     unless File.exist? cached_gem then
206:       FileUtils.cp @gem, File.join(@gem_home, "cache")
207:     end
208: 
209:     say @spec.post_install_message unless @spec.post_install_message.nil?
210: 
211:     @spec.loaded_from = File.join(@gem_home, 'specifications', @spec.spec_name)
212: 
213:     @source_index.add_spec @spec
214: 
215:     Gem.post_install_hooks.each do |hook|
216:       hook.call self
217:     end
218: 
219:     return @spec
220:   rescue Zlib::GzipFile::Error
221:     raise Gem::InstallError, "gzip error installing #{@gem}"
222:   end
installation_satisfies_dependency?(dependency) click to toggle source

True if the gems in the source_index satisfy dependency.

     # File lib/rubygems/installer.rb, line 242
242:   def installation_satisfies_dependency?(dependency)
243:     @source_index.find_name(dependency.name, dependency.requirement).size > 0
244:   end
shebang(bin_file_name) click to toggle source

Generates a #! line for bin_file_name’s wrapper copying arguments if necessary.

     # File lib/rubygems/installer.rb, line 371
371:   def shebang(bin_file_name)
372:     ruby_name = Gem::ConfigMap[:ruby_install_name] if @env_shebang
373:     path = File.join @gem_dir, @spec.bindir, bin_file_name
374:     first_line = File.open(path, "rb") {|file| file.gets}
375: 
376:     if /\A#!/ =~ first_line then
377:       # Preserve extra words on shebang line, like "-w".  Thanks RPA.
378:       shebang = first_line.sub(/\A\#!.*?ruby\S*(?=(\s+\S+))/, "#!#{Gem.ruby}")
379:       opts = $1
380:       shebang.strip! # Avoid nasty ^M issues.
381:     end
382: 
383:     if not ruby_name then
384:       "#!#{Gem.ruby}#{opts}"
385:     elsif opts then
386:       "#!/bin/sh\n'exec' #{ruby_name.dump} '-x' \"$0\" \"$@\"\n#{shebang}"
387:     else
388:       # Create a plain shebang line.
389:       @env_path ||= ENV_PATHS.find {|env_path| File.executable? env_path }
390:       "#!#{@env_path} #{ruby_name}"
391:     end
392:   end
unpack(directory) click to toggle source

Unpacks the gem into the given directory.

     # File lib/rubygems/installer.rb, line 249
249:   def unpack(directory)
250:     @gem_dir = directory
251:     @format = Gem::Format.from_file_by_path @gem, @security_policy
252:     extract_files
253:   end
windows_stub_script(bindir, bin_file_name) click to toggle source

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

     # File lib/rubygems/installer.rb, line 424
424:   def windows_stub_script(bindir, bin_file_name)
425:     @ECHO OFFIF NOT "%~f0" == "~f0" GOTO :WinNT@"#{File.basename(Gem.ruby).chomp('"')}" "#{File.join(bindir, bin_file_name)}" %1 %2 %3 %4 %5 %6 %7 %8 %9GOTO :EOF:WinNT@"#{File.basename(Gem.ruby).chomp('"')}" "%~dpn0" %*
426:   end
write_spec() click to toggle source

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

     # File lib/rubygems/installer.rb, line 259
259:   def write_spec
260:     rubycode = @spec.to_ruby
261: 
262:     file_name = File.join @gem_home, 'specifications', @spec.spec_name
263: 
264:     file_name.untaint
265: 
266:     File.open(file_name, "w") do |file|
267:       file.puts rubycode
268:     end
269:   end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.