class Gem::ConfigFile

Gem::ConfigFile 来自 gemrc 的 RubyGems 选项和 gem 命令选项。

gemrc 是一个 YAML 文件,使用字符串来匹配 gem 命令参数,使用符号来匹配 RubyGems 选项。

Gem 命令参数使用与命令名称匹配的字符串键,并允许您指定默认参数

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

您可以使用 gem: 来为所有命令设置默认参数。

RubyGems 选项使用符号键。有效的选项有

:backtrace

请参阅 backtrace

:sources

设置 Gem::sources

:verbose

请参阅 verbose

:concurrent_downloads

请参阅 concurrent_downloads

gemrc 文件可能存在于各种位置,并按以下顺序读取和合并

  • 系统范围 (/etc/gemrc)

  • 每个用户 (~/.gemrc)

  • 每个环境(GEMRC 环境变量中列出的 gemrc 文件)

常量

DEFAULT_BACKTRACE
DEFAULT_BULK_THRESHOLD
DEFAULT_CERT_EXPIRATION_LENGTH_DAYS
DEFAULT_CONCURRENT_DOWNLOADS
DEFAULT_INSTALL_EXTENSION_IN_LIB

待办事项:在 RubyGems 4.0 中使用 false 作为此选项的默认值

DEFAULT_IPV4_FALLBACK_ENABLED
DEFAULT_UPDATE_SOURCES
DEFAULT_VERBOSITY
OPERATING_SYSTEM_DEFAULTS

供 Ruby 打包器设置配置默认值。在 rubygems/defaults/operating_system.rb 中设置

PLATFORM_DEFAULTS

供 Ruby 实现者设置配置默认值。在 rubygems/defaults/#{RUBY_ENGINE}.rb 中设置

SYSTEM_WIDE_CONFIG_FILE

属性

args[R]

提供给配置文件对象的参数列表。

backtrace[W]

如果我们在错误时打印回溯,则为 True。

bulk_threshold[RW]

批量阈值。如果缺少 gem 的数量高于此阈值,则使用批量下载技术。(已弃用)

cert_expiration_length_days[RW]

用于签署证书的有效期

concurrent_downloads[RW]

应该并行执行的 gem 下载数量。

disable_default_gem_server[RW]

如果我们想在推送 gem 时强制指定 gem 服务器,则为 True

hash[R]
home[RW]

安装 gem 的位置 (已弃用)

install_extension_in_lib[RW]

将扩展安装到 lib 以及扩展目录中。

ipv4_fallback_enabled[RW]

实验性 ==

当 IPv6 不可访问或速度较慢时回退到 IPv4(默认值:false)

path[RW]

查找 gem 的位置(已弃用)

sources[RW]

查找 gem 的来源

ssl_ca_cert[RW]

用于远程 https 连接的 openssl CA 证书的目录或文件路径名

ssl_client_cert[R]

用于客户端身份验证的远程 https 连接的 openssl 客户端证书的目录或文件路径名

ssl_verify_mode[R]

用于远程 https 连接的 openssl 验证模式值

update_sources[RW]

如果我们想每次都更新 SourceInfoCache,则为 True,否则为 False

verbose[RW]

输出的详细级别

  • false – 没有输出

  • true – 正常输出

  • :loud – 额外输出

公共类方法

dump_with_rubygems_yaml(content) 点击以切换源
# File rubygems/config_file.rb, line 545
def self.dump_with_rubygems_yaml(content)
  content.transform_keys! do |k|
    k.is_a?(Symbol) ? ":#{k}" : k
  end

  require_relative "yaml_serializer"
  Gem::YAMLSerializer.dump(content)
end
load_with_rubygems_config_hash(yaml) 点击以切换源
# File rubygems/config_file.rb, line 554
def self.load_with_rubygems_config_hash(yaml)
  require_relative "yaml_serializer"

  content = Gem::YAMLSerializer.load(yaml)
  deep_transform_config_keys!(content)
end
new(args) 点击以切换源

创建配置文件对象。 args 是来自命令行的参数列表。

以下命令行选项在此处提前处理,而不是在以后处理大多数命令选项时处理。

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

显然,这些需要由 ConfigFile 对象处理,以确保我们获得正确的配置文件。

--backtrace

需要尽早打开回溯,以便可以正确处理在正常选项解析之前的错误。

--debug

启用 Ruby 级别调试消息。出于与 --backtrace 相同的原因,尽早处理。

# File rubygems/config_file.rb, line 184
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
  @install_extension_in_lib = DEFAULT_INSTALL_EXTENSION_IN_LIB
  @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

  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

  @hash.transform_keys! do |k|
    # gemhome and gempath are not working with symbol keys
    if %w[backtrace bulk_threshold verbose update_sources cert_expiration_length_days
          install_extension_in_lib ipv4_fallback_enabled sources disable_default_gem_server
          ssl_verify_mode ssl_ca_cert ssl_client_cert].include?(k)
      k.to_sym
    else
      k
    end
  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
  @verbose                     = @hash[:verbose]                     if @hash.key? :verbose
  @update_sources              = @hash[:update_sources]              if @hash.key? :update_sources
  # TODO: We should handle concurrent_downloads same as other options
  @cert_expiration_length_days = @hash[:cert_expiration_length_days] if @hash.key? :cert_expiration_length_days
  @install_extension_in_lib    = @hash[:install_extension_in_lib]    if @hash.key? :install_extension_in_lib
  @ipv4_fallback_enabled       = @hash[:ipv4_fallback_enabled]       if @hash.key? :ipv4_fallback_enabled

  @home                        = @hash[:gemhome]                     if @hash.key? :gemhome
  @path                        = @hash[:gempath]                     if @hash.key? :gempath
  @sources                     = @hash[:sources]                     if @hash.key? :sources
  @disable_default_gem_server  = @hash[:disable_default_gem_server]  if @hash.key? :disable_default_gem_server
  @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

