# class Gem::ConfigFile

`Gem::ConfigFile` RubyGems options and gem command options from gemrc.

gemrc is a `YAML` file that uses strings to match gem command arguments and symbols to match RubyGems options.

`Gem` command arguments use a `String` key that matches the command name and allow you to specify default arguments:

    install: --no-rdoc --no-ri
    update: --no-rdoc --no-ri

You can use `gem:` to set default arguments for all commands.

RubyGems options use symbol keys. Valid options are:

`:backtrace`

  See `backtrace`

`:sources`

  Sets `Gem::sources`

`:verbose`

  See `verbose`

`:concurrent_downloads`

  See `concurrent_downloads`

gemrc files may exist in various locations and are read and merged in the following order:

- system wide (/etc/gemrc)

- per user (~/.gemrc)

- per environment (gemrc files listed in the GEMRC environment variable)

### Constants

DEFAULT_BACKTRACE
DEFAULT_BULK_THRESHOLD
DEFAULT_CERT_EXPIRATION_LENGTH_DAYS
DEFAULT_CONCURRENT_DOWNLOADS
DEFAULT_IPV4_FALLBACK_ENABLED
DEFAULT_UPDATE_SOURCES
DEFAULT_VERBOSITY
OPERATING_SYSTEM_DEFAULTS

  For Ruby packagers to set configuration defaults. `Set` in rubygems/defaults/operating_system.rb

PLATFORM_DEFAULTS

  For Ruby implementers to set configuration defaults. `Set` in rubygems/defaults/#{RUBY_ENGINE}.rb

SYSTEM_WIDE_CONFIG_FILE

### Attributes

args[R]

List of arguments supplied to the config file object.

backtrace[W]

True if we print backtraces on errors.

bulk_threshold[RW]

Bulk threshold value. If the number of missing gems are above this threshold value, then a bulk download technique is used. (deprecated)

cert_expiration_length_days[RW]

Expiration length to sign a certificate

concurrent_downloads[RW]

Number of gem downloads that should be performed concurrently.

disable_default_gem_server[RW]

True if we want to force specification of gem server when pushing a gem

hash[R]
home[RW]

Where to install gems (deprecated)

ipv4_fallback_enabled[RW]

## Experimental ==¶ ↑

Fallback to IPv4 when IPv6 is not reachable or slow (default: false)

path[RW]

Where to look for gems (deprecated)

sources[RW]

sources to look for gems

ssl_ca_cert[RW]

Path name of directory or file of openssl CA certificate, used for remote https connection

ssl_client_cert[R]

Path name of directory or file of openssl client certificate, used for remote https connection with client authentication

ssl_verify_mode[R]

openssl verify mode value, used for remote https connection

update_sources[RW]

True if we want to update the SourceInfoCache every time, false otherwise

verbose[RW]

Verbose level of output:

- false – No output

- true – Normal output

- :loud – Extra output

### Public Class Methods

new(args) click to toggle source

Create the config file object. `args` is the list of arguments from the command line.

The following command line options are handled early here rather than later at the time most command options are processed.

`--config-file`, `--config-file==NAME`

  Obviously these need to be handled by the `ConfigFile` object to ensure we get the right config file.

`--backtrace`

  Backtrace needs to be turned on early so that errors before normal option parsing can be properly handled.

`--debug`

  Enable Ruby level debug messages. Handled early for the same reason as –backtrace.

    # File lib/rubygems/config_file.rb, line 176
    def initialize(args)
      set_config_file_name(args)

      @backtrace = DEFAULT_BACKTRACE
      @bulk_threshold = DEFAULT_BULK_THRESHOLD
      @verbose = DEFAULT_VERBOSITY
      @update_sources = DEFAULT_UPDATE_SOURCES
      @concurrent_downloads = DEFAULT_CONCURRENT_DOWNLOADS
      @cert_expiration_length_days = DEFAULT_CERT_EXPIRATION_LENGTH_DAYS
      @ipv4_fallback_enabled = ENV["IPV4_FALLBACK_ENABLED"] == "true" || DEFAULT_IPV4_FALLBACK_ENABLED

      operating_system_config = Marshal.load Marshal.dump(OPERATING_SYSTEM_DEFAULTS)
      platform_config = Marshal.load Marshal.dump(PLATFORM_DEFAULTS)
      system_config = load_file SYSTEM_WIDE_CONFIG_FILE
      user_config = load_file config_file_name.dup.tap(&Gem::UNTAINT)

      environment_config = (ENV["GEMRC"] || "")
        .split(File::PATH_SEPARATOR).inject({}) do |result, file|
          result.merge load_file file
        end

      @hash = operating_system_config.merge platform_config
      unless args.index "--norc"
        @hash = @hash.merge system_config
        @hash = @hash.merge user_config
        @hash = @hash.merge environment_config
      end

      # HACK these override command-line args, which is bad
      @backtrace                   = @hash[:backtrace]                   if @hash.key? :backtrace
      @bulk_threshold              = @hash[:bulk_threshold]              if @hash.key? :bulk_threshold
      @home                        = @hash[:gemhome]                     if @hash.key? :gemhome
      @path                        = @hash[:gempath]                     if @hash.key? :gempath
      @update_sources              = @hash[:update_sources]              if @hash.key? :update_sources
      @verbose                     = @hash[:verbose]                     if @hash.key? :verbose
      @disable_default_gem_server  = @hash[:disable_default_gem_server]  if @hash.key? :disable_default_gem_server
      @sources                     = @hash[:sources]                     if @hash.key? :sources
      @cert_expiration_length_days = @hash[:cert_expiration_length_days] if @hash.key? :cert_expiration_length_days
      @ipv4_fallback_enabled       = @hash[:ipv4_fallback_enabled]       if @hash.key? :ipv4_fallback_enabled

      @ssl_verify_mode  = @hash[:ssl_verify_mode]  if @hash.key? :ssl_verify_mode
      @ssl_ca_cert      = @hash[:ssl_ca_cert]      if @hash.key? :ssl_ca_cert
      @ssl_client_cert  = @hash[:ssl_client_cert]  if @hash.key? :ssl_client_cert

      @api_keys         = nil
      @rubygems_api_key = nil

      handle_arguments args
    end

