class Gem::RequestSet
RequestSet
将激活一组依赖项的请求分组。
nokogiri = Gem::Dependency.new 'nokogiri', '~> 1.6' pg = Gem::Dependency.new 'pg', '~> 0.14' set = Gem::RequestSet.new nokogiri, pg requests = set.resolve p requests.map { |r| r.full_name } #=> ["nokogiri-1.6.0", "mini_portile-0.5.1", "pg-0.17.0"]
属性
always_install[RW]
即使已安装也始终安装的 gem 数组
dependencies[R]
development[RW]
development_shallow[RW]
如果只想安装直接开发依赖项,则设置为 true。
errors[R]
在解析期间获取 gem 时发生的错误。
ignore_dependencies[RW]
如果为 true,则不执行依赖项解析,只安装请求的 gem。
prerelease[RW]
如果为 true,则允许依赖项匹配预发布 gem。
remote[RW]
如果为 false,则不使用远程集来解析 gem。
soft_missing[RW]
将缺失的依赖项视为静默错误
source_set[R]
通过 load_gemdeps 导入的源 gem 集。
公共类方法
new(*deps) { |self| ... } 单击以切换源代码
为 Gem::Dependency
对象列表 deps
创建一个 RequestSet
。然后,您可以 resolve
和 install
已解析的依赖项列表。
nokogiri = Gem::Dependency.new 'nokogiri', '~> 1.6' pg = Gem::Dependency.new 'pg', '~> 0.14' set = Gem::RequestSet.new nokogiri, pg
# File rubygems/request_set.rb, line 94 def initialize(*deps) @dependencies = deps @always_install = [] @conservative = false @dependency_names = {} @development = false @development_shallow = false @errors = [] @git_set = nil @ignore_dependencies = false @install_dir = Gem.dir @prerelease = false @remote = true @requests = [] @sets = [] @soft_missing = false @sorted_requests = nil @specs = nil @vendor_set = nil @source_set = nil yield self if block_given? end
公共实例方法
gem(name, *reqs) 单击以切换源代码
声明需要名为 name
且具有 reqs
要求的 gem。
# File rubygems/request_set.rb, line 122 def gem(name, *reqs) if dep = @dependency_names[name] dep.requirement.concat reqs else dep = Gem::Dependency.new name, *reqs @dependency_names[name] = dep @dependencies << dep end end
import(deps) 单击以切换源代码
将 deps
Gem::Dependency
对象添加到该集合。
# File rubygems/request_set.rb, line 135 def import(deps) @dependencies.concat deps end
install(options) { |request, installer| ... } 单击以切换源代码
使用 Gem::Installer
options
为此 RequestSet
安装 gem。
如果给定了 block
,则会产生一个激活 request
和 installer
。如果已安装与请求匹配的 gem,则 installer
将为 nil
。
# File rubygems/request_set.rb, line 146 def install(options, &block) # :yields: request, installer if dir = options[:install_dir] requests = install_into dir, false, options, &block return requests end @prerelease = options[:prerelease] requests = [] download_queue = Thread::Queue.new # Create a thread-safe list of gems to download sorted_requests.each do |req| download_queue << req end # Create N threads in a pool, have them download all the gems threads = Array.new(Gem.configuration.concurrent_downloads) do # When a thread pops this item, it knows to stop running. The symbol # is queued here so that there will be one symbol per thread. download_queue << :stop Thread.new do # The pop method will block waiting for items, so the only way # to stop a thread from running is to provide a final item that # means the thread should stop. while req = download_queue.pop break if req == :stop req.spec.download options unless req.installed? end end end # Wait for all the downloads to finish before continuing threads.each(&:value) # Install requested gems after they have been downloaded sorted_requests.each do |req| if req.installed? req.spec.spec.build_extensions if @always_install.none? {|spec| spec == req.spec.spec } yield req, nil if block_given? next end end spec = begin req.spec.install options do |installer| yield req, installer if block_given? end rescue Gem::RuntimeRequirementNotMetError => e suggestion = "There are no versions of #{req.request} compatible with your Ruby & RubyGems" suggestion += ". Maybe try installing an older version of the gem you're looking for?" unless @always_install.include?(req.spec.spec) e.suggestion = suggestion raise end requests << spec end return requests if options[:gemdeps] install_hooks requests, options requests end
install_from_gemdeps(options, &block) 单击以切换源代码
从 options
中的 :gemdeps
选项中的 gem 依赖文件安装,如 install
中那样产生 block
。
如果在 options
中给定了 :without_groups
,则不使用 gem 依赖文件中的这些组。有关其他 options
,请参阅 Gem::Installer
。
# File rubygems/request_set.rb, line 222 def install_from_gemdeps(options, &block) gemdeps = options[:gemdeps] @install_dir = options[:install_dir] || Gem.dir @prerelease = options[:prerelease] @remote = options[:domain] != :local @conservative = true if options[:conservative] gem_deps_api = load_gemdeps gemdeps, options[:without_groups], true resolve if options[:explain] puts "Gems to install:" sorted_requests.each do |spec| puts " #{spec.full_name}" end if Gem.configuration.really_verbose @resolver.stats.display end else installed = install options, &block if options.fetch :lock, true lockfile = Gem::RequestSet::Lockfile.build self, gemdeps, gem_deps_api.dependencies lockfile.write end installed end end
install_hooks(requests, options) 单击以切换源代码
在已安装的 gem 上调用钩子
# File rubygems/request_set.rb, line 298 def install_hooks(requests, options) specs = requests.map do |request| case request when Gem::Resolver::ActivationRequest then request.spec.spec else request end end require_relative "dependency_installer" inst = Gem::DependencyInstaller.new options inst.installed_gems.replace specs Gem.done_installing_hooks.each do |hook| hook.call inst, specs end unless Gem.done_installing_hooks.empty? end
install_into(dir, force = true, options = {}) { |request, nil| ... } 单击以切换源代码
# File rubygems/request_set.rb, line 257 def install_into(dir, force = true, options = {}) gem_home = ENV["GEM_HOME"] ENV["GEM_HOME"] = dir existing = force ? [] : specs_in(dir) existing.delete_if {|s| @always_install.include? s } dir = File.expand_path dir installed = [] options[:development] = false options[:install_dir] = dir options[:only_install_dir] = true @prerelease = options[:prerelease] sorted_requests.each do |request| spec = request.spec if existing.find {|s| s.full_name == spec.full_name } yield request, nil if block_given? next end spec.install options do |installer| yield request, installer if block_given? end installed << request end install_hooks installed, options installed ensure ENV["GEM_HOME"] = gem_home end
load_gemdeps(path, without_groups = [], installing = false) 单击以切换源代码
加载依赖项管理文件。
# File rubygems/request_set.rb, line 320 def load_gemdeps(path, without_groups = [], installing = false) @git_set = Gem::Resolver::GitSet.new @vendor_set = Gem::Resolver::VendorSet.new @source_set = Gem::Resolver::SourceSet.new @git_set.root_dir = @install_dir lock_file = "#{File.expand_path(path)}.lock" begin tokenizer = Gem::RequestSet::Lockfile::Tokenizer.from_file lock_file parser = tokenizer.make_parser self, [] parser.parse rescue Errno::ENOENT end gf = Gem::RequestSet::GemDependencyAPI.new self, path gf.installing = installing gf.without_groups = without_groups if without_groups gf.load end
resolve(set = Gem::Resolver::BestSet.new) 单击以切换源代码
解析请求的依赖项,并返回要激活的 Specification 对象的数组。
# File rubygems/request_set.rb, line 387 def resolve(set = Gem::Resolver::BestSet.new) @sets << set @sets << @git_set @sets << @vendor_set @sets << @source_set set = Gem::Resolver.compose_sets(*@sets) set.remote = @remote set.prerelease = @prerelease resolver = Gem::Resolver.new @dependencies, set resolver.development = @development resolver.development_shallow = @development_shallow resolver.ignore_dependencies = @ignore_dependencies resolver.soft_missing = @soft_missing if @conservative installed_gems = {} Gem::Specification.find_all do |spec| (installed_gems[spec.name] ||= []) << spec end resolver.skip_gems = installed_gems end @resolver = resolver @requests = resolver.resolve @errors = set.errors @requests end
resolve_current() 单击以切换源代码
针对通过 Gem.path
可用的 gem 解析请求的依赖项,并返回要激活的 Specification 对象的数组。
# File rubygems/request_set.rb, line 424 def resolve_current resolve Gem::Resolver::CurrentSet.new end
sorted_requests() 单击以切换源代码
# File rubygems/request_set.rb, line 428 def sorted_requests @sorted_requests ||= strongly_connected_components.flatten end
specs() 单击以切换源代码
# File rubygems/request_set.rb, line 432 def specs @specs ||= @requests.map(&:full_spec) end
specs_in(dir) 单击以切换源代码
# File rubygems/request_set.rb, line 436 def specs_in(dir) Gem::Util.glob_files_in_dir("*.gemspec", File.join(dir, "specifications")).map do |g| Gem::Specification.load g end end