module Bundler::Plugin::API::Source
此类提供了构建源插件的基础。这里的所有方法都是构建源插件所必需的(除了“uri_hash`、`gem_install_dir`;它们是辅助方法)。
尽可能为方法提供了默认值,这些默认值有望能够工作。但是,所有源插件都必须覆盖“fetch_gemspec_files”和“install”。也没有为“remote!”、“cache!”和“unlock!”提供默认值。
默认值应适用于大多数情况,但仍然可以(最好应该)根据插件的需要安全地覆盖它们(只要它们的行为符合预期)。在覆盖“initialize”时,您应该首先调用 super。
如果需要,插件应覆盖“hash”、“==”和“eql?”方法,以便能够匹配表示相同源的对象,但这些对象可能在不同的情况下创建(例如,从 Gemfile 和 lockfile 中)。默认值仅检查类和 URI,但详细的源插件可能需要更多的比较(例如,对分支或标记进行 Git 检查)。
@!attribute [r] uri
@return [String] the remote specified with `source` block in Gemfile
@!attribute [r] options
@return [String] options passed during initialization (either from lockfile or Gemfile)
@!attribute [r] name
@return [String] name that can be used to uniquely identify a source
@!attribute [rw] dependency_names
@return [Array<String>] Names of dependencies that the source should try to resolve. It is not necessary to use this list internally. This is present to be compatible with `Definition` and is used by rubygems source.
属性
公共类方法
# File bundler/plugin/api/source.rb, line 45 def initialize(opts) @options = opts @dependency_names = [] @uri = opts["uri"] @type = opts["type"] @name = opts["name"] || "#{@type} at #{@uri}" @checksum_store = Checksum::Store.new end
公共实例方法
这将检查两个源对象是否代表同一个源。
比较应仅在可以从 Gemfile 传递的选项中推断出的属性上进行,而不是在用于将 gem 固定到特定版本的属性上进行(例如,Git 源应在分支和标记上进行比较,而不是在提交哈希上)。
源对象是从 Gemfile 和 lockfile 中构造的。为了使源收敛,它们必须匹配。
这同样适用于“eql?”和“hash”
# File bundler/plugin/api/source.rb, line 214 def ==(other) other.is_a?(self.class) && uri == other.uri end
由定义使用。
注意:如果您不知道自己在做什么,请不要覆盖。
# File bundler/plugin/api/source.rb, line 259 def add_dependency_names(names) @dependencies |= Array(names) end
当调用cache
时,插件期望缓存 gem 的目录名称。
此名称也与缓存中的目录匹配以进行修剪
这由“app_cache_path”使用
# File bundler/plugin/api/source.rb, line 178 def app_cache_dirname base_name = File.basename(Gem::URI.parse(uri).normalize.path) "#{base_name}-#{uri_hash}" end
插件应缓存 gem 的完整路径,以便以后可以安装。
注意:如果您不知道自己在做什么,请不要覆盖。
# File bundler/plugin/api/source.rb, line 238 def app_cache_path(custom_path = nil) @app_cache_path ||= Bundler.app_cache(custom_path).join(app_cache_dirname) end
在缓存期间调用此方法,以保存源可以解析到的 gem 的副本,该副本由“app_cache_app”提供的路径提供,以便可以从缓存中重新安装它们,而无需查询远程(即远程的替代方法)。
它与应用程序一起存储,并且当调用“cached!”时,源插件应尝试仅从此缓存中提供规范和安装。
此缓存与可以在“cache_path”(来自API
)的子路径下完成的内部缓存不同。这可以被认为是 bundler 的缓存。
# File bundler/plugin/api/source.rb, line 194 def cache(spec, custom_path = nil) new_cache_path = app_cache_path(custom_path) FileUtils.rm_rf(new_cache_path) FileUtils.cp_r(install_path, new_cache_path) FileUtils.rm_rf(app_cache_path.join(".git")) FileUtils.touch(app_cache_path.join(".bundlecache")) end
设置内部表示以从应用程序缓存中获取 gem/规范。
当调用此方法时,源应尝试从“app_cache_path”提供的路径中获取规范并进行安装。
# File bundler/plugin/api/source.rb, line 162 def cached! end
注意:如果您不知道自己在做什么,请不要覆盖。
# File bundler/plugin/api/source.rb, line 264 def can_lock?(spec) spec.source == self end
@private 此API
关于源可能不稳定,并且目前我们希望插件在“#specs”中下载所有规范,因此我们实现该方法是为了兼容性目的,并将其保持未记录(并且不支持)覆盖它)
# File bundler/plugin/api/source.rb, line 318 def double_check_for(*); end
默认的“spec”方法使用此方法来构造此源插件可以安装的 gem 和版本的 Specification 对象。
注意:如果覆盖了 spec 方法,则此函数不是必需的
@return [Array<String>] 可以安装的 gem 的 gemspec 文件的路径
be installed
# File bundler/plugin/api/source.rb, line 62 def fetch_gemspec_files [] end
注意:如果您不知道自己在做什么,请不要覆盖。
# File bundler/plugin/api/source.rb, line 300 def gem_install_dir Bundler.install_path end
当覆盖“hash”时,请保留“==”方法的文档字符串中提到的行为,即,通过上述比较相等的两个方法应具有相同的哈希值。
# File bundler/plugin/api/source.rb, line 225 def hash [self.class, uri].hash end
注意:如果您不知道自己在做什么,请不要覆盖。
# File bundler/plugin/api/source.rb, line 291 def include?(other) other == self end
在适当的路径下安装由规范指定的 gem。“install_path”提供了一个足够好的默认值,如果源只能满足一个 gem,但不是绑定的。
@return [String] 安装后消息(如果有)
# File bundler/plugin/api/source.rb, line 82 def install(spec, opts) raise MalformattedPlugin, "Source plugins need to override the install method." end
安装单个 gem 的默认安装路径。如果源服务多个 gem,则它的用途不大,并且源应使用其自己的路径。
# File bundler/plugin/api/source.rb, line 107 def install_path @install_path ||= begin base_name = File.basename(Gem::URI.parse(uri).normalize.path) gem_install_dir.join("#{base_name}-#{uri_hash[0..11]}") end end
一个辅助方法,如果内部未使用,则不是必需的。
# File bundler/plugin/api/source.rb, line 230 def installed? File.directory?(install_path) end
设置内部表示以在本地获取 gem/规范。
调用此方法后,源应尝试从本地系统获取规范并进行安装。
# File bundler/plugin/api/source.rb, line 148 def local! end
要保存在 lockfile 中的选项,以便源插件稍后能够检出相同版本的 gem。
从 lock 文件创建源插件时会传递这些选项。
@return [Hash]
# File bundler/plugin/api/source.rb, line 73 def options_to_lock {} end
它为提供的规范构建扩展,生成 bin 并安装它们。
它依赖于“spec.loaded_from”来获取 full_gem_path。源插件应设置该属性。
在插件将 gem 放置在正确的安装位置后,应在“install”中调用此方法。
它还会运行Gem
钩子“pre_install”、“post_build”和“post_install”
注意:如果您不知道自己在做什么,请不要覆盖。
# File bundler/plugin/api/source.rb, line 98 def post_install(spec, disable_exts = false) opts = { env_shebang: false, disable_extensions: disable_exts } installer = Bundler::Source::Path::Installer.new(spec, opts) installer.post_install end
设置内部表示以从远程获取 gem/规范。
调用此方法后,源应尝试从远程路径获取规范并进行安装。
# File bundler/plugin/api/source.rb, line 155 def remote! end
它用于获取 full_gem_path。
spec 的 loaded_from 路径将根据此路径展开,以获取 full_gem_path
注意:如果您不知道自己在做什么,请不要覆盖。
# File bundler/plugin/api/source.rb, line 309 def root Bundler.root end
由定义使用。
注意:如果您不知道自己在做什么,请不要覆盖。
# File bundler/plugin/api/source.rb, line 252 def spec_names specs.spec_names end
解析 gemspec 文件以查找可以由源满足的 gem 的规范。
需要记住的几个重要点
- If the gems are not installed then it shall return specs for all the gems it can satisfy - If gem is installed (that is to be detected by the plugin itself) then it shall return at least the specs that are installed. - The `loaded_from` for each of the specs shall be correct (it is used to find the load path)
@return [Bundler::Index] 包含规范的索引
# File bundler/plugin/api/source.rb, line 128 def specs files = fetch_gemspec_files Bundler::Index.build do |index| files.each do |file| next unless spec = Bundler.load_gemspec(file) spec.installed_by_version = Gem::VERSION spec.source = self Bundler.rubygems.validate(spec) index << spec end end end
生成要输入到 lockfile 中的内容。保存类型和远程,还会调用“options_to_lock”。
Plugin
应使用“options_to_lock”将信息保存在 lockfile 中,而不是覆盖此信息。
注意:如果您不知道自己在做什么,请不要覆盖。
# File bundler/plugin/api/source.rb, line 275 def to_lock out = String.new("#{LockfileParser::PLUGIN}\n") out << " remote: #{@uri}\n" out << " type: #{@type}\n" options_to_lock.each do |opt, value| out << " #{opt}: #{value}\n" end out << " specs:\n" end
# File bundler/plugin/api/source.rb, line 285 def to_s "plugin source for #{@type} with uri #{@uri}" end
调用此方法以更新规范和安装。
如果源插件是从 lockfile 加载的还是以其他方式加载的,它应刷新缓存/规范(例如,git 源可以进行新的克隆)。
# File bundler/plugin/api/source.rb, line 169 def unlock! end
由定义使用。
注意:如果您不知道自己在做什么,请不要覆盖。
# File bundler/plugin/api/source.rb, line 245 def unmet_deps specs.unmet_dependency_names end
# File bundler/plugin/api/source.rb, line 295 def uri_hash SharedHelpers.digest(:SHA1).hexdigest(uri) end