### Public Instance Methods

[](key) click to toggle source

Return the configuration information for `key`.

    # File lib/rubygems/config_file.rb, line 503
    def [](key)
      @hash[key.to_s]
    end

[]=(key, value) click to toggle source

`Set` configuration option `key` to `value`.

    # File lib/rubygems/config_file.rb, line 508
    def []=(key, value)
      @hash[key.to_s] = value
    end

api_keys() click to toggle source

`Hash` of RubyGems.org and alternate API keys

    # File lib/rubygems/config_file.rb, line 229
    def api_keys
      load_api_keys unless @api_keys

      @api_keys
    end

backtrace() click to toggle source

True if the backtrace option has been specified, or debug is on.

    # File lib/rubygems/config_file.rb, line 370
    def backtrace
      @backtrace || $DEBUG
    end

check_credentials_permissions() click to toggle source

Checks the permissions of the credentials file. If they are not 0600 an error message is displayed and RubyGems aborts.

    # File lib/rubygems/config_file.rb, line 239
      def check_credentials_permissions
        return if Gem.win_platform? # windows doesn't write 0600 as 0600
        return unless File.exist? credentials_path

        existing_permissions = File.stat(credentials_path).mode & 0777

        return if existing_permissions == 0600

        alert_error <<-ERROR
    Your gem push credentials file located at:

    \t#{credentials_path}

    has file permissions of 0#{existing_permissions.to_s 8} but 0600 is required.

    To fix this error run:

    \tchmod 0600 #{credentials_path}

    You should reset your credentials at:

    \thttps://rubygems.org/profile/edit

    if you believe they were disclosed to a third party.
        ERROR

        terminate_interaction 1
      end

config_file_name() click to toggle source

The name of the configuration file.

    # File lib/rubygems/config_file.rb, line 389
    def config_file_name
      @config_file_name || Gem.config_file
    end

credentials_path() click to toggle source

Location of RubyGems.org credentials

    # File lib/rubygems/config_file.rb, line 271
    def credentials_path
      credentials = File.join Gem.user_home, ".gem", "credentials"
      if File.exist? credentials
        credentials
      else
        File.join Gem.data_home, "gem", "credentials"
      end
    end

each() { |:update_sources, update_sources| ... } click to toggle source

Delegates to @hash

    # File lib/rubygems/config_file.rb, line 413
    def each(&block)
      hash = @hash.dup
      hash.delete :update_sources
      hash.delete :verbose
      hash.delete :backtrace
      hash.delete :bulk_threshold

      yield :update_sources, @update_sources
      yield :verbose, @verbose
      yield :backtrace, @backtrace
      yield :bulk_threshold, @bulk_threshold

      yield "config_file_name", @config_file_name if @config_file_name

      hash.each(&block)
    end

handle_arguments(arg_list) click to toggle source

Handle the command arguments.

    # File lib/rubygems/config_file.rb, line 431
    def handle_arguments(arg_list)
      @args = []

      arg_list.each do |arg|
        case arg
        when /^--(backtrace|traceback)$/ then
          @backtrace = true
        when /^--debug$/ then
          $DEBUG = true

          warn "NOTE:  Debugging mode prints all exceptions even when rescued"
        else
          @args << arg
        end
      end
    end

last_update_check() click to toggle source

