class Gem::Resolver
给定一组作为 needed
的 Gem::Dependency
对象,以及一种通过 set
查询可用规范集的方法,计算一组 ActivationRequest
对象,这些对象指示为了满足所有需求应该激活的所有规范。
常量
- DEBUG_RESOLVER
-
如果设置了
DEBUG_RESOLVER
环境变量,则为解析器启用调试模式。这将在解析一组依赖关系时显示有关解析器状态的信息。 - SINGLE_POSSIBILITY_CONSTRAINT_PENALTY
属性
如果应该考虑所有开发依赖项,则 Set
为 true。
如果应该考虑直接开发依赖项,则 Set
为 true。
为 true 时,不会查找所请求 gem 的依赖项。
要跳过解析的 gem 的 Hash
。以 gem 名称为键,以 gem 规范数组为值。
配置的源中找不到的依赖项列表。
公共类方法
来源
# File lib/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
将 sets
组合成一个 ComposedSet
,该 ComposedSet
允许以统一的方式查找规范。如果其中一个 sets
本身是一个 ComposedSet
,则其 sets 将被展平到结果 ComposedSet
中。
来源
# File lib/rubygems/resolver.rb, line 87 def self.for_current_gems(needed) new needed, Gem::Resolver::CurrentSet.new end
创建一个 Resolver
,该解析器仅针对已安装的 gem 查询 needed
依赖项。
来源
# File lib/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
创建 Resolver
对象,该对象将从 needed
Dependency 对象开始解析树。
set
是一个对象,提供在哪里查找满足依赖关系的规范。默认情况下为 IndexSet
,它将查询 rubygems.org。
公共实例方法
来源
# File lib/rubygems/resolver.rb, line 271 def allow_missing?(dependency) @soft_missing end
来源
# File lib/rubygems/resolver.rb, line 252 def dependencies_for(specification) return [] if @ignore_dependencies spec = specification.spec requests(spec, specification) end
来源
# File lib/rubygems/resolver.rb, line 267 def name_for(dependency) dependency.name end
来源
# File lib/rubygems/resolver.rb, line 172 def output @output ||= debug? ? $stdout : File.open(IO::NULL, "w") end
来源
# File lib/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
来源
# File lib/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
继续解析!返回一个 ActivationRequest
对象数组。
来源
# File lib/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
来源
# File lib/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
私有实例方法
来源
# File lib/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
返回一个 (-infty, 0] 中的整数,数字越接近 0,表示依赖关系约束越小
具有 0 或 1 个可能性的依赖项(忽略版本要求)会被赋予非常负的值,因此它们总是在不受约束的依赖项之前排序