class Gem::Resolver
给定一组作为 needed 的 Gem::Dependency 对象,以及通过 set 查询可用规范集的方式,计算一组 ActivationRequest 对象,这些对象指示了为满足所有要求而应激活的所有规范。
Constants
- DEBUG_RESOLVER
-
如果设置了
DEBUG_RESOLVER环境变量,则为解析器启用调试模式。这将显示在解析依赖集时解析器的状态信息。 - SINGLE_POSSIBILITY_CONSTRAINT_PENALTY
属性
如果应考虑所有开发依赖项,则设置为 true。
如果应考虑直接开发依赖项,则设置为 true。
当为 true 时,不会为请求的 gem 查找依赖项。
要跳过解析的 gem 的 Hash。键是 gem 名称,值为 gem 规范数组。
在已配置的源中找不到的依赖项列表。
Public Class Methods
Source
# 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 中,该组合集允许以统一的方式查找规范。如果 sets 中的一个本身就是一个 ComposedSet,则其内部的集合会被展平到结果 ComposedSet 中。
Source
# File lib/rubygems/resolver.rb, line 87 def self.for_current_gems(needed) new needed, Gem::Resolver::CurrentSet.new end
创建一个 Resolver,该解析器仅针对 needed 依赖项查询已安装的 gem。
Source
# 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
Public Instance Methods
Source
# File lib/rubygems/resolver.rb, line 271 def allow_missing?(dependency) @soft_missing end
Source
# File lib/rubygems/resolver.rb, line 252 def dependencies_for(specification) return [] if @ignore_dependencies spec = specification.spec requests(spec, specification) end
Source
# File lib/rubygems/resolver.rb, line 267 def name_for(dependency) dependency.name end
Source
# File lib/rubygems/resolver.rb, line 172 def output @output ||= debug? ? $stdout : File.open(IO::NULL, "w") end
Source
# 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
Source
# 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 对象数组。
Source
# 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, -Gem::Platform.platform_specificity_match(spec.platform, Gem::Platform.local)] }. map {|spec| ActivationRequest.new spec, dependency }. each {|activation_request| activation_requests << activation_request } end activation_requests end
Source
# 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
私有实例方法
Source
# 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
返回一个整数,范围为 (-无穷, 0],值越接近 0 表示依赖项的约束性越弱。
具有 0 或 1 种可能性的依赖项(忽略版本要求)会获得非常负的值,因此它们始终排在最前面,位于无约束的依赖项之前。