class Gem::Resolver
给定一组 Gem::Dependency
对象作为 needed
,以及通过 set
查询可用规范集的方法,计算一组 ActivationRequest
对象,这些对象指示应激活以满足所有要求的所有规范。
常量
- DEBUG_RESOLVER
如果设置了
DEBUG_RESOLVER
环境变量,则会为解析器启用调试模式。这将在解析一组依赖项时显示有关解析器状态的信息。- SINGLE_POSSIBILITY_CONSTRAINT_PENALTY
属性
development[RW]
如果应考虑所有开发依赖项,则将 Set
设置为 true。
development_shallow[RW]
如果应考虑直接开发依赖项,则将 Set
设置为 true。
ignore_dependencies[RW]
当为 true 时,不会查找所请求 gem 的任何依赖项。
skip_gems[RW]
要跳过解析的 gem 的哈希表。以 gem 名称作为键,以 gem 规范数组作为值。
soft_missing[RW]
stats[R]
无法在配置的源中找到的依赖项列表。
公共类方法
compose_sets(*sets) 点击以切换源代码
将 sets
组合成一个 ComposedSet
,允许以统一的方式进行规范查找。如果其中一个 sets
本身是一个 ComposedSet
,则它的集将被展平到结果 ComposedSet
中。
# File rubygems/resolver.rb, line 59 def self.compose_sets(*sets) sets.compact! sets = sets.flat_map do |set| case set when Gem::Resolver::BestSet then set when Gem::Resolver::ComposedSet then set.sets else set end end case sets.length when 0 then raise ArgumentError, "one set in the composition must be non-nil" when 1 then sets.first else Gem::Resolver::ComposedSet.new(*sets) end end
for_current_gems(needed) 点击以切换源代码
创建一个 Resolver
,仅针对 needed
依赖项的已安装 gem 进行查询。
# File rubygems/resolver.rb, line 87 def self.for_current_gems(needed) new needed, Gem::Resolver::CurrentSet.new end
new(needed, set = nil) 点击以切换源代码
创建 Resolver
对象,它将从 needed
Dependency 对象开始解析树。
set
是一个对象,它提供在哪里查找满足依赖项的规范。默认情况下,这是 IndexSet
,它将查询 rubygems.org。
# File rubygems/resolver.rb, line 99 def initialize(needed, set = nil) @set = set || Gem::Resolver::IndexSet.new @needed = needed @development = false @development_shallow = false @ignore_dependencies = false @skip_gems = {} @soft_missing = false @stats = Gem::Resolver::Stats.new end
公共实例方法
allow_missing?(dependency) 点击以切换源代码
# File rubygems/resolver.rb, line 271 def allow_missing?(dependency) @soft_missing end
debug?() 点击以切换源代码
# File rubygems/resolver.rb, line 176 def debug? DEBUG_RESOLVER end
dependencies_for(specification) 点击以切换源代码
# File rubygems/resolver.rb, line 252 def dependencies_for(specification) return [] if @ignore_dependencies spec = specification.spec requests(spec, specification) end
name_for(dependency) 点击以切换源代码
# File rubygems/resolver.rb, line 267 def name_for(dependency) dependency.name end
output() 点击以切换源代码
# File rubygems/resolver.rb, line 172 def output @output ||= debug? ? $stdout : File.open(IO::NULL, "w") end
requirement_satisfied_by?(requirement, activated, spec) 点击以切换源代码
# File rubygems/resolver.rb, line 258 def requirement_satisfied_by?(requirement, activated, spec) matches_spec = requirement.matches_spec? spec return matches_spec if @soft_missing matches_spec && spec.spec.required_ruby_version.satisfied_by?(Gem.ruby_version) && spec.spec.required_rubygems_version.satisfied_by?(Gem.rubygems_version) end
resolve() 点击以切换源代码
开始解析!返回一个 ActivationRequest
对象数组。
# File rubygems/resolver.rb, line 185 def resolve Gem::Molinillo::Resolver.new(self, self).resolve(@needed.map {|d| DependencyRequest.new d, nil }).tsort.filter_map(&:payload) rescue Gem::Molinillo::VersionConflict => e conflict = e.conflicts.values.first raise Gem::DependencyResolutionError, Conflict.new(conflict.requirement_trees.first.first, conflict.existing, conflict.requirement) ensure @output.close if defined?(@output) && !debug? end
search_for(dependency) 点击以切换源代码
# File rubygems/resolver.rb, line 223 def search_for(dependency) possibles, all = find_possible(dependency) if !@soft_missing && possibles.empty? exc = Gem::UnsatisfiableDependencyError.new dependency, all exc.errors = @set.errors raise exc end groups = Hash.new {|hash, key| hash[key] = [] } # create groups & sources in the same loop sources = possibles.map do |spec| source = spec.source groups[source] << spec source end.uniq.reverse activation_requests = [] sources.each do |source| groups[source]. sort_by {|spec| [spec.version, spec.platform =~ Gem::Platform.local ? 1 : 0] }. # rubocop:disable Performance/RegexpMatch map {|spec| ActivationRequest.new spec, dependency }. each {|activation_request| activation_requests << activation_request } end activation_requests end
sort_dependencies(dependencies, activated, conflicts) 点击以切换源代码
# File rubygems/resolver.rb, line 275 def sort_dependencies(dependencies, activated, conflicts) dependencies.sort_by.with_index do |dependency, i| name = name_for(dependency) [ activated.vertex_named(name).payload ? 0 : 1, amount_constrained(dependency), conflicts[name] ? 0 : 1, activated.vertex_named(name).payload ? 0 : search_for(dependency).count, i, # for stable sort ] end end
私有实例方法
amount_constrained(dependency) 点击以切换源代码
返回一个 (-infty, 0] 中的整数,一个更接近 0 的数字表示依赖项的约束性较小
具有 0 或 1 个可能性的依赖项(忽略版本要求)被赋予非常负的值,因此它们始终在不受约束的依赖项之前首先排序
# File rubygems/resolver.rb, line 297 def amount_constrained(dependency) @amount_constrained ||= {} @amount_constrained[dependency.name] ||= begin name_dependency = Gem::Dependency.new(dependency.name) dependency_request_for_name = Gem::Resolver::DependencyRequest.new(name_dependency, dependency.requester) all = @set.find_all(dependency_request_for_name).size if all <= 1 all - SINGLE_POSSIBILITY_CONSTRAINT_PENALTY else search = search_for(dependency).size search - all end end end