模块 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 团队
常量
- DEFAULT_HOST
- GEM_DEP_FILES
- LOADED_SPECS_MUTEX
- MARSHAL_SPEC_DIR
远程存储库上
Marshal
快速 gemspecs 的位置- RDoc
Gem::RDoc
提供方法,用于在 gem 安装后为已安装的 gem 生成RDoc
和 ri 数据。此文件由 RubyGems 1.9 及更高版本自动加载。
- REPOSITORY_DEFAULT_GEM_SUBDIRECTORIES
gem 存储库中默认 gem 的子目录
- REPOSITORY_SUBDIRECTORIES
gem 存储库中的子目录
- RUBYGEMS_DIR
- VERSION
- WIN_PATTERNS
匹配 Windows Ruby 平台的正则表达式
Array
。
属性
RubyGems 发行版(如操作系统包管理器)可以通过将此设置为错误消息来禁用 RubyGems 更新,该错误消息在 gem update –system 时打印给最终用户,而不是实际更新。
RubyGems 是否应该增强内置的 ‘require` 以自动检查所需路径是否出现在已安装的 gem 中,并自动激活它们并将它们添加到 `$LOAD_PATH`。
在 Gem::DependencyInstaller
安装一组 gem 后要运行的钩子列表
GemDependencyAPI 对象,在调用 .use_gemdeps 时设置。它包含 Gemfile 中的所有信息。
已加载的 Gem::Specification
的 Hash
,按名称键控
在 Gem::Installer#install
提取文件并构建扩展后运行的钩子列表。
在 Gem::Installer#install
完成安装后运行的钩子列表。
在运行 Gem::Specification.reset
后运行的钩子列表。
在 Gem::Uninstaller#uninstall
完成安装后运行的钩子列表。
在 Gem::Installer#install
执行任何操作之前运行的钩子列表。
在运行 Gem::Specification.reset
之前运行的钩子列表。
在 Gem::Uninstaller#uninstall
执行任何操作之前运行的钩子列表。
公共类方法
来自已激活 gem 的 +$LOAD_PATH+ 中的路径数量。用于在 require
期间优先考虑 -I
和 ENV['RUBYLIB']
条目。
# File lib/rubygems.rb, line 572 def self.activated_gem_paths @activated_gem_paths ||= 0 end
将路径列表添加到 $LOAD_PATH 的适当位置。
# File lib/rubygems.rb, line 579 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
Find
gem name
的可执行文件的完整路径。如果未给出 exec_name
,则会引发异常,否则将返回指定可执行文件的路径。requirements
允许您指定特定 gem 版本。
# File lib/rubygems.rb, line 235 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 lib/rubygems.rb, line 289 def self.binary_mode "rb" end
安装 gem 可执行文件的路径。
# File lib/rubygems.rb, line 296 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 lib/rubygems/defaults.rb, line 147 def self.cache_home @cache_home ||= ENV["XDG_CACHE_HOME"] || File.join(Gem.user_home, ".cache") end
清除默认的 gem 相关变量。用于测试。
# File lib/rubygems.rb, line 1234 def clear_default_specs @path_to_default_spec_map.clear end
重置 dir
和 path
值。下次请求 dir
或 path
时,将从头开始计算值。这主要用于单元测试,以提供测试隔离。
# File lib/rubygems.rb, line 314 def self.clear_paths @paths = nil @user_home = nil Gem::Specification.reset Gem::Security.reset if defined?(Gem::Security) end
用户 .gemrc 文件的标准位置路径。
# File lib/rubygems/defaults.rb, line 133 def self.config_file @config_file ||= find_config_file end
用户配置目录的标准位置路径。
# File lib/rubygems/defaults.rb, line 114 def self.config_home @config_home ||= ENV["XDG_CONFIG_HOME"] || File.join(Gem.user_home, ".config") end
gem 的标准配置对象。
# File lib/rubygems.rb, line 324 def self.configuration @configuration ||= Gem::ConfigFile.new [] end
使用给定的配置对象(实现 ConfigFile
协议)作为标准配置对象。
# File lib/rubygems.rb, line 332 def self.configuration=(config) @configuration = config end
用户数据目录的标准位置路径。
# File lib/rubygems/defaults.rb, line 154 def self.data_home @data_home ||= ENV["XDG_DATA_HOME"] || File.join(Gem.user_home, ".local", "share") end
二进制文件的默认目录。
# File lib/rubygems/defaults.rb, line 204 def self.default_bindir RbConfig::CONFIG["bindir"] end
默认的签名证书链路径。
# File lib/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 lib/rubygems/defaults.rb, line 37 def self.default_dir @default_dir ||= File.join(RbConfig::CONFIG["rubylibprefix"], "gems", RbConfig::CONFIG["ruby_version"]) end
从 Ruby 的安装名称推断 Ruby 的 –program-prefix 和 –program-suffix。
# File lib/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 lib/rubygems/defaults.rb, line 48 def self.default_ext_dir_for(base_dir) nil end
默认的签名密钥路径。
# File lib/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 lib/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 lib/rubygems/defaults.rb, line 55 def self.default_rubygems_dirs nil # default to standard layout end
一个包含 RubyGems 默认源的 Array
# File lib/rubygems/defaults.rb, line 15 def self.default_sources %w[https://rubygems.org.cn/] end
如果环境中未指定备用值,则要使用的默认规范目录路径
# File lib/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 的规范文件路径。
# File lib/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 lib/rubygems.rb, line 339 def self.deflate(data) require "zlib" Zlib::Deflate.deflate data end
gem 安装的路径。
# File lib/rubygems.rb, line 387 def self.dir paths.home end
添加一个安装后钩子,当 Gem::DependencyInstaller#install
完成时,该钩子将传递一个 Gem::DependencyInstaller
和一个已安装规范列表
# File lib/rubygems.rb, line 683 def self.done_installing(&hook) @done_installing_hooks << hook end
动态库可要求路径的后缀。
# File lib/rubygems.rb, line 948 def self.dynamic_library_suffixes @dynamic_library_suffixes ||= suffixes - [".rb"] end
静默确保 Gem 目录 dir
包含处理默认 gem 的所有正确子目录。如果由于权限问题无法创建目录,我们将静默继续。
如果给定 mode
,则以该模式创建缺失的目录。
永远不会创建世界可写目录。
# File lib/rubygems.rb, line 421 def self.ensure_default_gem_subdirectories(dir = Gem.dir, mode = nil) ensure_subdirectories(dir, mode, REPOSITORY_DEFAULT_GEM_SUBDIRECTORIES) end
静默确保 Gem 目录 dir
包含所有正确的子目录。如果由于权限问题无法创建目录,我们将静默继续。
如果给定 mode
,则以该模式创建缺失的目录。
永远不会创建世界可写目录。
# File lib/rubygems.rb, line 408 def self.ensure_gem_subdirectories(dir = Gem.dir, mode = nil) ensure_subdirectories(dir, mode, REPOSITORY_SUBDIRECTORIES) end
# File lib/rubygems.rb, line 816 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 lib/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
中Find
默认 gem 的 Gem::Specification
# File lib/rubygems.rb, line 1219 def find_default_spec(path) @path_to_default_spec_map[path] end
返回与 glob
匹配的路径列表,gem 可以使用这些路径从其他 gem 中获取功能。例如
Gem.find_files('rdoc/discover').each do |path| load path end
如果 check_load_path
为真(默认值),则 find_files
还会搜索 $LOAD_PATH 中的文件以及 gem。
请注意,find_files
将返回所有文件,即使它们来自同一 gem 的不同版本。另请参阅 find_latest_files
# File lib/rubygems.rb, line 472 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.map {|spec| spec.matches_for_glob("#{glob}#{Gem.suffix_pattern}") }.flatten # $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
为真(默认值),则 find_latest_files
还会搜索 $LOAD_PATH 中的文件以及 gem。
与 find_files
不同,find_latest_files
只会返回来自 gem 最新版本的那些文件。
# File lib/rubygems.rb, line 509 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).map {|spec| spec.matches_for_glob("#{glob}#{Gem.suffix_pattern}") }.flatten # $LOAD_PATH might contain duplicate entries or reference # the spec dirs directly, so we prune. files.uniq! if check_load_path files end
从 path
中Find
未解析的默认 gem 的 Gem::Specification
# File lib/rubygems.rb, line 1226 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 lib/rubygems.rb, line 220 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
获取默认的 RubyGems API 主机。这通常是 https://rubygems.org.cn
。
# File lib/rubygems.rb, line 544 def self.host @host ||= Gem::DEFAULT_HOST end
Set
默认的 RubyGems API 主机。
# File lib/rubygems.rb, line 550 def self.host=(host) @host = host end
顶级安装帮助方法。允许您以交互方式安装 gem
% irb >> Gem.install "minitest" Fetching: minitest-5.14.0.gem (100%) => [#<Gem::Specification:0x1013b4528 @name="minitest", ...>]
# File lib/rubygems.rb, line 533 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 lib/rubygems.rb, line 1004 def self.java_platform? RUBY_PLATFORM == "java" end
返回 RubyGems 的最新发布版本。
# File lib/rubygems.rb, line 841 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
的最新发布版本规范。
# File lib/rubygems.rb, line 828 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 lib/rubygems.rb, line 849 def self.latest_version_for(name) latest_spec_for(name)&.version end
在 $LOAD_PATH 中查找所有 ‘rubygems_plugin’ 文件并加载它们。
# File lib/rubygems.rb, line 1046 def self.load_env_plugins load_plugin_files find_files_from_load_path("rubygems_plugin") end
将激活的 gem 路径插入 $LOAD_PATH 的索引。默认情况下,激活的 gem 的路径将插入到 site lib 目录之前。
# File lib/rubygems.rb, line 558 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 lib/rubygems.rb, line 1037 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 lib/rubygems.rb, line 604 def self.load_safe_marshal return if @safe_marshal_loaded require_relative "rubygems/safe_marshal" @safe_marshal_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 lib/rubygems.rb, line 626 def self.location_of_caller(depth = 1) caller[depth] =~ /(.*?):(\d+).*?$/i file = $1 lineno = $2.to_i [file, lineno] end
您 Ruby 版本的 Marshal
格式。
# File lib/rubygems.rb, line 637 def self.marshal_version "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}" end
# File lib/rubygems.rb, line 212 def self.needs rs = Gem::RequestSet.new yield rs finish_resolve rs end
使用给定的标志打开文件,并在 Windows 上使用 flock 保护访问权限。
# File lib/rubygems.rb, line 776 def self.open_file(path, flags, &block) File.open(path, flags) do |io| if !java_platform? && win_platform? begin io.flock(File::LOCK_EX) rescue Errno::ENOSYS, Errno::ENOTSUP end end yield io end rescue Errno::ENOLCK # NFS if Thread.main != Thread.current raise else File.open(path, flags) do |io| yield io end end 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 lib/rubygems/defaults.rb, line 286 def self.operating_system_defaults {} end
# File lib/rubygems.rb, line 391 def self.path paths.path end
如何分割 String
Gem 路径。对于奇特的平台可以覆盖。
# File lib/rubygems/defaults.rb, line 168 def self.path_separator File::PATH_SEPARATOR end
检索 RubyGems 用于查找文件的 PathSupport
对象。
# File lib/rubygems.rb, line 347 def self.paths @paths ||= Gem::PathSupport.new(ENV) end
从 env
初始化要使用的文件系统路径。env
是一个类似哈希的对象(通常是 ENV
),它被查询以获取“GEM_HOME”、“GEM_PATH”和“GEM_SPEC_CACHE”键。env
哈希的键应该是字符串,哈希的值应该是字符串或 nil
。
# File lib/rubygems.rb, line 357 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 lib/rubygems/defaults.rb, line 305 def self.platform_defaults {} end
此 RubyGems 支持的平台的 Array
。
# File lib/rubygems.rb, line 651 def self.platforms @platforms ||= [] if @platforms.empty? @platforms = [Gem::Platform::RUBY, Gem::Platform.local] end @platforms end
此 RubyGems 支持的平台的 Set
数组(主要用于测试)。
# File lib/rubygems.rb, line 644 def self.platforms=(platforms) @platforms = platforms end
可要求插件后缀的 glob 模式。
# File lib/rubygems.rb, line 921 def self.plugin_suffix_pattern @plugin_suffix_pattern ||= "_plugin#{suffix_pattern}" end
可要求插件后缀的 Regexp
。
# File lib/rubygems.rb, line 928 def self.plugin_suffix_regexp @plugin_suffix_regexp ||= /_plugin#{suffix_regexp}\z/ end
rubygems 插件要安装的路径。
# File lib/rubygems.rb, line 305 def self.plugindir(install_dir=Gem.dir) File.join install_dir, "plugins" end
添加一个构建后钩子,当调用 Gem::Installer
的 Gem::Installer#install
方法时,该钩子将传递一个 Gem::Installer
实例。该钩子在 gem 解压和扩展构建完成,但可执行文件或 gemspec 尚未写入之前调用。如果钩子返回 false
,则 gem 的文件将被删除,安装将被中止。
# File lib/rubygems.rb, line 666 def self.post_build(&hook) @post_build_hooks << hook end
添加一个安装后钩子,当调用 Gem::Installer
的 Gem::Installer#install
方法时,该钩子将传递一个 Gem::Installer
实例。
# File lib/rubygems.rb, line 674 def self.post_install(&hook) @post_install_hooks << hook end
添加一个钩子,该钩子将在运行 Gem::Specification.reset
之后运行。
# File lib/rubygems.rb, line 691 def self.post_reset(&hook) @post_reset_hooks << hook end
添加一个卸载后钩子,当调用 Gem::Uninstaller
的 Gem::Uninstaller#uninstall
方法时,该钩子将传递一个 Gem::Uninstaller
实例和被卸载的 spec。
# File lib/rubygems.rb, line 700 def self.post_uninstall(&hook) @post_uninstall_hooks << hook end
添加一个安装前钩子,当调用 Gem::Installer
的 Gem::Installer#install
方法时,该钩子将传递一个 Gem::Installer
实例。如果钩子返回 false
,则安装将被中止。
# File lib/rubygems.rb, line 709 def self.pre_install(&hook) @pre_install_hooks << hook end
添加一个钩子,该钩子将在运行 Gem::Specification.reset
之前运行。
# File lib/rubygems.rb, line 717 def self.pre_reset(&hook) @pre_reset_hooks << hook end
添加一个卸载前钩子,当调用 Gem::Uninstaller
的 Gem::Uninstaller#uninstall
方法时,该钩子将传递一个 Gem::Uninstaller
实例和将要被卸载的 spec。
# File lib/rubygems.rb, line 726 def self.pre_uninstall(&hook) @pre_uninstall_hooks << hook end
此 RubyGems 安装所在的目录前缀。如果您的前缀位于标准位置(即,rubygems 安装在您期望的位置),则 prefix 返回 nil。
# File lib/rubygems.rb, line 735 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 lib/rubygems.rb, line 755 def self.read_binary(path) open_file(path, "rb+", &:read) rescue Errno::EACCES, Errno::EROFS open_file(path, "rb", &:read) end
从磁盘刷新可用的 gems。
# File lib/rubygems.rb, line 748 def self.refresh Gem::Specification.reset end
为默认 gem 注册一个 Gem::Specification
。
支持两种格式的规范:
-
MRI 2.0 风格,其中 spec.files 包含未加前缀的 require 名称。spec 的文件名将按原样注册。
-
新风格,其中 spec.files 包含以 spec.require_paths 中的路径为前缀的文件。在注册 spec 的文件名之前,会剥离前缀。未加前缀的文件将被忽略。
# File lib/rubygems.rb, line 1194 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 lib/rubygems.rb, line 799 def self.ruby if @ruby.nil? @ruby = RbConfig.ruby @ruby = "\"#{@ruby}\"" if /\s/.match?(@ruby) end @ruby end
返回一个包含 Ruby 的 API 兼容版本的 String
。
# File lib/rubygems.rb, line 812 def self.ruby_api_version @ruby_api_version ||= RbConfig::CONFIG["ruby_version"].dup end
# File lib/rubygems/defaults.rb, line 208 def self.ruby_engine RUBY_ENGINE end
当前运行的 Ruby 的 Gem::Version
。
# File lib/rubygems.rb, line 856 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 lib/rubygems.rb, line 875 def self.rubygems_version return @rubygems_version if defined? @rubygems_version @rubygems_version = Gem::Version.new Gem::VERSION end
此平台是否为 Solaris?
# File lib/rubygems.rb, line 1011 def self.solaris_platform? RUBY_PLATFORM.include?("solaris") end
返回 Gem.source_date_epoch_string
的值,作为 Time
对象。
这在整个 RubyGems 中用于启用可重复构建。
# File lib/rubygems.rb, line 1149 def self.source_date_epoch Time.at(source_date_epoch_string.to_i).utc.freeze end
如果设置了 SOURCE_DATE_EPOCH 环境变量,则返回其值。否则,返回与 SOURCE_DATE_EPOCH 格式相同的 Gem.source_date_epoch_string
首次调用时间。
注意(@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 lib/rubygems.rb, line 1130 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 源的 Array
。如果源列表为空,则使用 default_sources
。
# File lib/rubygems.rb, line 884 def self.sources source_list = configuration.sources || default_sources @sources ||= Gem::SourceList.from(source_list) end
需要能够设置源,而无需调用 Gem.sources
.replace,因为这会导致无限循环。
DOC: 此注释不是关于方法本身的文档,它更像是关于实现的代码注释。
# File lib/rubygems.rb, line 896 def self.sources=(new_sources) if !new_sources @sources = nil else @sources = Gem::SourceList.from(new_sources) end end
# File lib/rubygems.rb, line 395 def self.spec_cache_dir paths.spec_cache_dir end
用户状态文件标准位置的路径。
# File lib/rubygems/defaults.rb, line 140 def self.state_file @state_file ||= File.join(Gem.state_home, "gem", "last_update_check") end
用户状态目录标准位置的路径。
# File lib/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 lib/rubygems.rb, line 907 def self.suffix_pattern @suffix_pattern ||= "{#{suffixes.join(",")}}" end
可 require 路径后缀的 Regexp
。
# File lib/rubygems.rb, line 914 def self.suffix_regexp @suffix_regexp ||= /#{Regexp.union(suffixes)}\z/ end
可 require 路径的后缀。
# File lib/rubygems.rb, line 935 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
使用调试 UI 输出打印提供的代码块运行所需的时间。
# File lib/rubygems.rb, line 956 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 lib/rubygems.rb, line 187 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 lib/rubygems.rb, line 971 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),并在找到第一个文件时激活其中的 gems。
你可以在 rubygems 启动时自动执行此操作。要启用此功能,请将 RUBYGEMS_GEMDEPS
环境变量设置为你的 gem 依赖文件路径或 “-” 以在父目录中自动发现。
注意:在多用户系统上启用自动发现可能会导致在不受你控制的目录中使用时执行任意代码。
# File lib/rubygems.rb, line 1070 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
使用 home
和 paths
值为 Gem.dir
和 Gem.path
。主要用于单元测试以提供环境隔离。
# File lib/rubygems.rb, line 981 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 lib/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
用户的 home 目录。
# File lib/rubygems/defaults.rb, line 96 def self.user_home @user_home ||= find_home end
这是一个 Windows 平台吗?
# File lib/rubygems.rb, line 992 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 lib/rubygems.rb, line 763 def self.write_binary(path, data) open_file(path, "wb") do |io| io.write data end 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 lib/rubygems.rb, line 1285 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 lib/rubygems.rb, line 1291 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
查找用户的 home 目录。
# File lib/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 lib/rubygems.rb, line 242 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