Reads time of last update check from state file

    # File lib/rubygems/config_file.rb, line 399
    def last_update_check
      if File.readable?(state_file_name)
        File.read(state_file_name).to_i
      else
        0
      end
    end

last_update_check=(timestamp) click to toggle source

Writes time of last update check to state file

    # File lib/rubygems/config_file.rb, line 408
    def last_update_check=(timestamp)
      File.write(state_file_name, timestamp.to_s) if state_file_writable?
    end

load_api_keys() click to toggle source

    # File lib/rubygems/config_file.rb, line 280
    def load_api_keys
      check_credentials_permissions

      @api_keys = if File.exist? credentials_path
        load_file(credentials_path)
      else
        @hash
      end

      if @api_keys.key? :rubygems_api_key
        @rubygems_api_key    = @api_keys[:rubygems_api_key]
        @api_keys[:rubygems] = @api_keys.delete :rubygems_api_key unless
          @api_keys.key? :rubygems
      end
    end

load_file(filename) click to toggle source

    # File lib/rubygems/config_file.rb, line 345
    def load_file(filename)
      Gem.load_yaml

      yaml_errors = [ArgumentError]
      yaml_errors << Psych::SyntaxError if defined?(Psych::SyntaxError)

      return {} unless filename && !filename.empty? && File.exist?(filename)

      begin
        content = Gem::SafeYAML.load(File.read(filename))
        unless content.kind_of? Hash
          warn "Failed to load #{filename} because it doesn't contain valid YAML hash"
          return {}
        end
        return content
      rescue *yaml_errors => e
        warn "Failed to load #{filename}, #{e}"
      rescue Errno::EACCES
        warn "Failed to load #{filename} due to permissions problem."
      end

      {}
    end

really_verbose() click to toggle source

Really verbose mode gives you extra output.

    # File lib/rubygems/config_file.rb, line 449
    def really_verbose
      case verbose
      when true, false, nil then
        false
      else
        true
      end
    end

rubygems_api_key() click to toggle source

Returns the RubyGems.org API key

    # File lib/rubygems/config_file.rb, line 299
    def rubygems_api_key
      load_api_keys unless @rubygems_api_key

      @rubygems_api_key
    end

rubygems_api_key=(api_key) click to toggle source

Sets the RubyGems.org API key to `api_key`

    # File lib/rubygems/config_file.rb, line 308
    def rubygems_api_key=(api_key)
      set_api_key :rubygems_api_key, api_key

      @rubygems_api_key = api_key
    end

set_api_key(host, api_key) click to toggle source

`Set` a specific host’s API key to `api_key`

    # File lib/rubygems/config_file.rb, line 317
    def set_api_key(host, api_key)
      check_credentials_permissions

      config = load_file(credentials_path).merge(host => api_key)

      dirname = File.dirname credentials_path
      require "fileutils"
      FileUtils.mkdir_p(dirname)

      Gem.load_yaml

      permissions = 0600 & (~File.umask)
      File.open(credentials_path, "w", permissions) do |f|
        f.write config.to_yaml
      end

      load_api_keys # reload
    end

state_file_name() click to toggle source

The name of the state file.

    # File lib/rubygems/config_file.rb, line 394
    def state_file_name
      Gem.state_file
    end

state_file_writable?() click to toggle source

Check state file is writable. Creates empty file if not present to ensure we can write to it.

    # File lib/rubygems/config_file.rb, line 375
    def state_file_writable?
      if File.exist?(state_file_name)
        File.writable?(state_file_name)
      else
        require "fileutils"
        FileUtils.mkdir_p File.dirname(state_file_name)
        File.open(state_file_name, "w") {}
        true
      end
    rescue Errno::EACCES
      false
    end

unset_api_key!() click to toggle source

Remove the +~/.gem/credentials+ file to clear all the current sessions.

    # File lib/rubygems/config_file.rb, line 339
    def unset_api_key!
      return false unless File.exist?(credentials_path)

      File.delete(credentials_path)
    end

write() click to toggle source

Writes out this config file, replacing its source.

    # File lib/rubygems/config_file.rb, line 493
    def write
      require "fileutils"
      FileUtils.mkdir_p File.dirname(config_file_name)

      File.open config_file_name, "w" do |io|
        io.write to_yaml
      end
    end

### Private Instance Methods

set_config_file_name(args) click to toggle source

    # File lib/rubygems/config_file.rb, line 526
    def set_config_file_name(args)
      @config_file_name = ENV["GEMRC"]
      need_config_file_name = false

      args.each do |arg|
        if need_config_file_name
          @config_file_name = arg
          need_config_file_name = false
        elsif arg =~ /^--config-file=(.*)/
          @config_file_name = $1
        elsif arg =~ /^--config-file$/
          need_config_file_name = true
        end
      end
    end