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