1# frozen_string_literal: true 2# -*- ruby -*- 3#-- 4# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. 5# All rights reserved. 6# See LICENSE.txt for permissions. 7#++ 8 9require 'rbconfig' 10 11module Gem 12 VERSION = "3.0.3.1".freeze 13end 14 15# Must be first since it unloads the prelude from 1.9.2 16require 'rubygems/compatibility' 17 18require 'rubygems/defaults' 19require 'rubygems/deprecate' 20require 'rubygems/errors' 21 22## 23# RubyGems is the Ruby standard for publishing and managing third party 24# libraries. 25# 26# For user documentation, see: 27# 28# * <tt>gem help</tt> and <tt>gem help [command]</tt> 29# * {RubyGems User Guide}[http://guides.rubygems.org/] 30# * {Frequently Asked Questions}[http://guides.rubygems.org/faqs] 31# 32# For gem developer documentation see: 33# 34# * {Creating Gems}[http://guides.rubygems.org/make-your-own-gem] 35# * Gem::Specification 36# * Gem::Version for version dependency notes 37# 38# Further RubyGems documentation can be found at: 39# 40# * {RubyGems Guides}[http://guides.rubygems.org] 41# * {RubyGems API}[http://www.rubydoc.info/github/rubygems/rubygems] (also available from 42# <tt>gem server</tt>) 43# 44# == RubyGems Plugins 45# 46# As of RubyGems 1.3.2, RubyGems will load plugins installed in gems or 47# $LOAD_PATH. Plugins must be named 'rubygems_plugin' (.rb, .so, etc) and 48# placed at the root of your gem's #require_path. Plugins are discovered via 49# Gem::find_files and then loaded. 50# 51# For an example plugin, see the {Graph gem}[https://github.com/seattlerb/graph] 52# which adds a `gem graph` command. 53# 54# == RubyGems Defaults, Packaging 55# 56# RubyGems defaults are stored in lib/rubygems/defaults.rb. If you're packaging 57# RubyGems or implementing Ruby you can change RubyGems' defaults. 58# 59# For RubyGems packagers, provide lib/rubygems/defaults/operating_system.rb 60# and override any defaults from lib/rubygems/defaults.rb. 61# 62# For Ruby implementers, provide lib/rubygems/defaults/#{RUBY_ENGINE}.rb and 63# override any defaults from lib/rubygems/defaults.rb. 64# 65# If you need RubyGems to perform extra work on install or uninstall, your 66# defaults override file can set pre/post install and uninstall hooks. 67# See Gem::pre_install, Gem::pre_uninstall, Gem::post_install, 68# Gem::post_uninstall. 69# 70# == Bugs 71# 72# You can submit bugs to the 73# {RubyGems bug tracker}[https://github.com/rubygems/rubygems/issues] 74# on GitHub 75# 76# == Credits 77# 78# RubyGems is currently maintained by Eric Hodel. 79# 80# RubyGems was originally developed at RubyConf 2003 by: 81# 82# * Rich Kilmer -- rich(at)infoether.com 83# * Chad Fowler -- chad(at)chadfowler.com 84# * David Black -- dblack(at)wobblini.net 85# * Paul Brannan -- paul(at)atdesk.com 86# * Jim Weirich -- jim(at)weirichhouse.org 87# 88# Contributors: 89# 90# * Gavin Sinclair -- gsinclair(at)soyabean.com.au 91# * George Marrows -- george.marrows(at)ntlworld.com 92# * Dick Davies -- rasputnik(at)hellooperator.net 93# * Mauricio Fernandez -- batsman.geo(at)yahoo.com 94# * Simon Strandgaard -- neoneye(at)adslhome.dk 95# * Dave Glasser -- glasser(at)mit.edu 96# * Paul Duncan -- pabs(at)pablotron.org 97# * Ville Aine -- vaine(at)cs.helsinki.fi 98# * Eric Hodel -- drbrain(at)segment7.net 99# * Daniel Berger -- djberg96(at)gmail.com 100# * Phil Hagelberg -- technomancy(at)gmail.com 101# * Ryan Davis -- ryand-ruby(at)zenspider.com 102# * Evan Phoenix -- evan(at)fallingsnow.net 103# * Steve Klabnik -- steve(at)steveklabnik.com 104# 105# (If your name is missing, PLEASE let us know!) 106# 107# == License 108# 109# See {LICENSE.txt}[rdoc-ref:lib/rubygems/LICENSE.txt] for permissions. 110# 111# Thanks! 112# 113# -The RubyGems Team 114 115 116module Gem 117 RUBYGEMS_DIR = File.dirname File.expand_path(__FILE__) 118 119 ## 120 # An Array of Regexps that match windows Ruby platforms. 121 122 WIN_PATTERNS = [ 123 /bccwin/i, 124 /cygwin/i, 125 /djgpp/i, 126 /mingw/i, 127 /mswin/i, 128 /wince/i, 129 ].freeze 130 131 GEM_DEP_FILES = %w[ 132 gem.deps.rb 133 gems.rb 134 Gemfile 135 Isolate 136 ].freeze 137 138 ## 139 # Subdirectories in a gem repository 140 141 REPOSITORY_SUBDIRECTORIES = %w[ 142 build_info 143 cache 144 doc 145 extensions 146 gems 147 specifications 148 ].freeze 149 150 ## 151 # Subdirectories in a gem repository for default gems 152 153 REPOSITORY_DEFAULT_GEM_SUBDIRECTORIES = %w[ 154 gems 155 specifications/default 156 ].freeze 157 158 ## 159 # Exception classes used in a Gem.read_binary +rescue+ statement. Not all of 160 # these are defined in Ruby 1.8.7, hence the need for this convoluted setup. 161 162 READ_BINARY_ERRORS = begin 163 read_binary_errors = [Errno::EACCES, Errno::EROFS, Errno::ENOSYS] 164 read_binary_errors << Errno::ENOTSUP if Errno.const_defined?(:ENOTSUP) 165 read_binary_errors 166 end.freeze 167 168 ## 169 # Exception classes used in Gem.write_binary +rescue+ statement. Not all of 170 # these are defined in Ruby 1.8.7. 171 172 WRITE_BINARY_ERRORS = begin 173 write_binary_errors = [Errno::ENOSYS] 174 write_binary_errors << Errno::ENOTSUP if Errno.const_defined?(:ENOTSUP) 175 write_binary_errors 176 end.freeze 177 178 USE_BUNDLER_FOR_GEMDEPS = !ENV['DONT_USE_BUNDLER_FOR_GEMDEPS'] # :nodoc: 179 180 @@win_platform = nil 181 182 @configuration = nil 183 @gemdeps = nil 184 @loaded_specs = {} 185 LOADED_SPECS_MUTEX = Mutex.new 186 @path_to_default_spec_map = {} 187 @platforms = [] 188 @ruby = nil 189 @ruby_api_version = nil 190 @sources = nil 191 192 @post_build_hooks ||= [] 193 @post_install_hooks ||= [] 194 @post_uninstall_hooks ||= [] 195 @pre_uninstall_hooks ||= [] 196 @pre_install_hooks ||= [] 197 @pre_reset_hooks ||= [] 198 @post_reset_hooks ||= [] 199 200 ## 201 # Try to activate a gem containing +path+. Returns true if 202 # activation succeeded or wasn't needed because it was already 203 # activated. Returns false if it can't find the path in a gem. 204 205 def self.try_activate(path) 206 # finds the _latest_ version... regardless of loaded specs and their deps 207 # if another gem had a requirement that would mean we shouldn't 208 # activate the latest version, then either it would already be activated 209 # or if it was ambiguous (and thus unresolved) the code in our custom 210 # require will try to activate the more specific version. 211 212 spec = Gem::Specification.find_by_path path 213 return false unless spec 214 return true if spec.activated? 215 216 begin 217 spec.activate 218 rescue Gem::LoadError => e # this could fail due to gem dep collisions, go lax 219 spec_by_name = Gem::Specification.find_by_name(spec.name) 220 if spec_by_name.nil? 221 raise e 222 else 223 spec_by_name.activate 224 end 225 end 226 227 return true 228 end 229 230 def self.needs 231 rs = Gem::RequestSet.new 232 233 yield rs 234 235 finish_resolve rs 236 end 237 238 def self.finish_resolve(request_set=Gem::RequestSet.new) 239 request_set.import Gem::Specification.unresolved_deps.values 240 request_set.import Gem.loaded_specs.values.map {|s| Gem::Dependency.new(s.name, s.version) } 241 242 request_set.resolve_current.each do |s| 243 s.full_spec.activate 244 end 245 end 246 247 ## 248 # Find the full path to the executable for gem +name+. If the +exec_name+ 249 # is not given, an exception will be raised, otherwise the 250 # specified executable's path is returned. +requirements+ allows 251 # you to specify specific gem versions. 252 253 def self.bin_path(name, exec_name = nil, *requirements) 254 # TODO: fails test_self_bin_path_bin_file_gone_in_latest 255 # Gem::Specification.find_by_name(name, *requirements).bin_file exec_name 256 257 raise ArgumentError, "you must supply exec_name" unless exec_name 258 259 requirements = Gem::Requirement.default if 260 requirements.empty? 261 262 find_spec_for_exe(name, exec_name, requirements).bin_file exec_name 263 end 264 265 def self.find_spec_for_exe(name, exec_name, requirements) 266 dep = Gem::Dependency.new name, requirements 267 268 loaded = Gem.loaded_specs[name] 269 270 return loaded if loaded && dep.matches_spec?(loaded) 271 272 specs = dep.matching_specs(true) 273 274 specs = specs.find_all { |spec| 275 spec.executables.include? exec_name 276 } if exec_name 277 278 unless spec = specs.first 279 msg = "can't find gem #{dep} with executable #{exec_name}" 280 if name == "bundler" && bundler_message = Gem::BundlerVersionFinder.missing_version_message 281 msg = bundler_message 282 end 283 raise Gem::GemNotFoundException, msg 284 end 285 286 spec 287 end 288 private_class_method :find_spec_for_exe 289 290 ## 291 # Find the full path to the executable for gem +name+. If the +exec_name+ 292 # is not given, an exception will be raised, otherwise the 293 # specified executable's path is returned. +requirements+ allows 294 # you to specify specific gem versions. 295 # 296 # A side effect of this method is that it will activate the gem that 297 # contains the executable. 298 # 299 # This method should *only* be used in bin stub files. 300 301 def self.activate_bin_path(name, exec_name, requirement) # :nodoc: 302 spec = find_spec_for_exe name, exec_name, [requirement] 303 Gem::LOADED_SPECS_MUTEX.synchronize do 304 spec.activate 305 finish_resolve 306 end 307 spec.bin_file exec_name 308 end 309 310 ## 311 # The mode needed to read a file as straight binary. 312 313 def self.binary_mode 314 'rb' 315 end 316 317 ## 318 # The path where gem executables are to be installed. 319 320 def self.bindir(install_dir=Gem.dir) 321 return File.join install_dir, 'bin' unless 322 install_dir.to_s == Gem.default_dir.to_s 323 Gem.default_bindir 324 end 325 326 ## 327 # Reset the +dir+ and +path+ values. The next time +dir+ or +path+ 328 # is requested, the values will be calculated from scratch. This is 329 # mainly used by the unit tests to provide test isolation. 330 331 def self.clear_paths 332 @paths = nil 333 @user_home = nil 334 Gem::Specification.reset 335 Gem::Security.reset if defined?(Gem::Security) 336 end 337 338 ## 339 # The path to standard location of the user's .gemrc file. 340 341 def self.config_file 342 @config_file ||= File.join Gem.user_home, '.gemrc' 343 end 344 345 ## 346 # The standard configuration object for gems. 347 348 def self.configuration 349 @configuration ||= Gem::ConfigFile.new [] 350 end 351 352 ## 353 # Use the given configuration object (which implements the ConfigFile 354 # protocol) as the standard configuration object. 355 356 def self.configuration=(config) 357 @configuration = config 358 end 359 360 ## 361 # The path to the data directory specified by the gem name. If the 362 # package is not available as a gem, return nil. 363 364 def self.datadir(gem_name) 365 spec = @loaded_specs[gem_name] 366 return nil if spec.nil? 367 spec.datadir 368 end 369 370 ## 371 # A Zlib::Deflate.deflate wrapper 372 373 def self.deflate(data) 374 require 'zlib' 375 Zlib::Deflate.deflate data 376 end 377 378 # Retrieve the PathSupport object that RubyGems uses to 379 # lookup files. 380 381 def self.paths 382 @paths ||= Gem::PathSupport.new(ENV) 383 end 384 385 # Initialize the filesystem paths to use from +env+. 386 # +env+ is a hash-like object (typically ENV) that 387 # is queried for 'GEM_HOME', 'GEM_PATH', and 'GEM_SPEC_CACHE' 388 # Keys for the +env+ hash should be Strings, and values of the hash should 389 # be Strings or +nil+. 390 391 def self.paths=(env) 392 clear_paths 393 target = {} 394 env.each_pair do |k,v| 395 case k 396 when 'GEM_HOME', 'GEM_PATH', 'GEM_SPEC_CACHE' 397 case v 398 when nil, String 399 target[k] = v 400 when Array 401 unless Gem::Deprecate.skip 402 warn <<-eowarn 403Array values in the parameter to `Gem.paths=` are deprecated. 404Please use a String or nil. 405An Array (#{env.inspect}) was passed in from #{caller[3]} 406 eowarn 407 end 408 target[k] = v.join File::PATH_SEPARATOR 409 end 410 else 411 target[k] = v 412 end 413 end 414 @paths = Gem::PathSupport.new ENV.to_hash.merge(target) 415 Gem::Specification.dirs = @paths.path 416 end 417 418 ## 419 # The path where gems are to be installed. 420 #-- 421 # FIXME deprecate these once everything else has been done -ebh 422 423 def self.dir 424 paths.home 425 end 426 427 def self.path 428 paths.path 429 end 430 431 def self.spec_cache_dir 432 paths.spec_cache_dir 433 end 434 435 ## 436 # Quietly ensure the Gem directory +dir+ contains all the proper 437 # subdirectories. If we can't create a directory due to a permission 438 # problem, then we will silently continue. 439 # 440 # If +mode+ is given, missing directories are created with this mode. 441 # 442 # World-writable directories will never be created. 443 444 def self.ensure_gem_subdirectories(dir = Gem.dir, mode = nil) 445 ensure_subdirectories(dir, mode, REPOSITORY_SUBDIRECTORIES) 446 end 447 448 ## 449 # Quietly ensure the Gem directory +dir+ contains all the proper 450 # subdirectories for handling default gems. If we can't create a 451 # directory due to a permission problem, then we will silently continue. 452 # 453 # If +mode+ is given, missing directories are created with this mode. 454 # 455 # World-writable directories will never be created. 456 457 def self.ensure_default_gem_subdirectories(dir = Gem.dir, mode = nil) 458 ensure_subdirectories(dir, mode, REPOSITORY_DEFAULT_GEM_SUBDIRECTORIES) 459 end 460 461 def self.ensure_subdirectories(dir, mode, subdirs) # :nodoc: 462 old_umask = File.umask 463 File.umask old_umask | 002 464 465 require 'fileutils' 466 467 options = {} 468 469 options[:mode] = mode if mode 470 471 subdirs.each do |name| 472 subdir = File.join dir, name 473 next if File.exist? subdir 474 FileUtils.mkdir_p subdir, options rescue nil 475 end 476 ensure 477 File.umask old_umask 478 end 479 480 ## 481 # The extension API version of ruby. This includes the static vs non-static 482 # distinction as extensions cannot be shared between the two. 483 484 def self.extension_api_version # :nodoc: 485 if 'no' == RbConfig::CONFIG['ENABLE_SHARED'] 486 "#{ruby_api_version}-static" 487 else 488 ruby_api_version 489 end 490 end 491 492 ## 493 # Returns a list of paths matching +glob+ that can be used by a gem to pick 494 # up features from other gems. For example: 495 # 496 # Gem.find_files('rdoc/discover').each do |path| load path end 497 # 498 # if +check_load_path+ is true (the default), then find_files also searches 499 # $LOAD_PATH for files as well as gems. 500 # 501 # Note that find_files will return all files even if they are from different 502 # versions of the same gem. See also find_latest_files 503 504 def self.find_files(glob, check_load_path=true) 505 files = [] 506 507 files = find_files_from_load_path glob if check_load_path 508 509 gem_specifications = @gemdeps ? Gem.loaded_specs.values : Gem::Specification.stubs 510 511 files.concat gem_specifications.map { |spec| 512 spec.matches_for_glob("#{glob}#{Gem.suffix_pattern}") 513 }.flatten 514 515 # $LOAD_PATH might contain duplicate entries or reference 516 # the spec dirs directly, so we prune. 517 files.uniq! if check_load_path 518 519 return files 520 end 521 522 def self.find_files_from_load_path(glob) # :nodoc: 523 glob_with_suffixes = "#{glob}#{Gem.suffix_pattern}" 524 $LOAD_PATH.map { |load_path| 525 Gem::Util.glob_files_in_dir(glob_with_suffixes, load_path) 526 }.flatten.select { |file| File.file? file.untaint } 527 end 528 529 ## 530 # Returns a list of paths matching +glob+ from the latest gems that can be 531 # used by a gem to pick up features from other gems. For example: 532 # 533 # Gem.find_latest_files('rdoc/discover').each do |path| load path end 534 # 535 # if +check_load_path+ is true (the default), then find_latest_files also 536 # searches $LOAD_PATH for files as well as gems. 537 # 538 # Unlike find_files, find_latest_files will return only files from the 539 # latest version of a gem. 540 541 def self.find_latest_files(glob, check_load_path=true) 542 files = [] 543 544 files = find_files_from_load_path glob if check_load_path 545 546 files.concat Gem::Specification.latest_specs(true).map { |spec| 547 spec.matches_for_glob("#{glob}#{Gem.suffix_pattern}") 548 }.flatten 549 550 # $LOAD_PATH might contain duplicate entries or reference 551 # the spec dirs directly, so we prune. 552 files.uniq! if check_load_path 553 554 return files 555 end 556 557 ## 558 # Finds the user's home directory. 559 #-- 560 # Some comments from the ruby-talk list regarding finding the home 561 # directory: 562 # 563 # I have HOME, USERPROFILE and HOMEDRIVE + HOMEPATH. Ruby seems 564 # to be depending on HOME in those code samples. I propose that 565 # it should fallback to USERPROFILE and HOMEDRIVE + HOMEPATH (at 566 # least on Win32). 567 #++ 568 #-- 569 # 570 # FIXME move to pathsupport 571 # 572 #++ 573 574 def self.find_home 575 Dir.home.dup 576 rescue 577 if Gem.win_platform? 578 File.expand_path File.join(ENV['HOMEDRIVE'] || ENV['SystemDrive'], '/') 579 else 580 File.expand_path "/" 581 end 582 end 583 584 private_class_method :find_home 585 586 # TODO: remove in RubyGems 4.0 587 588 ## 589 # Zlib::GzipReader wrapper that unzips +data+. 590 591 def self.gunzip(data) 592 Gem::Util.gunzip data 593 end 594 595 class << self 596 extend Gem::Deprecate 597 deprecate :gunzip, "Gem::Util.gunzip", 2018, 12 598 end 599 600 ## 601 # Zlib::GzipWriter wrapper that zips +data+. 602 603 def self.gzip(data) 604 Gem::Util.gzip data 605 end 606 607 class << self 608 extend Gem::Deprecate 609 deprecate :gzip, "Gem::Util.gzip", 2018, 12 610 end 611 612 ## 613 # A Zlib::Inflate#inflate wrapper 614 615 def self.inflate(data) 616 Gem::Util.inflate data 617 end 618 619 class << self 620 extend Gem::Deprecate 621 deprecate :inflate, "Gem::Util.inflate", 2018, 12 622 end 623 624 ## 625 # Top level install helper method. Allows you to install gems interactively: 626 # 627 # % irb 628 # >> Gem.install "minitest" 629 # Fetching: minitest-3.0.1.gem (100%) 630 # => [#<Gem::Specification:0x1013b4528 @name="minitest", ...>] 631 632 def self.install(name, version = Gem::Requirement.default, *options) 633 require "rubygems/dependency_installer" 634 inst = Gem::DependencyInstaller.new(*options) 635 inst.install name, version 636 inst.installed_gems 637 end 638 639 ## 640 # Get the default RubyGems API host. This is normally 641 # <tt>https://rubygems.org</tt>. 642 643 def self.host 644 # TODO: move to utils 645 @host ||= Gem::DEFAULT_HOST 646 end 647 648 ## Set the default RubyGems API host. 649 650 def self.host=(host) 651 # TODO: move to utils 652 @host = host 653 end 654 655 ## 656 # The index to insert activated gem paths into the $LOAD_PATH. The activated 657 # gem's paths are inserted before site lib directory by default. 658 659 def self.load_path_insert_index 660 $LOAD_PATH.each_with_index do |path, i| 661 return i if path.instance_variable_defined?(:@gem_prelude_index) 662 end 663 664 index = $LOAD_PATH.index RbConfig::CONFIG['sitelibdir'] 665 666 index 667 end 668 669 @yaml_loaded = false 670 671 ## 672 # Loads YAML, preferring Psych 673 674 def self.load_yaml 675 return if @yaml_loaded 676 return unless defined?(gem) 677 678 begin 679 gem 'psych', '>= 2.0.0' 680 rescue Gem::LoadError 681 # It's OK if the user does not have the psych gem installed. We will 682 # attempt to require the stdlib version 683 end 684 685 begin 686 # Try requiring the gem version *or* stdlib version of psych. 687 require 'psych' 688 rescue ::LoadError 689 # If we can't load psych, thats fine, go on. 690 else 691 # If 'yaml' has already been required, then we have to 692 # be sure to switch it over to the newly loaded psych. 693 if defined?(YAML::ENGINE) && YAML::ENGINE.yamler != "psych" 694 YAML::ENGINE.yamler = "psych" 695 end 696 697 require 'rubygems/psych_additions' 698 require 'rubygems/psych_tree' 699 end 700 701 require 'yaml' 702 require 'rubygems/safe_yaml' 703 704 # Now that we're sure some kind of yaml library is loaded, pull 705 # in our hack to deal with Syck's DefaultKey ugliness. 706 require 'rubygems/syck_hack' 707 708 @yaml_loaded = true 709 end 710 711 ## 712 # The file name and line number of the caller of the caller of this method. 713 # 714 # +depth+ is how many layers up the call stack it should go. 715 # 716 # e.g., 717 # 718 # def a; Gem.location_of_caller; end 719 # a #=> ["x.rb", 2] # (it'll vary depending on file name and line number) 720 # 721 # def b; c; end 722 # def c; Gem.location_of_caller(2); end 723 # b #=> ["x.rb", 6] # (it'll vary depending on file name and line number) 724 725 def self.location_of_caller(depth = 1) 726 caller[depth] =~ /(.*?):(\d+).*?$/i 727 file = $1 728 lineno = $2.to_i 729 730 [file, lineno] 731 end 732 733 ## 734 # The version of the Marshal format for your Ruby. 735 736 def self.marshal_version 737 "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}" 738 end 739 740 ## 741 # Set array of platforms this RubyGems supports (primarily for testing). 742 743 def self.platforms=(platforms) 744 @platforms = platforms 745 end 746 747 ## 748 # Array of platforms this RubyGems supports. 749 750 def self.platforms 751 @platforms ||= [] 752 if @platforms.empty? 753 @platforms = [Gem::Platform::RUBY, Gem::Platform.local] 754 end 755 @platforms 756 end 757 758 ## 759 # Adds a post-build hook that will be passed an Gem::Installer instance 760 # when Gem::Installer#install is called. The hook is called after the gem 761 # has been extracted and extensions have been built but before the 762 # executables or gemspec has been written. If the hook returns +false+ then 763 # the gem's files will be removed and the install will be aborted. 764 765 def self.post_build(&hook) 766 @post_build_hooks << hook 767 end 768 769 ## 770 # Adds a post-install hook that will be passed an Gem::Installer instance 771 # when Gem::Installer#install is called 772 773 def self.post_install(&hook) 774 @post_install_hooks << hook 775 end 776 777 ## 778 # Adds a post-installs hook that will be passed a Gem::DependencyInstaller 779 # and a list of installed specifications when 780 # Gem::DependencyInstaller#install is complete 781 782 def self.done_installing(&hook) 783 @done_installing_hooks << hook 784 end 785 786 ## 787 # Adds a hook that will get run after Gem::Specification.reset is 788 # run. 789 790 def self.post_reset(&hook) 791 @post_reset_hooks << hook 792 end 793 794 ## 795 # Adds a post-uninstall hook that will be passed a Gem::Uninstaller instance 796 # and the spec that was uninstalled when Gem::Uninstaller#uninstall is 797 # called 798 799 def self.post_uninstall(&hook) 800 @post_uninstall_hooks << hook 801 end 802 803 ## 804 # Adds a pre-install hook that will be passed an Gem::Installer instance 805 # when Gem::Installer#install is called. If the hook returns +false+ then 806 # the install will be aborted. 807 808 def self.pre_install(&hook) 809 @pre_install_hooks << hook 810 end 811 812 ## 813 # Adds a hook that will get run before Gem::Specification.reset is 814 # run. 815 816 def self.pre_reset(&hook) 817 @pre_reset_hooks << hook 818 end 819 820 ## 821 # Adds a pre-uninstall hook that will be passed an Gem::Uninstaller instance 822 # and the spec that will be uninstalled when Gem::Uninstaller#uninstall is 823 # called 824 825 def self.pre_uninstall(&hook) 826 @pre_uninstall_hooks << hook 827 end 828 829 ## 830 # The directory prefix this RubyGems was installed at. If your 831 # prefix is in a standard location (ie, rubygems is installed where 832 # you'd expect it to be), then prefix returns nil. 833 834 def self.prefix 835 prefix = File.dirname RUBYGEMS_DIR 836 837 if prefix != File.expand_path(RbConfig::CONFIG['sitelibdir']) and 838 prefix != File.expand_path(RbConfig::CONFIG['libdir']) and 839 'lib' == File.basename(RUBYGEMS_DIR) 840 prefix 841 end 842 end 843 844 ## 845 # Refresh available gems from disk. 846 847 def self.refresh 848 Gem::Specification.reset 849 end 850 851 ## 852 # Safely read a file in binary mode on all platforms. 853 854 def self.read_binary(path) 855 File.open path, 'rb+' do |f| 856 f.flock(File::LOCK_EX) 857 f.read 858 end 859 rescue *READ_BINARY_ERRORS 860 File.open path, 'rb' do |f| 861 f.read 862 end 863 rescue Errno::ENOLCK # NFS 864 if Thread.main != Thread.current 865 raise 866 else 867 File.open path, 'rb' do |f| 868 f.read 869 end 870 end 871 end 872 873 ## 874 # Safely write a file in binary mode on all platforms. 875 def self.write_binary(path, data) 876 open(path, 'wb') do |io| 877 begin 878 io.flock(File::LOCK_EX) 879 rescue *WRITE_BINARY_ERRORS 880 end 881 io.write data 882 end 883 rescue Errno::ENOLCK # NFS 884 if Thread.main != Thread.current 885 raise 886 else 887 open(path, 'wb') do |io| 888 io.write data 889 end 890 end 891 end 892 893 ## 894 # The path to the running Ruby interpreter. 895 896 def self.ruby 897 if @ruby.nil? 898 @ruby = File.join(RbConfig::CONFIG['bindir'], 899 "#{RbConfig::CONFIG['ruby_install_name']}#{RbConfig::CONFIG['EXEEXT']}") 900 901 @ruby = "\"#{@ruby}\"" if @ruby =~ /\s/ 902 end 903 904 @ruby 905 end 906 907 ## 908 # Returns a String containing the API compatibility version of Ruby 909 910 def self.ruby_api_version 911 @ruby_api_version ||= RbConfig::CONFIG['ruby_version'].dup 912 end 913 914 def self.env_requirement(gem_name) 915 @env_requirements_by_name ||= {} 916 @env_requirements_by_name[gem_name] ||= begin 917 req = ENV["GEM_REQUIREMENT_#{gem_name.upcase}"] || '>= 0'.freeze 918 Gem::Requirement.create(req) 919 end 920 end 921 post_reset { @env_requirements_by_name = {} } 922 923 ## 924 # Returns the latest release-version specification for the gem +name+. 925 926 def self.latest_spec_for(name) 927 dependency = Gem::Dependency.new name 928 fetcher = Gem::SpecFetcher.fetcher 929 spec_tuples, = fetcher.spec_for_dependency dependency 930 931 spec, = spec_tuples.first 932 933 spec 934 end 935 936 ## 937 # Returns the latest release version of RubyGems. 938 939 def self.latest_rubygems_version 940 latest_version_for('rubygems-update') or 941 raise "Can't find 'rubygems-update' in any repo. Check `gem source list`." 942 end 943 944 ## 945 # Returns the version of the latest release-version of gem +name+ 946 947 def self.latest_version_for(name) 948 spec = latest_spec_for name 949 spec and spec.version 950 end 951 952 ## 953 # A Gem::Version for the currently running Ruby. 954 955 def self.ruby_version 956 return @ruby_version if defined? @ruby_version 957 version = RUBY_VERSION.dup 958 959 if defined?(RUBY_PATCHLEVEL) && RUBY_PATCHLEVEL != -1 960 version << ".#{RUBY_PATCHLEVEL}" 961 elsif defined?(RUBY_DESCRIPTION) 962 if RUBY_ENGINE == "ruby" 963 desc = RUBY_DESCRIPTION[/\Aruby #{Regexp.quote(RUBY_VERSION)}([^ ]+) /, 1] 964 else 965 desc = RUBY_DESCRIPTION[/\A#{RUBY_ENGINE} #{Regexp.quote(RUBY_ENGINE_VERSION)} \(#{RUBY_VERSION}([^ ]+)\) /, 1] 966 end 967 version << ".#{desc}" if desc 968 end 969 970 @ruby_version = Gem::Version.new version 971 end 972 973 ## 974 # A Gem::Version for the currently running RubyGems 975 976 def self.rubygems_version 977 return @rubygems_version if defined? @rubygems_version 978 @rubygems_version = Gem::Version.new Gem::VERSION 979 end 980 981 ## 982 # Returns an Array of sources to fetch remote gems from. Uses 983 # default_sources if the sources list is empty. 984 985 def self.sources 986 source_list = configuration.sources || default_sources 987 @sources ||= Gem::SourceList.from(source_list) 988 end 989 990 ## 991 # Need to be able to set the sources without calling 992 # Gem.sources.replace since that would cause an infinite loop. 993 # 994 # DOC: This comment is not documentation about the method itself, it's 995 # more of a code comment about the implementation. 996 997 def self.sources=(new_sources) 998 if !new_sources 999 @sources = nil 1000 else 1001 @sources = Gem::SourceList.from(new_sources) 1002 end 1003 end 1004 1005 ## 1006 # Glob pattern for require-able path suffixes. 1007 1008 def self.suffix_pattern 1009 @suffix_pattern ||= "{#{suffixes.join(',')}}" 1010 end 1011 1012 ## 1013 # Suffixes for require-able paths. 1014 1015 def self.suffixes 1016 @suffixes ||= ['', 1017 '.rb', 1018 *%w(DLEXT DLEXT2).map { |key| 1019 val = RbConfig::CONFIG[key] 1020 next unless val and not val.empty? 1021 ".#{val}" 1022 } 1023 ].compact.uniq 1024 end 1025 1026 ## 1027 # Prints the amount of time the supplied block takes to run using the debug 1028 # UI output. 1029 1030 def self.time(msg, width = 0, display = Gem.configuration.verbose) 1031 now = Time.now 1032 1033 value = yield 1034 1035 elapsed = Time.now - now 1036 1037 ui.say "%2$*1$s: %3$3.3fs" % [-width, msg, elapsed] if display 1038 1039 value 1040 end 1041 1042 ## 1043 # Lazily loads DefaultUserInteraction and returns the default UI. 1044 1045 def self.ui 1046 require 'rubygems/user_interaction' 1047 1048 Gem::DefaultUserInteraction.ui 1049 end 1050 1051 ## 1052 # Use the +home+ and +paths+ values for Gem.dir and Gem.path. Used mainly 1053 # by the unit tests to provide environment isolation. 1054 1055 def self.use_paths(home, *paths) 1056 paths.flatten! 1057 paths.compact! 1058 hash = { "GEM_HOME" => home, "GEM_PATH" => paths.empty? ? home : paths.join(File::PATH_SEPARATOR) } 1059 hash.delete_if { |_, v| v.nil? } 1060 self.paths = hash 1061 end 1062 1063 ## 1064 # The home directory for the user. 1065 1066 def self.user_home 1067 @user_home ||= find_home.untaint 1068 end 1069 1070 ## 1071 # Is this a windows platform? 1072 1073 def self.win_platform? 1074 if @@win_platform.nil? 1075 ruby_platform = RbConfig::CONFIG['host_os'] 1076 @@win_platform = !!WIN_PATTERNS.find { |r| ruby_platform =~ r } 1077 end 1078 1079 @@win_platform 1080 end 1081 1082 ## 1083 # Load +plugins+ as Ruby files 1084 1085 def self.load_plugin_files(plugins) # :nodoc: 1086 plugins.each do |plugin| 1087 1088 # Skip older versions of the GemCutter plugin: Its commands are in 1089 # RubyGems proper now. 1090 1091 next if plugin =~ /gemcutter-0\.[0-3]/ 1092 1093 begin 1094 load plugin 1095 rescue ::Exception => e 1096 details = "#{plugin.inspect}: #{e.message} (#{e.class})" 1097 warn "Error loading RubyGems plugin #{details}" 1098 end 1099 end 1100 end 1101 1102 ## 1103 # Find the 'rubygems_plugin' files in the latest installed gems and load 1104 # them 1105 1106 def self.load_plugins 1107 # Remove this env var by at least 3.0 1108 if ENV['RUBYGEMS_LOAD_ALL_PLUGINS'] 1109 load_plugin_files find_files('rubygems_plugin', false) 1110 else 1111 load_plugin_files find_latest_files('rubygems_plugin', false) 1112 end 1113 end 1114 1115 ## 1116 # Find all 'rubygems_plugin' files in $LOAD_PATH and load them 1117 1118 def self.load_env_plugins 1119 path = "rubygems_plugin" 1120 1121 files = [] 1122 glob = "#{path}#{Gem.suffix_pattern}" 1123 $LOAD_PATH.each do |load_path| 1124 globbed = Gem::Util.glob_files_in_dir(glob, load_path) 1125 1126 globbed.each do |load_path_file| 1127 files << load_path_file if File.file?(load_path_file.untaint) 1128 end 1129 end 1130 1131 load_plugin_files files 1132 end 1133 1134 ## 1135 # Looks for a gem dependency file at +path+ and activates the gems in the 1136 # file if found. If the file is not found an ArgumentError is raised. 1137 # 1138 # If +path+ is not given the RUBYGEMS_GEMDEPS environment variable is used, 1139 # but if no file is found no exception is raised. 1140 # 1141 # If '-' is given for +path+ RubyGems searches up from the current working 1142 # directory for gem dependency files (gem.deps.rb, Gemfile, Isolate) and 1143 # activates the gems in the first one found. 1144 # 1145 # You can run this automatically when rubygems starts. To enable, set 1146 # the <code>RUBYGEMS_GEMDEPS</code> environment variable to either the path 1147 # of your gem dependencies file or "-" to auto-discover in parent 1148 # directories. 1149 # 1150 # NOTE: Enabling automatic discovery on multiuser systems can lead to 1151 # execution of arbitrary code when used from directories outside your 1152 # control. 1153 1154 def self.use_gemdeps(path = nil) 1155 raise_exception = path 1156 1157 path ||= ENV['RUBYGEMS_GEMDEPS'] 1158 return unless path 1159 1160 path = path.dup 1161 1162 if path == "-" 1163 Gem::Util.traverse_parents Dir.pwd do |directory| 1164 dep_file = GEM_DEP_FILES.find { |f| File.file?(f) } 1165 1166 next unless dep_file 1167 1168 path = File.join directory, dep_file 1169 break 1170 end 1171 end 1172 1173 path.untaint 1174 1175 unless File.file? path 1176 return unless raise_exception 1177 1178 raise ArgumentError, "Unable to find gem dependencies file at #{path}" 1179 end 1180 1181 if USE_BUNDLER_FOR_GEMDEPS 1182 1183 ENV["BUNDLE_GEMFILE"] ||= File.expand_path(path) 1184 require 'rubygems/user_interaction' 1185 Gem::DefaultUserInteraction.use_ui(ui) do 1186 require "bundler" 1187 @gemdeps = Bundler.setup 1188 Bundler.ui = nil 1189 @gemdeps.requested_specs.map(&:to_spec).sort_by(&:name) 1190 end 1191 1192 else 1193 1194 rs = Gem::RequestSet.new 1195 @gemdeps = rs.load_gemdeps path 1196 1197 rs.resolve_current.map do |s| 1198 s.full_spec.tap(&:activate) 1199 end 1200 1201 end 1202 rescue => e 1203 case e 1204 when Gem::LoadError, Gem::UnsatisfiableDependencyError, (defined?(Bundler::GemNotFound) ? Bundler::GemNotFound : Gem::LoadError) 1205 warn e.message 1206 warn "You may need to `gem install -g` to install missing gems" 1207 warn "" 1208 else 1209 raise 1210 end 1211 end 1212 1213 class << self 1214 ## 1215 # TODO remove with RubyGems 4.0 1216 1217 alias detect_gemdeps use_gemdeps # :nodoc: 1218 1219 extend Gem::Deprecate 1220 deprecate :detect_gemdeps, "Gem.use_gemdeps", 2018, 12 1221 end 1222 1223 # FIX: Almost everywhere else we use the `def self.` way of defining class 1224 # methods, and then we switch over to `class << self` here. Pick one or the 1225 # other. 1226 class << self 1227 1228 ## 1229 # Hash of loaded Gem::Specification keyed by name 1230 1231 attr_reader :loaded_specs 1232 1233 ## 1234 # GemDependencyAPI object, which is set when .use_gemdeps is called. 1235 # This contains all the information from the Gemfile. 1236 1237 attr_reader :gemdeps 1238 1239 ## 1240 # Register a Gem::Specification for default gem. 1241 # 1242 # Two formats for the specification are supported: 1243 # 1244 # * MRI 2.0 style, where spec.files contains unprefixed require names. 1245 # The spec's filenames will be registered as-is. 1246 # * New style, where spec.files contains files prefixed with paths 1247 # from spec.require_paths. The prefixes are stripped before 1248 # registering the spec's filenames. Unprefixed files are omitted. 1249 # 1250 1251 def register_default_spec(spec) 1252 new_format = Gem.default_gems_use_full_paths? || spec.require_paths.any? {|path| spec.files.any? {|f| f.start_with? path } } 1253 1254 if new_format 1255 prefix_group = spec.require_paths.map {|f| f + "/"}.join("|") 1256 prefix_pattern = /^(#{prefix_group})/ 1257 end 1258 1259 suffix_pattern = /#{Regexp.union(Gem.suffixes)}\z/ 1260 1261 spec.files.each do |file| 1262 if new_format 1263 file = file.sub(prefix_pattern, "") 1264 next unless $~ 1265 end 1266 1267 @path_to_default_spec_map[file] = spec 1268 @path_to_default_spec_map[file.sub(suffix_pattern, "")] = spec 1269 end 1270 end 1271 1272 ## 1273 # Find a Gem::Specification of default gem from +path+ 1274 1275 def find_unresolved_default_spec(path) 1276 @path_to_default_spec_map[path] 1277 end 1278 1279 ## 1280 # Remove needless Gem::Specification of default gem from 1281 # unresolved default gem list 1282 1283 def remove_unresolved_default_spec(spec) 1284 spec.files.each do |file| 1285 @path_to_default_spec_map.delete(file) 1286 end 1287 end 1288 1289 ## 1290 # Clear default gem related variables. It is for test 1291 1292 def clear_default_specs 1293 @path_to_default_spec_map.clear 1294 end 1295 1296 ## 1297 # The list of hooks to be run after Gem::Installer#install extracts files 1298 # and builds extensions 1299 1300 attr_reader :post_build_hooks 1301 1302 ## 1303 # The list of hooks to be run after Gem::Installer#install completes 1304 # installation 1305 1306 attr_reader :post_install_hooks 1307 1308 ## 1309 # The list of hooks to be run after Gem::DependencyInstaller installs a 1310 # set of gems 1311 1312 attr_reader :done_installing_hooks 1313 1314 ## 1315 # The list of hooks to be run after Gem::Specification.reset is run. 1316 1317 attr_reader :post_reset_hooks 1318 1319 ## 1320 # The list of hooks to be run after Gem::Uninstaller#uninstall completes 1321 # installation 1322 1323 attr_reader :post_uninstall_hooks 1324 1325 ## 1326 # The list of hooks to be run before Gem::Installer#install does any work 1327 1328 attr_reader :pre_install_hooks 1329 1330 ## 1331 # The list of hooks to be run before Gem::Specification.reset is run. 1332 1333 attr_reader :pre_reset_hooks 1334 1335 ## 1336 # The list of hooks to be run before Gem::Uninstaller#uninstall does any 1337 # work 1338 1339 attr_reader :pre_uninstall_hooks 1340 end 1341 1342 ## 1343 # Location of Marshal quick gemspecs on remote repositories 1344 1345 MARSHAL_SPEC_DIR = "quick/Marshal.#{Gem.marshal_version}/".freeze 1346 1347 autoload :BundlerVersionFinder, 'rubygems/bundler_version_finder' 1348 autoload :ConfigFile, 'rubygems/config_file' 1349 autoload :Dependency, 'rubygems/dependency' 1350 autoload :DependencyList, 'rubygems/dependency_list' 1351 autoload :Installer, 'rubygems/installer' 1352 autoload :Licenses, 'rubygems/util/licenses' 1353 autoload :PathSupport, 'rubygems/path_support' 1354 autoload :Platform, 'rubygems/platform' 1355 autoload :RequestSet, 'rubygems/request_set' 1356 autoload :Requirement, 'rubygems/requirement' 1357 autoload :Resolver, 'rubygems/resolver' 1358 autoload :Source, 'rubygems/source' 1359 autoload :SourceList, 'rubygems/source_list' 1360 autoload :SpecFetcher, 'rubygems/spec_fetcher' 1361 autoload :Specification, 'rubygems/specification' 1362 autoload :Util, 'rubygems/util' 1363 autoload :Version, 'rubygems/version' 1364 1365 require "rubygems/specification" 1366end 1367 1368require 'rubygems/exceptions' 1369 1370# REFACTOR: This should be pulled out into some kind of hacks file. 1371begin 1372 ## 1373 # Defaults the operating system (or packager) wants to provide for RubyGems. 1374 1375 require 'rubygems/defaults/operating_system' 1376rescue LoadError 1377end 1378 1379if defined?(RUBY_ENGINE) 1380 begin 1381 ## 1382 # Defaults the Ruby implementation wants to provide for RubyGems 1383 1384 require "rubygems/defaults/#{RUBY_ENGINE}" 1385 rescue LoadError 1386 end 1387end 1388 1389## 1390# Loads the default specs. 1391Gem::Specification.load_defaults 1392 1393require 'rubygems/core_ext/kernel_gem' 1394require 'rubygems/core_ext/kernel_require' 1395require 'rubygems/core_ext/kernel_warn' 1396 1397Gem.use_gemdeps 1398