class Bundler::GemVersionPromoter

这个类包含所有逻辑,用于根据请求的级别(补丁、次要、主要)确定要更新到的下一个 Gem 版本。主要设计用于与 Resolver 一起工作,后者将在返回解析引擎以选择最佳版本之前,从其索引中获取可用的依赖项版本列表。

属性

level[R]
pre[RW]
strict[RW]

默认情况下,strict 为 false,这意味着会从 sort_versions 返回 gem 的每个可用版本。顺序优先考虑请求的级别(:patch、:minor、:major),但在复杂的依赖关系情况下,一些 gem 将必然被提升到超出请求的级别,甚至回退到旧版本。

如果将 strict 设置为 true,则会截断 sort_versions 的结果,消除当前级别范围之外的任何版本。这可能导致意外的结果,甚至导致 VersionConflict 异常,报告引用的源中实际存在的 gem 版本不存在。

公共类方法

new() 点击以切换源代码

创建 GemVersionPromoter 实例。

@return [GemVersionPromoter]

# File bundler/gem_version_promoter.rb, line 29
def initialize
  @level = :major
  @strict = false
  @pre = false
end

公共实例方法

filter_versions(package, specs) 点击以切换源代码

给定一个 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
level=(value) 点击以切换源代码

@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
major?() 点击以切换源代码

@return [bool] 用于测试级别变量值的便捷方法。

# File bundler/gem_version_promoter.rb, line 82
def major?
  level == :major
end
minor?() 点击以切换源代码

@return [bool] 用于测试级别变量值的便捷方法。

# File bundler/gem_version_promoter.rb, line 87
def minor?
  level == :minor
end
pre?() 点击以切换源代码

@return [bool] 用于测试 pre 变量值的便捷方法。

# File bundler/gem_version_promoter.rb, line 92
def pre?
  pre == true
end
sort_versions(package, specs) 点击以切换源代码

给定一个 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

私有实例方法

either_version_older_than_locked?(a, b, locked_version) 点击以切换源代码
# 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
move_version_to_beginning(result, version) 点击以切换源代码
# 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
post_sort(result, unlock, locked_version) 点击以切换源代码

特定的版本移动并不总是在排序期间可靠地完成,因为并非所有元素都会相互比较。

# 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
segments_do_not_match?(a, b, level) 点击以切换源代码
# 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