模块 Gem
RubyGems 是发布和管理第三方库的 Ruby 标准。
有关用户文档,请参见
-
gem help
和gem help [command]
有关 gem 开发人员文档,请参见
-
Gem::Version
,了解版本依赖项说明
更多 RubyGems 文档可以在以下位置找到
-
RubyGems API(也可以从
gem server
获取)
RubyGems 插件¶ ↑
RubyGems 将加载每个已安装 gem 或 $LOAD_PATH 的最新版本中的插件。插件必须命名为“rubygems_plugin”(.rb,.so 等),并放置在 gem 的 require_path 的根目录中。插件安装在特殊位置,并在启动时加载。
有关示例插件,请参见Graph gem,它添加了 gem graph
命令。
RubyGems 默认值,打包¶ ↑
RubyGems 默认值存储在 lib/rubygems/defaults.rb 中。如果您正在打包 RubyGems 或实现 Ruby,则可以更改 RubyGems 的默认值。
对于 RubyGems 打包者,请提供 lib/rubygems/defaults/operating_system.rb 并覆盖 lib/rubygems/defaults.rb 中的任何默认值。
对于 Ruby 实现者,请提供 lib/rubygems/defaults/#{RUBY_ENGINE}.rb 并覆盖 lib/rubygems/defaults.rb 中的任何默认值。
如果需要 RubyGems 在安装或卸载时执行额外的工作,则默认值覆盖文件可以设置安装前/后和卸载挂钩。请参见Gem::pre_install
,Gem::pre_uninstall
,Gem::post_install
,Gem::post_uninstall
。
错误¶ ↑
您可以将错误提交到 GitHub 上的RubyGems 错误跟踪器
贡献者¶ ↑
RubyGems 目前由 Eric Hodel 维护。
RubyGems 最初由以下人员在 RubyConf 2003 上开发:
-
Rich Kilmer – rich(at)infoether.com
-
Chad Fowler – chad(at)chadfowler.com
-
David Black – dblack(at)wobblini.net
-
Paul Brannan – paul(at)atdesk.com
-
Jim Weirich – jim(at)weirichhouse.org
贡献者
-
Gavin Sinclair – gsinclair(at)soyabean.com.au
-
George Marrows – george.marrows(at)ntlworld.com
-
Dick Davies – rasputnik(at)hellooperator.net
-
Mauricio Fernandez – batsman.geo(at)yahoo.com
-
Simon Strandgaard – neoneye(at)adslhome.dk
-
Dave Glasser – glasser(at)mit.edu
-
Paul Duncan – pabs(at)pablotron.org
-
Ville Aine – vaine(at)cs.helsinki.fi
-
Eric Hodel – drbrain(at)segment7.net
-
Daniel Berger – djberg96(at)gmail.com
-
Phil Hagelberg – technomancy(at)gmail.com
-
Ryan Davis – ryand-ruby(at)zenspider.com
-
Evan Phoenix – evan(at)fallingsnow.net
-
Steve Klabnik – steve(at)steveklabnik.com
(如果您的名字遗漏了,请务必告知我们!)
许可证¶ ↑
有关权限,请参见LICENSE.txt。
谢谢!
-RubyGems 团队
提供了 3 种方法来声明某项内容何时将被弃用。
+deprecate(name, repl, year, month)+
Indicate something may be removed on/after a certain date.
+rubygems_deprecate(name, replacement=:none)+
Indicate something will be removed in the next major RubyGems version, and (optionally) a replacement for it.
rubygems_deprecate_command
:
Indicate a RubyGems command (in +lib/rubygems/commands/*.rb+) will be removed in the next RubyGems version.
还提供了 skip_during
来临时关闭弃用警告。此方法旨在在测试套件中使用,这样,如果您需要确保 stderr 为空,则弃用警告不会导致测试失败。
deprecate
和 rubygems_deprecate
的用法示例
class Legacy def self.some_class_method # ... end def some_instance_method # ... end def some_old_method # ... end extend Gem::Deprecate deprecate :some_instance_method, "X.z", 2011, 4 rubygems_deprecate :some_old_method, "Modern#some_new_method" class << self extend Gem::Deprecate deprecate :some_class_method, :none, 2011, 4 end end
rubygems_deprecate_command
的用法示例
class Gem::Commands::QueryCommand < Gem::Command extend Gem::Deprecate rubygems_deprecate_command # ... end
skip_during
的用法示例
class TestSomething < Gem::Testcase def test_some_thing_with_deprecations Gem::Deprecate.skip_during do actual_stdout, actual_stderr = capture_output do Gem.something_deprecated end assert_empty actual_stdout assert_equal(expected, actual_stderr) end end end
常量
- DEFAULT_HOST
- GEM_DEP_FILES
- LOADED_SPECS_MUTEX
- MARSHAL_SPEC_DIR
远程存储库上 Marshal 快速 gemspec 的位置
- RDoc
- REPOSITORY_DEFAULT_GEM_SUBDIRECTORIES
默认 gem 的 gem 存储库中的子目录
- REPOSITORY_SUBDIRECTORIES
gem 存储库中的子目录
- RUBYGEMS_DIR
- VERSION
- WIN_PATTERNS
与 Windows Ruby 平台匹配的正则表达式数组。
属性
RubyGems 分发者(如操作系统软件包管理器)可以通过将此属性设置为错误消息(而不是实际更新),在 gem update --system 上打印给最终用户,从而禁用 RubyGems 更新。
RubyGems 是否应增强内置的“require”,以自动检查所要求的路径是否存在于已安装的 gem 中,并自动激活它们并将其添加到 `$LOAD_PATH`。
在Gem::DependencyInstaller
安装一组 gem 后要运行的挂钩列表
GemDependencyAPI 对象,在调用 .use_gemdeps 时设置。其中包含来自 Gemfile 的所有信息。
按名称键入的加载的Gem::Specification
的哈希
在Gem::Installer#install
提取文件并构建扩展后要运行的挂钩列表
在Gem::Installer#install
完成安装后要运行的挂钩列表
在运行Gem::Specification.reset
后要运行的挂钩列表。
在Gem::Uninstaller#uninstall
完成安装后要运行的挂钩列表
在Gem::Installer#install
执行任何工作之前要运行的挂钩列表
在运行Gem::Specification.reset
之前要运行的挂钩列表。
在Gem::Uninstaller#uninstall
执行任何工作之前要运行的挂钩列表
公共类方法
返回从给定 uri
派生的 Gem::URI 对象,该对象可以是 Gem::URI 字符串或现有的 Gem::URI 对象
# Returns a new Gem::URI. uri = Gem::URI('http://github.com/ruby/ruby') # => #<Gem::URI::HTTP http://github.com/ruby/ruby> # Returns the given Gem::URI. Gem::URI(uri) # => #<Gem::URI::HTTP http://github.com/ruby/ruby>
# File rubygems/vendor/uri/lib/uri/common.rb, line 865 def URI(uri) if uri.is_a?(Gem::URI::Generic) uri elsif uri = String.try_convert(uri) Gem::URI.parse(uri) else raise ArgumentError, "bad argument (expected Gem::URI object or Gem::URI string)" end end
来自已激活 gem 的 +$LOAD_PATH+ 中的路径数。用于在 require
期间优先处理 -I
和 ENV['RUBYLIB']
条目。
# File rubygems.rb, line 592 def self.activated_gem_paths @activated_gem_paths ||= 0 end
将路径列表添加到 $LOAD_PATH 中的适当位置。
# File rubygems.rb, line 599 def self.add_to_load_path(*paths) @activated_gem_paths = activated_gem_paths + paths.size # gem directories must come after -I and ENV['RUBYLIB'] $LOAD_PATH.insert(Gem.load_path_insert_index, *paths) end
查找 gem name
的可执行文件的完整路径。如果未提供 exec_name
,则会引发异常,否则将返回指定可执行文件的路径。requirements
允许您指定特定的 gem 版本。
# File rubygems.rb, line 238 def self.bin_path(name, exec_name = nil, *requirements) requirements = Gem::Requirement.default if requirements.empty? find_spec_for_exe(name, exec_name, requirements).bin_file exec_name end
以纯二进制方式读取文件所需的模式。
# File rubygems.rb, line 292 def self.binary_mode "rb" end
gem 可执行文件要安装到的路径。
# File rubygems.rb, line 299 def self.bindir(install_dir=Gem.dir) return File.join install_dir, "bin" unless install_dir.to_s == Gem.default_dir.to_s Gem.default_bindir end
用户缓存目录的标准位置的路径。
# File rubygems/defaults.rb, line 147 def self.cache_home @cache_home ||= ENV["XDG_CACHE_HOME"] || File.join(Gem.user_home, ".cache") end
清除默认的 gem 相关变量。用于测试。
# File rubygems.rb, line 1270 def clear_default_specs @path_to_default_spec_map.clear end
重置 dir
和 path
的值。下次请求 dir
或 path
时,将从头开始计算这些值。这主要用于单元测试以提供测试隔离。
# File rubygems.rb, line 317 def self.clear_paths @paths = nil @user_home = nil Gem::Specification.reset Gem::Security.reset if defined?(Gem::Security) end
用户的 .gemrc 文件的标准位置的路径。
# File rubygems/defaults.rb, line 133 def self.config_file @config_file ||= find_config_file end
用户的配置目录的标准位置的路径。
# File rubygems/defaults.rb, line 114 def self.config_home @config_home ||= ENV["XDG_CONFIG_HOME"] || File.join(Gem.user_home, ".config") end
gems 的标准配置对象。
# File rubygems.rb, line 327 def self.configuration @configuration ||= Gem::ConfigFile.new [] end
使用给定的配置对象(实现 ConfigFile
协议)作为标准配置对象。
# File rubygems.rb, line 335 def self.configuration=(config) @configuration = config end
用户数据目录的标准位置的路径。
# File rubygems/defaults.rb, line 154 def self.data_home @data_home ||= ENV["XDG_DATA_HOME"] || File.join(Gem.user_home, ".local", "share") end
二进制文件的默认目录。
# File rubygems/defaults.rb, line 204 def self.default_bindir RbConfig::CONFIG["bindir"] end
默认签名证书链路径。
# File rubygems/defaults.rb, line 228 def self.default_cert_path default_cert_path = File.join Gem.user_home, ".gem", "gem-public_cert.pem" unless File.exist?(default_cert_path) default_cert_path = File.join Gem.data_home, "gem", "gem-public_cert.pem" end default_cert_path end
如果环境中未指定备用值,则要使用的默认主目录路径。
# File rubygems/defaults.rb, line 37 def self.default_dir @default_dir ||= File.join(RbConfig::CONFIG["rubylibprefix"], "gems", RbConfig::CONFIG["ruby_version"]) end
从 Ruby 的安装名称推断其 --program-prefix 和 --program-suffix。
# File rubygems/defaults.rb, line 186 def self.default_exec_format exec_format = begin RbConfig::CONFIG["ruby_install_name"].sub("ruby", "%s") rescue StandardError "%s" end unless exec_format.include?("%s") raise Gem::Exception, "[BUG] invalid exec_format #{exec_format.inspect}, no %s" end exec_format end
返回指定 RubyGems 基本目录的二进制扩展目录,如果无法确定此类目录,则返回 nil。
默认情况下,二进制扩展与它们的 Ruby 对应项并排存在,因此返回 nil。
# File rubygems/defaults.rb, line 48 def self.default_ext_dir_for(base_dir) nil end
默认签名密钥路径。
# File rubygems/defaults.rb, line 215 def self.default_key_path default_key_path = File.join Gem.user_home, ".gem", "gem-private_key.pem" unless File.exist?(default_key_path) default_key_path = File.join Gem.data_home, "gem", "gem-private_key.pem" end default_key_path end
默认 gem 加载路径。
# File rubygems/defaults.rb, line 175 def self.default_path path = [] path << user_dir if user_home && File.exist?(user_home) path << default_dir path << vendor_dir if vendor_dir && File.directory?(vendor_dir) path end
RubyGems 的 .rb 文件和 bin 文件安装的路径。
# File rubygems/defaults.rb, line 55 def self.default_rubygems_dirs nil # default to standard layout end
RubyGems 附带的默认源的数组。
# File rubygems/defaults.rb, line 15 def self.default_sources %w[https://rubygems.org.cn/] end
如果环境中未指定备用值,则要使用的默认 spec 目录路径。
# File rubygems/defaults.rb, line 23 def self.default_spec_cache_dir default_spec_cache_dir = File.join Gem.user_home, ".gem", "specs" unless File.exist?(default_spec_cache_dir) default_spec_cache_dir = File.join Gem.cache_home, "gem", "specs" end default_spec_cache_dir end
默认 gem 的 specification 文件路径。
# File rubygems/defaults.rb, line 62 def self.default_specifications_dir @default_specifications_dir ||= File.join(Gem.default_dir, "specifications", "default") end
一个 Zlib::Deflate.deflate 包装器。
# File rubygems.rb, line 342 def self.deflate(data) require "zlib" Zlib::Deflate.deflate data end
gems 要安装到的路径。
# File rubygems.rb, line 390 def self.dir paths.home end
添加一个安装后钩子,当 Gem::DependencyInstaller#install
完成时,该钩子将传递一个 Gem::DependencyInstaller
和已安装的 specifications 列表。
# File rubygems.rb, line 703 def self.done_installing(&hook) @done_installing_hooks << hook end
动态库可 require 路径的后缀。
# File rubygems.rb, line 977 def self.dynamic_library_suffixes @dynamic_library_suffixes ||= suffixes - [".rb"] end
静默地确保 Gem
目录 dir
包含处理默认 gems 的所有适当子目录。如果由于权限问题而无法创建目录,我们将静默地继续。
如果给定了 mode
,则使用此模式创建缺少的目录。
永远不会创建全局可写的目录。
# File rubygems.rb, line 441 def self.ensure_default_gem_subdirectories(dir = Gem.dir, mode = nil) ensure_subdirectories(dir, mode, REPOSITORY_DEFAULT_GEM_SUBDIRECTORIES) end
静默地确保 Gem
目录 dir
包含所有适当的子目录。如果由于权限问题而无法创建目录,我们将静默地继续。
如果给定了 mode
,则使用此模式创建缺少的目录。
永远不会创建全局可写的目录。
# File rubygems.rb, line 428 def self.ensure_gem_subdirectories(dir = Gem.dir, mode = nil) ensure_subdirectories(dir, mode, REPOSITORY_SUBDIRECTORIES) end
# File rubygems.rb, line 845 def self.env_requirement(gem_name) @env_requirements_by_name ||= {} @env_requirements_by_name[gem_name] ||= begin req = ENV["GEM_REQUIREMENT_#{gem_name.upcase}"] || ">= 0" Gem::Requirement.create(req) end end
查找用户的配置文件。
# File rubygems/defaults.rb, line 121 def self.find_config_file gemrc = File.join Gem.user_home, ".gemrc" if File.exist? gemrc gemrc else File.join Gem.config_home, "gem", "gemrc" end end
从 path
查找默认 gem 的 Gem::Specification
。
# File rubygems.rb, line 1255 def find_default_spec(path) @path_to_default_spec_map[path] end
返回与 glob
匹配的路径列表,gem 可以使用这些路径从其他 gems 中获取功能。例如
Gem.find_files('rdoc/discover').each do |path| load path end
如果 check_load_path
为 true(默认值),则 find_files
也会在 $LOAD_PATH 中搜索文件以及 gems。
请注意,即使文件来自同一 gem 的不同版本,find_files
也会返回所有文件。另请参见 find_latest_files
。
# File rubygems.rb, line 492 def self.find_files(glob, check_load_path=true) files = [] files = find_files_from_load_path glob if check_load_path gem_specifications = @gemdeps ? Gem.loaded_specs.values : Gem::Specification.stubs files.concat gem_specifications.flat_map {|spec| spec.matches_for_glob("#{glob}#{Gem.suffix_pattern}") } # $LOAD_PATH might contain duplicate entries or reference # the spec dirs directly, so we prune. files.uniq! if check_load_path files end
返回与 glob
匹配的路径列表,这些路径来自最新的 gem,gem 可以使用它们从其他 gem 中获取功能。例如
Gem.find_latest_files('rdoc/discover').each do |path| load path end
如果 check_load_path
为 true(默认值),则 find_latest_files
也会在 $LOAD_PATH 中搜索文件以及 gems。
与 find_files
不同,find_latest_files
将仅返回来自 gem 的最新版本的文件。
# File rubygems.rb, line 529 def self.find_latest_files(glob, check_load_path=true) files = [] files = find_files_from_load_path glob if check_load_path files.concat Gem::Specification.latest_specs(true).flat_map {|spec| spec.matches_for_glob("#{glob}#{Gem.suffix_pattern}") } # $LOAD_PATH might contain duplicate entries or reference # the spec dirs directly, so we prune. files.uniq! if check_load_path files end
从 path
查找默认 gem 的未解析 Gem::Specification
。
# File rubygems.rb, line 1262 def find_unresolved_default_spec(path) default_spec = @path_to_default_spec_map[path] default_spec if default_spec && loaded_specs[default_spec.name] != default_spec end
# File rubygems.rb, line 223 def self.finish_resolve(request_set=Gem::RequestSet.new) request_set.import Gem::Specification.unresolved_deps.values request_set.import Gem.loaded_specs.values.map {|s| Gem::Dependency.new(s.name, s.version) } request_set.resolve_current.each do |s| s.full_spec.activate end end
此平台是否为 FreeBSD。
# File rubygems.rb, line 1047 def self.freebsd_platform? RbConfig::CONFIG["host_os"].to_s.include?("bsd") end
获取默认的 RubyGems API 主机。这通常是 https://rubygems.org.cn
。
# File rubygems.rb, line 564 def self.host @host ||= Gem::DEFAULT_HOST end
设置默认的 RubyGems API 主机。
# File rubygems.rb, line 570 def self.host=(host) @host = host end
顶级安装帮助方法。允许您以交互方式安装 gems。
% irb >> Gem.install "minitest" Fetching: minitest-5.14.0.gem (100%) => [#<Gem::Specification:0x1013b4528 @name="minitest", ...>]
# File rubygems.rb, line 553 def self.install(name, version = Gem::Requirement.default, *options) require_relative "rubygems/dependency_installer" inst = Gem::DependencyInstaller.new(*options) inst.install name, version inst.installed_gems end
这是一个 java 平台吗?
# File rubygems.rb, line 1033 def self.java_platform? RUBY_PLATFORM == "java" end
返回 RubyGems 的最新发行版本。
# File rubygems.rb, line 870 def self.latest_rubygems_version latest_version_for("rubygems-update") || raise("Can't find 'rubygems-update' in any repo. Check `gem source list`.") end
返回 gem name
的最新发行版本 specification。
# File rubygems.rb, line 857 def self.latest_spec_for(name) dependency = Gem::Dependency.new name fetcher = Gem::SpecFetcher.fetcher spec_tuples, = fetcher.spec_for_dependency dependency spec, = spec_tuples.last spec end
返回 gem name
的最新发行版本的版本。
# File rubygems.rb, line 878 def self.latest_version_for(name) latest_spec_for(name)&.version end
查找 $LOAD_PATH 中的所有“rubygems_plugin”文件并加载它们。
# File rubygems.rb, line 1082 def self.load_env_plugins load_plugin_files find_files_from_load_path("rubygems_plugin") end
将激活的 gem 路径插入 $LOAD_PATH 的索引。默认情况下,激活的 gem 的路径插入在 site lib 目录之前。
# File rubygems.rb, line 578 def self.load_path_insert_index $LOAD_PATH.each_with_index do |path, i| return i if path.instance_variable_defined?(:@gem_prelude_index) end index = $LOAD_PATH.index RbConfig::CONFIG["sitelibdir"] index || 0 end
在标准位置查找 rubygems 插件文件并加载它们。
# File rubygems.rb, line 1073 def self.load_plugins Gem.path.each do |gem_path| load_plugin_files Gem::Util.glob_files_in_dir("*#{Gem.plugin_suffix_pattern}", plugindir(gem_path)) end end
# File rubygems.rb, line 624 def self.load_safe_marshal return if @safe_marshal_loaded require_relative "rubygems/safe_marshal" @safe_marshal_loaded = true end
加载 YAML,首选 Psych。
# File rubygems.rb, line 611 def self.load_yaml return if @yaml_loaded require "psych" require_relative "rubygems/psych_tree" require_relative "rubygems/safe_yaml" @yaml_loaded = true end
此方法的调用者的调用者的文件名和行号。
depth
是应该向上调用堆栈的层数。
例如,
def a; Gem.location_of_caller
; end a #=> [“x.rb”, 2] #(它会因文件名和行号而异)
def b; c; end def c; Gem.location_of_caller(2)
; end b #=> [“x.rb”, 6] #(它会因文件名和行号而异)
# File rubygems.rb, line 646 def self.location_of_caller(depth = 1) caller[depth] =~ /(.*?):(\d+).*?$/i file = $1 lineno = $2.to_i [file, lineno] end
Ruby 的 Marshal 格式的版本。
# File rubygems.rb, line 657 def self.marshal_version "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}" end
# File rubygems.rb, line 215 def self.needs rs = Gem::RequestSet.new yield rs finish_resolve rs end
使用给定标志打开文件。
# File rubygems.rb, line 793 def self.open_file(path, flags, &block) File.open(path, flags, &block) end
使用给定标志打开文件,并使用 flock 保护访问。
# File rubygems.rb, line 811 def self.open_file_with_flock(path, &block) # read-write mode is used rather than read-only in order to support NFS mode = IO::RDWR | IO::APPEND | IO::CREAT | IO::BINARY mode |= IO::SHARE_DELETE if IO.const_defined?(:SHARE_DELETE) File.open(path, mode) do |io| begin io.flock(File::LOCK_EX) rescue Errno::ENOSYS, Errno::ENOTSUP end yield io end end
使用给定标志打开文件,并使用文件锁保护访问。
# File rubygems.rb, line 800 def self.open_file_with_lock(path, &block) file_lock = "#{path}.lock" open_file_with_flock(file_lock, &block) ensure require "fileutils" FileUtils.rm_f file_lock end
为 Ruby 打包器提供的 gem 命令的默认选项。
此处的选项应结构化为一个字符串数组,其中键为 “gem” 命令名称,值为默认选项字符串。
示例
def self.operating_system_defaults
{ 'install' => '--no-rdoc --no-ri --env-shebang', 'update' => '--no-rdoc --no-ri --env-shebang' }
end
# File rubygems/defaults.rb, line 286 def self.operating_system_defaults {} end
# File rubygems.rb, line 394 def self.path paths.path end
如何分割字符串 Gem
路径。可为特殊的平台重写。
# File rubygems/defaults.rb, line 168 def self.path_separator File::PATH_SEPARATOR end
检索 RubyGems 用于查找文件的 PathSupport
对象。
# File rubygems.rb, line 350 def self.paths @paths ||= Gem::PathSupport.new(ENV) end
从 env
初始化要使用的文件系统路径。env
是一个类似哈希的对象(通常是 ENV),它查询 ‘GEM_HOME’、‘GEM_PATH’ 和 ‘GEM_SPEC_CACHE’ 键。 env
哈希的键应为字符串,哈希的值应为字符串或 nil
。
# File rubygems.rb, line 360 def self.paths=(env) clear_paths target = {} env.each_pair do |k,v| case k when "GEM_HOME", "GEM_PATH", "GEM_SPEC_CACHE" case v when nil, String target[k] = v when Array unless Gem::Deprecate.skip warn <<-EOWARN Array values in the parameter to `Gem.paths=` are deprecated. Please use a String or nil. An Array (#{env.inspect}) was passed in from #{caller[3]} EOWARN end target[k] = v.join File::PATH_SEPARATOR end else target[k] = v end end @paths = Gem::PathSupport.new ENV.to_hash.merge(target) Gem::Specification.dirs = @paths.path end
为 Ruby 实现者提供的 gem 命令的默认选项。
此处的选项应结构化为一个字符串数组,其中键为 “gem” 命令名称,值为默认选项字符串。
示例
def self.platform_defaults
{ 'install' => '--no-rdoc --no-ri --env-shebang', 'update' => '--no-rdoc --no-ri --env-shebang' }
end
# File rubygems/defaults.rb, line 305 def self.platform_defaults {} end
此 RubyGems 支持的平台数组。
# File rubygems.rb, line 671 def self.platforms @platforms ||= [] if @platforms.empty? @platforms = [Gem::Platform::RUBY, Gem::Platform.local] end @platforms end
设置此 RubyGems 支持的平台数组(主要用于测试)。
# File rubygems.rb, line 664 def self.platforms=(platforms) @platforms = platforms end
可 require 的插件后缀的 Glob 模式。
# File rubygems.rb, line 950 def self.plugin_suffix_pattern @plugin_suffix_pattern ||= "_plugin#{suffix_pattern}" end
可 require 的插件后缀的正则表达式。
# File rubygems.rb, line 957 def self.plugin_suffix_regexp @plugin_suffix_regexp ||= /_plugin#{suffix_regexp}\z/ end
rubygems 插件要安装的路径。
# File rubygems.rb, line 308 def self.plugindir(install_dir=Gem.dir) File.join install_dir, "plugins" end
添加一个 post-build 钩子,当 Gem::Installer#install
被调用时,该钩子将被传递一个 Gem::Installer
实例。钩子在 gem 解压和扩展构建之后,但在可执行文件或 gemspec 写入之前被调用。如果钩子返回 false
,则 gem 的文件将被删除,并且安装将中止。
# File rubygems.rb, line 686 def self.post_build(&hook) @post_build_hooks << hook end
添加一个 post-install 钩子,当 Gem::Installer#install
被调用时,该钩子将被传递一个 Gem::Installer
实例
# File rubygems.rb, line 694 def self.post_install(&hook) @post_install_hooks << hook end
添加一个在 Gem::Specification.reset
运行后运行的钩子。
# File rubygems.rb, line 711 def self.post_reset(&hook) @post_reset_hooks << hook end
添加一个 post-uninstall 钩子,当 Gem::Uninstaller#uninstall
被调用时,该钩子将被传递一个 Gem::Uninstaller
实例和卸载的 spec。
# File rubygems.rb, line 720 def self.post_uninstall(&hook) @post_uninstall_hooks << hook end
添加一个 pre-install 钩子,当 Gem::Installer#install
被调用时,该钩子将被传递一个 Gem::Installer
实例。如果钩子返回 false
,则安装将中止。
# File rubygems.rb, line 729 def self.pre_install(&hook) @pre_install_hooks << hook end
添加一个在 Gem::Specification.reset
运行之前运行的钩子。
# File rubygems.rb, line 737 def self.pre_reset(&hook) @pre_reset_hooks << hook end
添加一个 pre-uninstall 钩子,当 Gem::Uninstaller#uninstall
被调用时,该钩子将被传递一个 Gem::Uninstaller
实例和将要卸载的 spec。
# File rubygems.rb, line 746 def self.pre_uninstall(&hook) @pre_uninstall_hooks << hook end
此 RubyGems 安装的目录前缀。如果您的前缀位于标准位置(即,rubygems 安装在您期望的位置),则 prefix 返回 nil。
# File rubygems.rb, line 755 def self.prefix prefix = File.dirname RUBYGEMS_DIR if prefix != File.expand_path(RbConfig::CONFIG["sitelibdir"]) && prefix != File.expand_path(RbConfig::CONFIG["libdir"]) && File.basename(RUBYGEMS_DIR) == "lib" prefix end end
在所有平台上以二进制模式安全地读取文件。
# File rubygems.rb, line 775 def self.read_binary(path) File.binread(path) end
从磁盘刷新可用的 gem。
# File rubygems.rb, line 768 def self.refresh Gem::Specification.reset end
为默认 gem 注册一个 Gem::Specification
。
支持两种规格格式
-
MRI 2.0 样式,其中 spec.files 包含未加前缀的 require 名称。spec 的文件名将按原样注册。
-
新样式,其中 spec.files 包含以 spec.require_paths 中的路径为前缀的文件。在注册 spec 的文件名之前,会去除前缀。未加前缀的文件将被忽略。
# File rubygems.rb, line 1230 def register_default_spec(spec) extended_require_paths = spec.require_paths.map {|f| f + "/" } new_format = extended_require_paths.any? {|path| spec.files.any? {|f| f.start_with? path } } if new_format prefix_group = extended_require_paths.join("|") prefix_pattern = /^(#{prefix_group})/ end spec.files.each do |file| if new_format file = file.sub(prefix_pattern, "") next unless $~ end spec.activate if already_loaded?(file) @path_to_default_spec_map[file] = spec @path_to_default_spec_map[file.sub(suffix_regexp, "")] = spec end end
正在运行的 Ruby 解释器的路径。
# File rubygems.rb, line 828 def self.ruby if @ruby.nil? @ruby = RbConfig.ruby @ruby = "\"#{@ruby}\"" if /\s/.match?(@ruby) end @ruby end
返回一个包含 Ruby 的 API 兼容性版本的字符串
# File rubygems.rb, line 841 def self.ruby_api_version @ruby_api_version ||= target_rbconfig["ruby_version"].dup end
# File rubygems/defaults.rb, line 208 def self.ruby_engine RUBY_ENGINE end
当前正在运行的 Ruby 的 Gem::Version
。
# File rubygems.rb, line 885 def self.ruby_version return @ruby_version if defined? @ruby_version version = RUBY_VERSION.dup if RUBY_PATCHLEVEL == -1 if RUBY_ENGINE == "ruby" desc = RUBY_DESCRIPTION[/\Aruby #{Regexp.quote(RUBY_VERSION)}([^ ]+) /, 1] else desc = RUBY_DESCRIPTION[/\A#{RUBY_ENGINE} #{Regexp.quote(RUBY_ENGINE_VERSION)} \(#{RUBY_VERSION}([^ ]+)\) /, 1] end version << ".#{desc}" if desc end @ruby_version = Gem::Version.new version end
当前正在运行的 RubyGems 的 Gem::Version
# File rubygems.rb, line 904 def self.rubygems_version return @rubygems_version if defined? @rubygems_version @rubygems_version = Gem::Version.new Gem::VERSION end
# File rubygems.rb, line 412 def self.set_target_rbconfig(rbconfig_path) @target_rbconfig = Gem::TargetRbConfig.from_path(rbconfig_path) Gem::Platform.local(refresh: true) Gem.platforms << Gem::Platform.local unless Gem.platforms.include? Gem::Platform.local @target_rbconfig end
此平台是 Solaris 吗?
# File rubygems.rb, line 1040 def self.solaris_platform? RUBY_PLATFORM.include?("solaris") end
返回 Gem.source_date_epoch_string
的值,作为 Time 对象。
这在整个 RubyGems 中用于实现可重现的构建。
# File rubygems.rb, line 1185 def self.source_date_epoch Time.at(source_date_epoch_string.to_i).utc.freeze end
如果设置了 SOURCE_DATE_EPOCH 环境变量,则返回其值。否则,返回首次调用 Gem.source_date_epoch_string
的时间,格式与 SOURCE_DATE_EPOCH 相同。
注意(@duckinator):此实现有点奇怪,因为我们希望
1. Make builds reproducible by default, by having this function always return the same result during a given run. 2. Allow changing ENV['SOURCE_DATE_EPOCH'] at runtime, since multiple tests that set this variable will be run in a single process.
如果您简化此函数,并且很多测试失败,则可能是由于上面的 #2 引起的。
有关 SOURCE_DATE_EPOCH 的详细信息:reproducible-builds.org/specs/source-date-epoch/
# File rubygems.rb, line 1166 def self.source_date_epoch_string # The value used if $SOURCE_DATE_EPOCH is not set. @default_source_date_epoch ||= Time.now.to_i.to_s specified_epoch = ENV["SOURCE_DATE_EPOCH"] # If it's empty or just whitespace, treat it like it wasn't set at all. specified_epoch = nil if !specified_epoch.nil? && specified_epoch.strip.empty? epoch = specified_epoch || @default_source_date_epoch epoch.strip end
返回用于从远程获取 gem 的源的数组。如果源列表为空,则使用 default_sources
。
# File rubygems.rb, line 913 def self.sources source_list = configuration.sources || default_sources @sources ||= Gem::SourceList.from(source_list) end
需要能够在不调用 Gem.sources
.replace 的情况下设置源,因为这将导致无限循环。
DOC:此注释不是关于方法本身的文档,它更像是关于实现的注释。
# File rubygems.rb, line 925 def self.sources=(new_sources) if !new_sources @sources = nil else @sources = Gem::SourceList.from(new_sources) end end
# File rubygems.rb, line 398 def self.spec_cache_dir paths.spec_cache_dir end
用户状态文件的标准位置的路径。
# File rubygems/defaults.rb, line 140 def self.state_file @state_file ||= File.join(Gem.state_home, "gem", "last_update_check") end
用户状态目录的标准位置的路径。
# File rubygems/defaults.rb, line 161 def self.state_home @state_home ||= ENV["XDG_STATE_HOME"] || File.join(Gem.user_home, ".local", "state") end
可 require 的路径后缀的 Glob 模式。
# File rubygems.rb, line 936 def self.suffix_pattern @suffix_pattern ||= "{#{suffixes.join(",")}}" end
可 require 的路径后缀的正则表达式。
# File rubygems.rb, line 943 def self.suffix_regexp @suffix_regexp ||= /#{Regexp.union(suffixes)}\z/ end
可 require 的路径的后缀。
# File rubygems.rb, line 964 def self.suffixes @suffixes ||= ["", ".rb", *%w[DLEXT DLEXT2].map do |key| val = RbConfig::CONFIG[key] next unless val && !val.empty? ".#{val}" end].compact.uniq end
部署目标平台的 RbConfig 对象。
这通常与运行平台相同,但如果您正在进行交叉编译,则可能有所不同。
# File rubygems.rb, line 408 def self.target_rbconfig @target_rbconfig || Gem::TargetRbConfig.for_running_ruby end
使用调试 UI 输出打印提供的代码块运行所需的时间量。
# File rubygems.rb, line 985 def self.time(msg, width = 0, display = Gem.configuration.verbose) now = Time.now value = yield elapsed = Time.now - now ui.say format("%2$*1$s: %3$3.3fs", -width, msg, elapsed) if display value end
尝试激活包含 path
的 gem。如果激活成功或不需要激活(因为它已激活),则返回 true。如果在 gem 中找不到该路径,则返回 false。
# File rubygems.rb, line 190 def self.try_activate(path) # finds the _latest_ version... regardless of loaded specs and their deps # if another gem had a requirement that would mean we shouldn't # activate the latest version, then either it would already be activated # or if it was ambiguous (and thus unresolved) the code in our custom # require will try to activate the more specific version. spec = Gem::Specification.find_by_path path return false unless spec return true if spec.activated? begin spec.activate rescue Gem::LoadError => e # this could fail due to gem dep collisions, go lax spec_by_name = Gem::Specification.find_by_name(spec.name) if spec_by_name.nil? raise e else spec_by_name.activate end end true end
惰性加载 DefaultUserInteraction
并返回默认 UI。
# File rubygems.rb, line 1000 def self.ui require_relative "rubygems/user_interaction" Gem::DefaultUserInteraction.ui end
在 path
中查找 gem 依赖项文件,如果找到,则激活文件中的 gem。如果找不到文件,则会引发 ArgumentError。
如果未提供 path
,则使用 RUBYGEMS_GEMDEPS 环境变量,但如果未找到文件,则不会引发异常。
如果为 path
提供了 '-',则 RubyGems 从当前工作目录向上搜索 gem 依赖项文件(gem.deps.rb、Gemfile、Isolate)并激活找到的第一个文件中的 gem。
您可以在 rubygems 启动时自动运行此操作。要启用,请将 RUBYGEMS_GEMDEPS
环境变量设置为您的 gem 依赖项文件的路径,或设置为 “-” 以在父目录中自动发现。
注意:在多用户系统上启用自动发现可能会导致在不受您控制的目录中使用时执行任意代码。
# File rubygems.rb, line 1106 def self.use_gemdeps(path = nil) raise_exception = path path ||= ENV["RUBYGEMS_GEMDEPS"] return unless path path = path.dup if path == "-" Gem::Util.traverse_parents Dir.pwd do |directory| dep_file = GEM_DEP_FILES.find {|f| File.file?(f) } next unless dep_file path = File.join directory, dep_file break end end unless File.file? path return unless raise_exception raise ArgumentError, "Unable to find gem dependencies file at #{path}" end ENV["BUNDLE_GEMFILE"] ||= File.expand_path(path) require_relative "rubygems/user_interaction" require "bundler" begin Gem::DefaultUserInteraction.use_ui(ui) do Bundler.ui.silence do @gemdeps = Bundler.setup end ensure Gem::DefaultUserInteraction.ui.close end rescue Bundler::BundlerError => e warn e.message warn "You may need to `bundle install` to install missing gems" warn "" end end
使用 Gem.dir
和 Gem.path
的 home
和 paths
值。主要由单元测试使用,以提供环境隔离。
# File rubygems.rb, line 1010 def self.use_paths(home, *paths) paths.flatten! paths.compact! hash = { "GEM_HOME" => home, "GEM_PATH" => paths.empty? ? home : paths.join(File::PATH_SEPARATOR) } hash.delete_if {|_, v| v.nil? } self.paths = hash end
用户主目录下 gems 的路径
# File rubygems/defaults.rb, line 103 def self.user_dir gem_dir = File.join(Gem.user_home, ".gem") gem_dir = File.join(Gem.data_home, "gem") unless File.exist?(gem_dir) parts = [gem_dir, ruby_engine] parts << RbConfig::CONFIG["ruby_version"] unless RbConfig::CONFIG["ruby_version"].empty? File.join parts end
用户的主目录。
# File rubygems/defaults.rb, line 96 def self.user_home @user_home ||= find_home end
这是一个 Windows 平台吗?
# File rubygems.rb, line 1021 def self.win_platform? if @@win_platform.nil? ruby_platform = RbConfig::CONFIG["host_os"] @@win_platform = !WIN_PATTERNS.find {|r| ruby_platform =~ r }.nil? end @@win_platform end
在所有平台上以二进制模式安全地写入文件。
# File rubygems.rb, line 782 def self.write_binary(path, data) File.binwrite(path, data) rescue Errno::ENOSPC # If we ran out of space but the file exists, it's *guaranteed* to be corrupted. File.delete(path) if File.exist?(path) raise end
私有类方法
# File rubygems.rb, line 1321 def already_loaded?(file) $LOADED_FEATURES.any? do |feature_path| feature_path.end_with?(file) && default_gem_load_paths.any? {|load_path_entry| feature_path == "#{load_path_entry}/#{file}" } end end
# File rubygems.rb, line 1327 def default_gem_load_paths @default_gem_load_paths ||= $LOAD_PATH[load_path_insert_index..-1].map do |lp| expanded = File.expand_path(lp) next expanded unless File.exist?(expanded) File.realpath(expanded) end end
查找用户的主目录。
# File rubygems/defaults.rb, line 81 def self.find_home Dir.home.dup rescue StandardError if Gem.win_platform? File.expand_path File.join(ENV["HOMEDRIVE"] || ENV["SystemDrive"], "/") else File.expand_path "/" end end
# File rubygems.rb, line 245 def self.find_spec_for_exe(name, exec_name, requirements) raise ArgumentError, "you must supply exec_name" unless exec_name dep = Gem::Dependency.new name, requirements loaded = Gem.loaded_specs[name] return loaded if loaded && dep.matches_spec?(loaded) specs = dep.matching_specs(true) specs = specs.find_all do |spec| spec.executables.include? exec_name end if exec_name unless spec = specs.first msg = "can't find gem #{dep} with executable #{exec_name}" raise Gem::GemNotFoundException, msg end spec end
私有实例方法
返回从给定 uri
派生的 Gem::URI 对象,该对象可以是 Gem::URI 字符串或现有的 Gem::URI 对象
# Returns a new Gem::URI. uri = Gem::URI('http://github.com/ruby/ruby') # => #<Gem::URI::HTTP http://github.com/ruby/ruby> # Returns the given Gem::URI. Gem::URI(uri) # => #<Gem::URI::HTTP http://github.com/ruby/ruby>
# File rubygems/vendor/uri/lib/uri/common.rb, line 865 def URI(uri) if uri.is_a?(Gem::URI::Generic) uri elsif uri = String.try_convert(uri) Gem::URI.parse(uri) else raise ArgumentError, "bad argument (expected Gem::URI object or Gem::URI string)" end end