class Bundler::GemVersionPromoter
这个类包含所有逻辑,用于根据请求的级别(补丁、次要、主要)确定要更新到的下一个 Gem
版本。主要设计用于与 Resolver
一起工作,后者将在返回解析引擎以选择最佳版本之前,从其索引中获取可用的依赖项版本列表。
属性
默认情况下,strict 为 false,这意味着会从 sort_versions 返回 gem 的每个可用版本。顺序优先考虑请求的级别(:patch、:minor、:major),但在复杂的依赖关系情况下,一些 gem 将必然被提升到超出请求的级别,甚至回退到旧版本。
如果将 strict 设置为 true,则会截断 sort_versions
的结果,消除当前级别范围之外的任何版本。这可能导致意外的结果,甚至导致 VersionConflict 异常,报告引用的源中实际存在的 gem 版本不存在。
公共类方法
创建 GemVersionPromoter
实例。
@return [GemVersionPromoter]
# File bundler/gem_version_promoter.rb, line 29 def initialize @level = :major @strict = false @pre = false end
公共实例方法
给定一个 Resolver::Package
和一个 gem 的可用版本规范的数组,如果 strict 为 true,此方法将截断数组。这意味着过滤掉从当前锁定版本降级的版本,并过滤掉超出选定级别(主要、次要或补丁)的升级。@param package [Resolver::Package] 正在解析的包。@param specs [Specification] 包的规范数组。@return [Specification] 规范数组的新实例
truncated.
# File bundler/gem_version_promoter.rb, line 105 def filter_versions(package, specs) return specs unless strict locked_version = package.locked_version return specs if locked_version.nil? || major? specs.select do |spec| gsv = spec.version must_match = minor? ? [0] : [0, 1] all_match = must_match.all? {|idx| gsv.segments[idx] == locked_version.segments[idx] } all_match && gsv >= locked_version end end
@param value [Symbol] 三个符号之一::major、:minor 或 :patch。
# File bundler/gem_version_promoter.rb, line 36 def level=(value) v = case value when String, Symbol value.to_sym end raise ArgumentError, "Unexpected level #{v}. Must be :major, :minor or :patch" unless [:major, :minor, :patch].include?(v) @level = v end
@return [bool] 用于测试级别变量值的便捷方法。
# File bundler/gem_version_promoter.rb, line 82 def major? level == :major end
@return [bool] 用于测试级别变量值的便捷方法。
# File bundler/gem_version_promoter.rb, line 87 def minor? level == :minor end
@return [bool] 用于测试 pre 变量值的便捷方法。
# File bundler/gem_version_promoter.rb, line 92 def pre? pre == true end
给定一个 Resolver::Package
和一个 gem 的可用版本规范的数组,此方法将返回排序后的规范数组,以便在解析决定捆绑包中哪些版本最能解决所有依赖关系时,优先考虑当前级别(:major、:minor 或 :patch)。@param package [Resolver::Package] 正在解析的包。@param specs [Specification] 包的规范数组。@return [Specification] 排序后的规范数组的新实例。
# File bundler/gem_version_promoter.rb, line 54 def sort_versions(package, specs) locked_version = package.locked_version result = specs.sort do |a, b| unless package.prerelease_specified? || pre? a_pre = a.prerelease? b_pre = b.prerelease? next 1 if a_pre && !b_pre next -1 if b_pre && !a_pre end if major? || locked_version.nil? b <=> a elsif either_version_older_than_locked?(a, b, locked_version) b <=> a elsif segments_do_not_match?(a, b, :major) a <=> b elsif !minor? && segments_do_not_match?(a, b, :minor) a <=> b else b <=> a end end post_sort(result, package.unlock?, locked_version) end
私有实例方法
# File bundler/gem_version_promoter.rb, line 123 def either_version_older_than_locked?(a, b, locked_version) a.version < locked_version || b.version < locked_version end
# File bundler/gem_version_promoter.rb, line 144 def move_version_to_beginning(result, version) move, keep = result.partition {|s| s.version.to_s == version.to_s } move.concat(keep) end
特定的版本移动并不总是在排序期间可靠地完成,因为并非所有元素都会相互比较。
# File bundler/gem_version_promoter.rb, line 134 def post_sort(result, unlock, locked_version) # default :major behavior in Bundler does not do this return result if major? if unlock || locked_version.nil? result else move_version_to_beginning(result, locked_version) end end
# File bundler/gem_version_promoter.rb, line 127 def segments_do_not_match?(a, b, level) index = [:major, :minor].index(level) a.segments[index] != b.segments[index] end