私有类方法

deep_transform_config_keys!(config) 点击以切换源
# File rubygems/config_file.rb, line 563
def self.deep_transform_config_keys!(config)
  config.transform_keys! do |k|
    if k.match?(/\A:(.*)\Z/)
      k[1..-1].to_sym
    elsif k.include?("__") || k.match?(%r{/\Z})
      if k.is_a?(Symbol)
        k.to_s.gsub(/__/,".").gsub(%r{/\Z}, "").to_sym
      else
        k.dup.gsub(/__/,".").gsub(%r{/\Z}, "")
      end
    else
      k
    end
  end

  config.transform_values! do |v|
    if v.is_a?(String)
      if v.match?(/\A:(.*)\Z/)
        v[1..-1].to_sym
      elsif v.match?(/\A[+-]?\d+\Z/)
        v.to_i
      elsif v.match?(/\Atrue|false\Z/)
        v == "true"
      elsif v.empty?
        nil
      else
        v
      end
    elsif v.empty?
      nil
    elsif v.is_a?(Hash)
      deep_transform_config_keys!(v)
    else
      v
    end
  end

  config
end

公共实例方法

[](key) 点击以切换源

返回 key 的配置信息。

# File rubygems/config_file.rb, line 524
def [](key)
  @hash[key] || @hash[key.to_s]
end
[]=(key, value) 点击以切换源

将配置选项 key 设置为 value

# File rubygems/config_file.rb, line 529
def []=(key, value)
  @hash[key] = value
end
api_keys() 点击以切换源

RubyGems.org 和备用 API 密钥的哈希值

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

  @api_keys
end
backtrace() 点击以切换源

如果已指定 backtrace 选项或调试已打开,则为 True。

# File rubygems/config_file.rb, line 388
def backtrace
  @backtrace || $DEBUG
end
check_credentials_permissions() 点击以切换源

检查凭据文件的权限。如果它们不是 0600,则会显示错误消息,并且 RubyGems 将中止。

# File rubygems/config_file.rb, line 261
  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 & 0o777

    return if existing_permissions == 0o600

    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.cn/profile/edit

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

    terminate_interaction 1
  end
config_file_name() 点击以切换源

配置文件的名称。

# File rubygems/config_file.rb, line 407
def config_file_name
  @config_file_name || Gem.config_file
end
credentials_path() 点击以切换源

RubyGems.org 凭据的位置

# File rubygems/config_file.rb, line 293
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| ... } 点击以切换源

委托给 @hash

# File rubygems/config_file.rb, line 431
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) 点击以切换源

处理命令参数。

# File rubygems/config_file.rb, line 449
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() 点击以切换源

从状态文件读取上次更新检查的时间

# File rubygems/config_file.rb, line 417
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) 点击以切换源

将上次更新检查的时间写入状态文件

# File rubygems/config_file.rb, line 426
def last_update_check=(timestamp)
  File.write(state_file_name, timestamp.to_s) if state_file_writable?
end
load_api_keys() 点击以切换源
# File rubygems/config_file.rb, line 302
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) 点击以切换源
# File rubygems/config_file.rb, line 365
def load_file(filename)
  yaml_errors = [ArgumentError]

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

  begin
    config = self.class.load_with_rubygems_config_hash(File.read(filename))
    if config.keys.any? {|k| k.to_s.gsub(%r{https?:\/\/}, "").include?(": ") }
      warn "Failed to load #{filename} because it doesn't contain valid YAML hash"
      return {}
    else
      return config
    end
  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() 点击以切换源

真正详细的模式会为您提供额外的输出。

# File rubygems/config_file.rb, line 467
def really_verbose
  case verbose
  when true, false, nil then
    false
  else
    true
  end
end
rubygems_api_key() 点击以切换源

返回 RubyGems.org API 密钥

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

  @rubygems_api_key
end
rubygems_api_key=(api_key) 点击以切换源

将 RubyGems.org API 密钥设置为 api_key

# File rubygems/config_file.rb, line 330
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) 点击以切换源

将特定主机的 API 密钥设置为 api_key

# File rubygems/config_file.rb, line 339
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)

  permissions = 0o600 & (~File.umask)
  File.open(credentials_path, "w", permissions) do |f|
    f.write self.class.dump_with_rubygems_yaml(config)
  end

  load_api_keys # reload
end
state_file_name() 点击以切换源

状态文件的名称。

# File rubygems/config_file.rb, line 412
def state_file_name
  Gem.state_file
end
state_file_writable?() 点击以切换源

检查状态文件是否可写。如果不存在,则创建空文件,以确保我们可以写入该文件。

# File rubygems/config_file.rb, line 393
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!() 点击以切换源

删除 +~/.gem/credentials+ 文件以清除所有当前会话。

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

  File.delete(credentials_path)
end
write() 点击以切换源

写出此配置文件,替换其来源。

# File rubygems/config_file.rb, line 514
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

私有实例方法

set_config_file_name(args) 点击以切换源
# File rubygems/config_file.rb, line 603
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 /^--config-file$/.match?(arg)
      need_config_file_name = true
    end
  end
end