1# frozen_string_literal: true 2#-- 3# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. 4# All rights reserved. 5# See LICENSE.txt for permissions. 6#++ 7 8require 'rubygems/command' 9require 'rubygems/exceptions' 10require 'rubygems/deprecate' 11require 'rubygems/package' 12require 'rubygems/ext' 13require 'rubygems/user_interaction' 14require 'fileutils' 15 16## 17# The installer installs the files contained in the .gem into the Gem.home. 18# 19# Gem::Installer does the work of putting files in all the right places on the 20# filesystem including unpacking the gem into its gem dir, installing the 21# gemspec in the specifications dir, storing the cached gem in the cache dir, 22# and installing either wrappers or symlinks for executables. 23# 24# The installer invokes pre and post install hooks. Hooks can be added either 25# through a rubygems_plugin.rb file in an installed gem or via a 26# rubygems/defaults/#{RUBY_ENGINE}.rb or rubygems/defaults/operating_system.rb 27# file. See Gem.pre_install and Gem.post_install for details. 28 29class Gem::Installer 30 31 extend Gem::Deprecate 32 33 ## 34 # Paths where env(1) might live. Some systems are broken and have it in 35 # /bin 36 37 ENV_PATHS = %w[/usr/bin/env /bin/env].freeze 38 39 ## 40 # Deprecated in favor of Gem::Ext::BuildError 41 42 ExtensionBuildError = Gem::Ext::BuildError # :nodoc: 43 44 include Gem::UserInteraction 45 46 ## 47 # Filename of the gem being installed. 48 49 attr_reader :gem 50 51 ## 52 # The directory a gem's executables will be installed into 53 54 attr_reader :bin_dir 55 56 attr_reader :build_root # :nodoc: 57 58 ## 59 # The gem repository the gem will be installed into 60 61 attr_reader :gem_home 62 63 ## 64 # The options passed when the Gem::Installer was instantiated. 65 66 attr_reader :options 67 68 @path_warning = false 69 70 @install_lock = Mutex.new 71 72 class << self 73 74 ## 75 # True if we've warned about PATH not including Gem.bindir 76 77 attr_accessor :path_warning 78 79 ## 80 # Certain aspects of the install process are not thread-safe. This lock is 81 # used to allow multiple threads to install Gems at the same time. 82 83 attr_reader :install_lock 84 85 ## 86 # Overrides the executable format. 87 # 88 # This is a sprintf format with a "%s" which will be replaced with the 89 # executable name. It is based off the ruby executable name's difference 90 # from "ruby". 91 92 attr_writer :exec_format 93 94 # Defaults to use Ruby's program prefix and suffix. 95 def exec_format 96 @exec_format ||= Gem.default_exec_format 97 end 98 99 end 100 101 ## 102 # Construct an installer object for the gem file located at +path+ 103 104 def self.at(path, options = {}) 105 security_policy = options[:security_policy] 106 package = Gem::Package.new path, security_policy 107 new package, options 108 end 109 110 class FakePackage 111 attr_accessor :spec 112 113 attr_accessor :dir_mode 114 attr_accessor :prog_mode 115 attr_accessor :data_mode 116 117 def initialize(spec) 118 @spec = spec 119 end 120 121 def extract_files(destination_dir, pattern = '*') 122 FileUtils.mkdir_p destination_dir 123 124 spec.files.each do |file| 125 file = File.join destination_dir, file 126 next if File.exist? file 127 FileUtils.mkdir_p File.dirname(file) 128 File.open file, 'w' do |fp| fp.puts "# #{file}" end 129 end 130 end 131 132 def copy_to(path) 133 end 134 end 135 136 ## 137 # Construct an installer object for an ephemeral gem (one where we don't 138 # actually have a .gem file, just a spec) 139 140 def self.for_spec(spec, options = {}) 141 # FIXME: we should have a real Package class for this 142 new FakePackage.new(spec), options 143 end 144 145 ## 146 # Constructs an Installer instance that will install the gem at +package+ which 147 # can either be a path or an instance of Gem::Package. +options+ is a Hash 148 # with the following keys: 149 # 150 # :bin_dir:: Where to put a bin wrapper if needed. 151 # :development:: Whether or not development dependencies should be installed. 152 # :env_shebang:: Use /usr/bin/env in bin wrappers. 153 # :force:: Overrides all version checks and security policy checks, except 154 # for a signed-gems-only policy. 155 # :format_executable:: Format the executable the same as the Ruby executable. 156 # If your Ruby is ruby18, foo_exec will be installed as 157 # foo_exec18. 158 # :ignore_dependencies:: Don't raise if a dependency is missing. 159 # :install_dir:: The directory to install the gem into. 160 # :security_policy:: Use the specified security policy. See Gem::Security 161 # :user_install:: Indicate that the gem should be unpacked into the users 162 # personal gem directory. 163 # :only_install_dir:: Only validate dependencies against what is in the 164 # install_dir 165 # :wrappers:: Install wrappers if true, symlinks if false. 166 # :build_args:: An Array of arguments to pass to the extension builder 167 # process. If not set, then Gem::Command.build_args is used 168 # :post_install_message:: Print gem post install message if true 169 170 def initialize(package, options={}) 171 require 'fileutils' 172 173 @options = options 174 if package.is_a? String 175 security_policy = options[:security_policy] 176 @package = Gem::Package.new package, security_policy 177 if $VERBOSE 178 warn "constructing an Installer object with a string is deprecated. Please use Gem::Installer.at (called from: #{caller.first})" 179 end 180 else 181 @package = package 182 end 183 184 process_options 185 186 @package.dir_mode = options[:dir_mode] 187 @package.prog_mode = options[:prog_mode] 188 @package.data_mode = options[:data_mode] 189 190 @bin_dir = options[:bin_dir] if options[:bin_dir] 191 192 if options[:user_install] and not options[:unpack] 193 @gem_home = Gem.user_dir 194 @bin_dir = Gem.bindir gem_home unless options[:bin_dir] 195 check_that_user_bin_dir_is_in_path 196 end 197 end 198 199 ## 200 # Checks if +filename+ exists in +@bin_dir+. 201 # 202 # If +@force+ is set +filename+ is overwritten. 203 # 204 # If +filename+ exists and is a RubyGems wrapper for different gem the user 205 # is consulted. 206 # 207 # If +filename+ exists and +@bin_dir+ is Gem.default_bindir (/usr/local) the 208 # user is consulted. 209 # 210 # Otherwise +filename+ is overwritten. 211 212 def check_executable_overwrite(filename) # :nodoc: 213 return if @force 214 215 generated_bin = File.join @bin_dir, formatted_program_filename(filename) 216 217 return unless File.exist? generated_bin 218 219 ruby_executable = false 220 existing = nil 221 222 File.open generated_bin, 'rb' do |io| 223 next unless io.gets =~ /^#!/ # shebang 224 io.gets # blankline 225 226 # TODO detect a specially formatted comment instead of trying 227 # to run a regexp against Ruby code. 228 next unless io.gets =~ /This file was generated by RubyGems/ 229 230 ruby_executable = true 231 existing = io.read.slice(%r{ 232 ^\s*( 233 gem \s | 234 load \s Gem\.bin_path\( | 235 load \s Gem\.activate_bin_path\( 236 ) 237 (['"])(.*?)(\2), 238 }x, 3) 239 end 240 241 return if spec.name == existing 242 243 # somebody has written to RubyGems' directory, overwrite, too bad 244 return if Gem.default_bindir != @bin_dir and not ruby_executable 245 246 question = "#{spec.name}'s executable \"#{filename}\" conflicts with ".dup 247 248 if ruby_executable 249 question << (existing || 'an unknown executable') 250 251 return if ask_yes_no "#{question}\nOverwrite the executable?", false 252 253 conflict = "installed executable from #{existing}" 254 else 255 question << generated_bin 256 257 return if ask_yes_no "#{question}\nOverwrite the executable?", false 258 259 conflict = generated_bin 260 end 261 262 raise Gem::InstallError, 263 "\"#{filename}\" from #{spec.name} conflicts with #{conflict}" 264 end 265 266 ## 267 # Lazy accessor for the spec's gem directory. 268 269 def gem_dir 270 @gem_dir ||= File.join(gem_home, "gems", spec.full_name) 271 end 272 273 ## 274 # Lazy accessor for the installer's spec. 275 276 def spec 277 @package.spec 278 rescue Gem::Package::Error => e 279 raise Gem::InstallError, "invalid gem: #{e.message}" 280 end 281 282 ## 283 # Installs the gem and returns a loaded Gem::Specification for the installed 284 # gem. 285 # 286 # The gem will be installed with the following structure: 287 # 288 # @gem_home/ 289 # cache/<gem-version>.gem #=> a cached copy of the installed gem 290 # gems/<gem-version>/... #=> extracted files 291 # specifications/<gem-version>.gemspec #=> the Gem::Specification 292 293 def install 294 pre_install_checks 295 296 FileUtils.rm_f File.join gem_home, 'specifications', spec.spec_name 297 298 run_pre_install_hooks 299 300 # Set loaded_from to ensure extension_dir is correct 301 if @options[:install_as_default] 302 spec.loaded_from = default_spec_file 303 else 304 spec.loaded_from = spec_file 305 end 306 307 # Completely remove any previous gem files 308 FileUtils.rm_rf gem_dir 309 FileUtils.rm_rf spec.extension_dir 310 311 dir_mode = options[:dir_mode] 312 FileUtils.mkdir_p gem_dir, :mode => dir_mode && 0755 313 314 if @options[:install_as_default] 315 extract_bin 316 write_default_spec 317 else 318 extract_files 319 320 build_extensions 321 write_build_info_file 322 run_post_build_hooks 323 324 generate_bin 325 write_spec 326 write_cache_file 327 end 328 329 File.chmod(dir_mode, gem_dir) if dir_mode 330 331 say spec.post_install_message if options[:post_install_message] && !spec.post_install_message.nil? 332 333 Gem::Installer.install_lock.synchronize { Gem::Specification.reset } 334 335 run_post_install_hooks 336 337 spec 338 339 # TODO This rescue is in the wrong place. What is raising this exception? 340 # move this rescue to around the code that actually might raise it. 341 rescue Zlib::GzipFile::Error 342 raise Gem::InstallError, "gzip error installing #{gem}" 343 end 344 345 def run_pre_install_hooks # :nodoc: 346 Gem.pre_install_hooks.each do |hook| 347 if hook.call(self) == false 348 location = " at #{$1}" if hook.inspect =~ /@(.*:\d+)/ 349 350 message = "pre-install hook#{location} failed for #{spec.full_name}" 351 raise Gem::InstallError, message 352 end 353 end 354 end 355 356 def run_post_build_hooks # :nodoc: 357 Gem.post_build_hooks.each do |hook| 358 if hook.call(self) == false 359 FileUtils.rm_rf gem_dir 360 361 location = " at #{$1}" if hook.inspect =~ /@(.*:\d+)/ 362 363 message = "post-build hook#{location} failed for #{spec.full_name}" 364 raise Gem::InstallError, message 365 end 366 end 367 end 368 369 def run_post_install_hooks # :nodoc: 370 Gem.post_install_hooks.each do |hook| 371 hook.call self 372 end 373 end 374 375 ## 376 # 377 # Return an Array of Specifications contained within the gem_home 378 # we'll be installing into. 379 380 def installed_specs 381 @specs ||= begin 382 specs = [] 383 384 Gem::Util.glob_files_in_dir("*.gemspec", File.join(gem_home, "specifications")).each do |path| 385 spec = Gem::Specification.load path.untaint 386 specs << spec if spec 387 end 388 389 specs 390 end 391 end 392 393 ## 394 # Ensure that the dependency is satisfied by the current installation of 395 # gem. If it is not an exception is raised. 396 # 397 # spec :: Gem::Specification 398 # dependency :: Gem::Dependency 399 400 def ensure_dependency(spec, dependency) 401 unless installation_satisfies_dependency? dependency 402 raise Gem::InstallError, "#{spec.name} requires #{dependency}" 403 end 404 true 405 end 406 407 ## 408 # True if the gems in the system satisfy +dependency+. 409 410 def installation_satisfies_dependency?(dependency) 411 return true if @options[:development] and dependency.type == :development 412 return true if installed_specs.detect { |s| dependency.matches_spec? s } 413 return false if @only_install_dir 414 not dependency.matching_specs.empty? 415 end 416 417 ## 418 # Unpacks the gem into the given directory. 419 420 def unpack(directory) 421 @gem_dir = directory 422 extract_files 423 end 424 425 ## 426 # The location of the spec file that is installed. 427 # 428 429 def spec_file 430 File.join gem_home, "specifications", "#{spec.full_name}.gemspec" 431 end 432 433 ## 434 # The location of the default spec file for default gems. 435 # 436 437 def default_spec_file 438 File.join Gem::Specification.default_specifications_dir, "#{spec.full_name}.gemspec" 439 end 440 441 ## 442 # Writes the .gemspec specification (in Ruby) to the gem home's 443 # specifications directory. 444 445 def write_spec 446 File.open spec_file, 'w' do |file| 447 spec.installed_by_version = Gem.rubygems_version 448 449 file.puts spec.to_ruby_for_cache 450 451 file.fsync rescue nil # for filesystems without fsync(2) 452 end 453 end 454 455 ## 456 # Writes the full .gemspec specification (in Ruby) to the gem home's 457 # specifications/default directory. 458 459 def write_default_spec 460 File.open(default_spec_file, "w") do |file| 461 file.puts spec.to_ruby 462 end 463 end 464 465 ## 466 # Creates windows .bat files for easy running of commands 467 468 def generate_windows_script(filename, bindir) 469 if Gem.win_platform? 470 script_name = filename + ".bat" 471 script_path = File.join bindir, File.basename(script_name) 472 File.open script_path, 'w' do |file| 473 file.puts windows_stub_script(bindir, filename) 474 end 475 476 verbose script_path 477 end 478 end 479 480 def generate_bin # :nodoc: 481 return if spec.executables.nil? or spec.executables.empty? 482 483 begin 484 Dir.mkdir @bin_dir, *[options[:dir_mode] && 0755].compact 485 rescue SystemCallError 486 raise unless File.directory? @bin_dir 487 end 488 489 raise Gem::FilePermissionError.new(@bin_dir) unless File.writable? @bin_dir 490 491 spec.executables.each do |filename| 492 filename.untaint 493 bin_path = File.join gem_dir, spec.bindir, filename 494 495 unless File.exist? bin_path 496 # TODO change this to a more useful warning 497 warn "`#{bin_path}` does not exist, maybe `gem pristine #{spec.name}` will fix it?" 498 next 499 end 500 501 mode = File.stat(bin_path).mode 502 dir_mode = options[:prog_mode] || (mode | 0111) 503 FileUtils.chmod dir_mode, bin_path unless dir_mode == mode 504 505 check_executable_overwrite filename 506 507 if @wrappers 508 generate_bin_script filename, @bin_dir 509 else 510 generate_bin_symlink filename, @bin_dir 511 end 512 513 end 514 end 515 516 ## 517 # Creates the scripts to run the applications in the gem. 518 #-- 519 # The Windows script is generated in addition to the regular one due to a 520 # bug or misfeature in the Windows shell's pipe. See 521 # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/193379 522 523 def generate_bin_script(filename, bindir) 524 bin_script_path = File.join bindir, formatted_program_filename(filename) 525 526 FileUtils.rm_f bin_script_path # prior install may have been --no-wrappers 527 528 File.open bin_script_path, 'wb', 0755 do |file| 529 file.print app_script_text(filename) 530 file.chmod(options[:prog_mode] || 0755) 531 end 532 533 verbose bin_script_path 534 535 generate_windows_script filename, bindir 536 end 537 538 ## 539 # Creates the symlinks to run the applications in the gem. Moves 540 # the symlink if the gem being installed has a newer version. 541 542 def generate_bin_symlink(filename, bindir) 543 src = File.join gem_dir, spec.bindir, filename 544 dst = File.join bindir, formatted_program_filename(filename) 545 546 if File.exist? dst 547 if File.symlink? dst 548 link = File.readlink(dst).split File::SEPARATOR 549 cur_version = Gem::Version.create(link[-3].sub(/^.*-/, '')) 550 return if spec.version < cur_version 551 end 552 File.unlink dst 553 end 554 555 FileUtils.symlink src, dst, :verbose => Gem.configuration.really_verbose 556 rescue NotImplementedError, SystemCallError 557 alert_warning "Unable to use symlinks, installing wrapper" 558 generate_bin_script filename, bindir 559 end 560 561 ## 562 # Generates a #! line for +bin_file_name+'s wrapper copying arguments if 563 # necessary. 564 # 565 # If the :custom_shebang config is set, then it is used as a template 566 # for how to create the shebang used for to run a gem's executables. 567 # 568 # The template supports 4 expansions: 569 # 570 # $env the path to the unix env utility 571 # $ruby the path to the currently running ruby interpreter 572 # $exec the path to the gem's executable 573 # $name the name of the gem the executable is for 574 # 575 576 def shebang(bin_file_name) 577 ruby_name = RbConfig::CONFIG['ruby_install_name'] if @env_shebang 578 path = File.join gem_dir, spec.bindir, bin_file_name 579 first_line = File.open(path, "rb") {|file| file.gets} 580 581 if /\A#!/ =~ first_line 582 # Preserve extra words on shebang line, like "-w". Thanks RPA. 583 shebang = first_line.sub(/\A\#!.*?ruby\S*((\s+\S+)+)/, "#!#{Gem.ruby}") 584 opts = $1 585 shebang.strip! # Avoid nasty ^M issues. 586 end 587 588 if which = Gem.configuration[:custom_shebang] 589 # replace bin_file_name with "ruby" to avoid endless loops 590 which = which.gsub(/ #{bin_file_name}$/," #{RbConfig::CONFIG['ruby_install_name']}") 591 592 which = which.gsub(/\$(\w+)/) do 593 case $1 594 when "env" 595 @env_path ||= ENV_PATHS.find {|env_path| File.executable? env_path } 596 when "ruby" 597 "#{Gem.ruby}#{opts}" 598 when "exec" 599 bin_file_name 600 when "name" 601 spec.name 602 end 603 end 604 605 "#!#{which}" 606 elsif not ruby_name 607 "#!#{Gem.ruby}#{opts}" 608 elsif opts 609 "#!/bin/sh\n'exec' #{ruby_name.dump} '-x' \"$0\" \"$@\"\n#{shebang}" 610 else 611 # Create a plain shebang line. 612 @env_path ||= ENV_PATHS.find {|env_path| File.executable? env_path } 613 "#!#{@env_path} #{ruby_name}" 614 end 615 end 616 617 ## 618 # Ensures the Gem::Specification written out for this gem is loadable upon 619 # installation. 620 621 def ensure_loadable_spec 622 ruby = spec.to_ruby_for_cache 623 ruby.untaint 624 625 begin 626 eval ruby 627 rescue StandardError, SyntaxError => e 628 raise Gem::InstallError, 629 "The specification for #{spec.full_name} is corrupt (#{e.class})" 630 end 631 end 632 633 def ensure_required_ruby_version_met # :nodoc: 634 if rrv = spec.required_ruby_version 635 ruby_version = Gem.ruby_version 636 unless rrv.satisfied_by? ruby_version 637 raise Gem::RuntimeRequirementNotMetError, 638 "#{spec.name} requires Ruby version #{rrv}. The current ruby version is #{ruby_version}." 639 end 640 end 641 end 642 643 def ensure_required_rubygems_version_met # :nodoc: 644 if rrgv = spec.required_rubygems_version 645 unless rrgv.satisfied_by? Gem.rubygems_version 646 rg_version = Gem::VERSION 647 raise Gem::RuntimeRequirementNotMetError, 648 "#{spec.name} requires RubyGems version #{rrgv}. The current RubyGems version is #{rg_version}. " + 649 "Try 'gem update --system' to update RubyGems itself." 650 end 651 end 652 end 653 654 def ensure_dependencies_met # :nodoc: 655 deps = spec.runtime_dependencies 656 deps |= spec.development_dependencies if @development 657 658 deps.each do |dep_gem| 659 ensure_dependency spec, dep_gem 660 end 661 end 662 663 def process_options # :nodoc: 664 @options = { 665 :bin_dir => nil, 666 :env_shebang => false, 667 :force => false, 668 :only_install_dir => false, 669 :post_install_message => true 670 }.merge options 671 672 @env_shebang = options[:env_shebang] 673 @force = options[:force] 674 @install_dir = options[:install_dir] 675 @gem_home = options[:install_dir] || Gem.dir 676 @ignore_dependencies = options[:ignore_dependencies] 677 @format_executable = options[:format_executable] 678 @wrappers = options[:wrappers] 679 @only_install_dir = options[:only_install_dir] 680 681 # If the user has asked for the gem to be installed in a directory that is 682 # the system gem directory, then use the system bin directory, else create 683 # (or use) a new bin dir under the gem_home. 684 @bin_dir = options[:bin_dir] || Gem.bindir(gem_home) 685 @development = options[:development] 686 @build_root = options[:build_root] 687 688 @build_args = options[:build_args] || Gem::Command.build_args 689 690 unless @build_root.nil? 691 require 'pathname' 692 @build_root = Pathname.new(@build_root).expand_path 693 @bin_dir = File.join(@build_root, options[:bin_dir] || Gem.bindir(@gem_home)) 694 @gem_home = File.join(@build_root, @gem_home) 695 alert_warning "You build with buildroot.\n Build root: #{@build_root}\n Bin dir: #{@bin_dir}\n Gem home: #{@gem_home}" 696 end 697 end 698 699 def check_that_user_bin_dir_is_in_path # :nodoc: 700 user_bin_dir = @bin_dir || Gem.bindir(gem_home) 701 user_bin_dir = user_bin_dir.gsub(File::SEPARATOR, File::ALT_SEPARATOR) if 702 File::ALT_SEPARATOR 703 704 path = ENV['PATH'] 705 if Gem.win_platform? 706 path = path.downcase 707 user_bin_dir = user_bin_dir.downcase 708 end 709 710 path = path.split(File::PATH_SEPARATOR) 711 712 unless path.include? user_bin_dir 713 unless !Gem.win_platform? && (path.include? user_bin_dir.sub(ENV['HOME'], '~')) 714 unless self.class.path_warning 715 alert_warning "You don't have #{user_bin_dir} in your PATH,\n\t gem executables will not run." 716 self.class.path_warning = true 717 end 718 end 719 end 720 end 721 722 def verify_gem_home(unpack = false) # :nodoc: 723 FileUtils.mkdir_p gem_home, :mode => options[:dir_mode] && 0755 724 raise Gem::FilePermissionError, gem_home unless 725 unpack or File.writable?(gem_home) 726 end 727 728 def verify_spec 729 unless spec.name =~ Gem::Specification::VALID_NAME_PATTERN 730 raise Gem::InstallError, "#{spec} has an invalid name" 731 end 732 733 if spec.raw_require_paths.any?{|path| path =~ /\R/ } 734 raise Gem::InstallError, "#{spec} has an invalid require_paths" 735 end 736 737 if spec.extensions.any?{|ext| ext =~ /\R/ } 738 raise Gem::InstallError, "#{spec} has an invalid extensions" 739 end 740 741 unless spec.specification_version.to_s =~ /\A\d+\z/ 742 raise Gem::InstallError, "#{spec} has an invalid specification_version" 743 end 744 745 if spec.dependencies.any? {|dep| dep.type =~ /\R/ || dep.name =~ /\R/ } 746 raise Gem::InstallError, "#{spec} has an invalid dependencies" 747 end 748 end 749 750 ## 751 # Return the text for an application file. 752 753 def app_script_text(bin_file_name) 754 # note that the `load` lines cannot be indented, as old RG versions match 755 # against the beginning of the line 756 return <<-TEXT 757#{shebang bin_file_name} 758# 759# This file was generated by RubyGems. 760# 761# The application '#{spec.name}' is installed as part of a gem, and 762# this file is here to facilitate running it. 763# 764 765require 'rubygems' 766 767version = "#{Gem::Requirement.default}.a" 768 769str = ARGV.first 770if str 771 str = str.b[/\\A_(.*)_\\z/, 1] 772 if str and Gem::Version.correct?(str) 773 version = str 774 ARGV.shift 775 end 776end 777 778if Gem.respond_to?(:activate_bin_path) 779load Gem.activate_bin_path('#{spec.name}', '#{bin_file_name}', version) 780else 781gem #{spec.name.dump}, version 782load Gem.bin_path(#{spec.name.dump}, #{bin_file_name.dump}, version) 783end 784TEXT 785 end 786 787 ## 788 # return the stub script text used to launch the true Ruby script 789 790 def windows_stub_script(bindir, bin_file_name) 791 rb_config = RbConfig::CONFIG 792 rb_topdir = RbConfig::TOPDIR || File.dirname(rb_config["bindir"]) 793 794 # get ruby executable file name from RbConfig 795 ruby_exe = "#{rb_config['RUBY_INSTALL_NAME']}#{rb_config['EXEEXT']}" 796 ruby_exe = "ruby.exe" if ruby_exe.empty? 797 798 if File.exist?(File.join bindir, ruby_exe) 799 # stub & ruby.exe withing same folder. Portable 800 <<-TEXT 801@ECHO OFF 802@"%~dp0ruby.exe" "%~dpn0" %* 803 TEXT 804 elsif bindir.downcase.start_with? rb_topdir.downcase 805 # stub within ruby folder, but not standard bin. Portable 806 require 'pathname' 807 from = Pathname.new bindir 808 to = Pathname.new "#{rb_topdir}/bin" 809 rel = to.relative_path_from from 810 <<-TEXT 811@ECHO OFF 812@"%~dp0#{rel}/ruby.exe" "%~dpn0" %* 813 TEXT 814 else 815 # outside ruby folder, maybe -user-install or bundler. Portable, but ruby 816 # is dependent on PATH 817 <<-TEXT 818@ECHO OFF 819@ruby.exe "%~dpn0" %* 820 TEXT 821 end 822 end 823 ## 824 # Builds extensions. Valid types of extensions are extconf.rb files, 825 # configure scripts and rakefiles or mkrf_conf files. 826 827 def build_extensions 828 builder = Gem::Ext::Builder.new spec, @build_args 829 830 builder.build_extensions 831 end 832 833 ## 834 # Logs the build +output+ in +build_dir+, then raises Gem::Ext::BuildError. 835 # 836 # TODO: Delete this for RubyGems 4. It remains for API compatibility 837 838 def extension_build_error(build_dir, output, backtrace = nil) # :nodoc: 839 builder = Gem::Ext::Builder.new spec, @build_args 840 841 builder.build_error build_dir, output, backtrace 842 end 843 deprecate :extension_build_error, :none, 2018, 12 844 845 ## 846 # Reads the file index and extracts each file into the gem directory. 847 # 848 # Ensures that files can't be installed outside the gem directory. 849 850 def extract_files 851 @package.extract_files gem_dir 852 end 853 854 ## 855 # Extracts only the bin/ files from the gem into the gem directory. 856 # This is used by default gems to allow a gem-aware stub to function 857 # without the full gem installed. 858 859 def extract_bin 860 @package.extract_files gem_dir, "bin/*" 861 end 862 863 ## 864 # Prefix and suffix the program filename the same as ruby. 865 866 def formatted_program_filename(filename) 867 if @format_executable 868 self.class.exec_format % File.basename(filename) 869 else 870 filename 871 end 872 end 873 874 ## 875 # 876 # Return the target directory where the gem is to be installed. This 877 # directory is not guaranteed to be populated. 878 # 879 880 def dir 881 gem_dir.to_s 882 end 883 884 ## 885 # Performs various checks before installing the gem such as the install 886 # repository is writable and its directories exist, required Ruby and 887 # rubygems versions are met and that dependencies are installed. 888 # 889 # Version and dependency checks are skipped if this install is forced. 890 # 891 # The dependent check will be skipped if the install is ignoring dependencies. 892 893 def pre_install_checks 894 verify_gem_home options[:unpack] 895 896 # The name and require_paths must be verified first, since it could contain 897 # ruby code that would be eval'ed in #ensure_loadable_spec 898 verify_spec 899 900 ensure_loadable_spec 901 902 if options[:install_as_default] 903 Gem.ensure_default_gem_subdirectories gem_home 904 else 905 Gem.ensure_gem_subdirectories gem_home 906 end 907 908 return true if @force 909 910 ensure_required_ruby_version_met 911 ensure_required_rubygems_version_met 912 ensure_dependencies_met unless @ignore_dependencies 913 914 true 915 end 916 917 ## 918 # Writes the file containing the arguments for building this gem's 919 # extensions. 920 921 def write_build_info_file 922 return if @build_args.empty? 923 924 build_info_dir = File.join gem_home, 'build_info' 925 926 dir_mode = options[:dir_mode] 927 FileUtils.mkdir_p build_info_dir, :mode => dir_mode && 0755 928 929 build_info_file = File.join build_info_dir, "#{spec.full_name}.info" 930 931 File.open build_info_file, 'w' do |io| 932 @build_args.each do |arg| 933 io.puts arg 934 end 935 end 936 937 File.chmod(dir_mode, build_info_dir) if dir_mode 938 end 939 940 ## 941 # Writes the .gem file to the cache directory 942 943 def write_cache_file 944 cache_file = File.join gem_home, 'cache', spec.file_name 945 @package.copy_to cache_file 946 end 947 948end 949