class Bundler::GemVersionPromoter

to the resolution engine to select the best version.
available dependency versions as found in its index, before returning it to
Primarily designed to work with Resolver which will provide it the list of
Gem to update to based on the requested level (patch, minor, major).
This class contains all of the logic for determining the next version of a

def debug_format_result(dep, spec_groups)

def debug_format_result(dep, spec_groups)
  a = [dep.to_s,
       spec_groups.map {|sg| [sg.version, sg.dependencies_for_activated_platforms.map {|dp| [dp.name, dp.requirement.to_s] }] }]
  last_map = a.last.map {|sg_data| [sg_data.first.version, sg_data.last.map {|aa| aa.join(" ") }] }
  [a.first, last_map, level, strict ? :strict : :not_strict]
end

def either_version_older_than_locked

def either_version_older_than_locked
  @a_ver < @locked_version || @b_ver < @locked_version
end

def filter_dep_specs(spec_groups, locked_spec)

def filter_dep_specs(spec_groups, locked_spec)
  res = spec_groups.select do |spec_group|
    if locked_spec && !major?
      gsv = spec_group.version
      lsv = locked_spec.version
      must_match = minor? ? [0] : [0, 1]
      matches = must_match.map {|idx| gsv.segments[idx] == lsv.segments[idx] }
      (matches.uniq == [true]) ? (gsv >= lsv) : false
    else
      true
    end
  end
  sort_dep_specs(res, locked_spec)
end

def initialize(locked_specs = SpecSet.new([]), unlock_gems = [])

Returns:
  • (GemVersionPromoter) -

Parameters:
  • unlock_gems (String) -- List of gem names being unlocked. If empty,
  • locked_specs (SpecSet) -- All current locked specs. Unlike Definition
def initialize(locked_specs = SpecSet.new([]), unlock_gems = [])
  @level = :major
  @strict = false
  @locked_specs = locked_specs
  @unlock_gems = unlock_gems
  @sort_versions = {}
end

def level=(value)

Parameters:
  • value (Symbol) -- One of three Symbols: :major, :minor or :patch.
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

def major?

Returns:
  • (bool) - Convenience method for testing value of level variable.
def major?
  level == :major
end

def minor?

Returns:
  • (bool) - Convenience method for testing value of level variable.
def minor?
  level == :minor
end

def move_version_to_end(result, version)

def move_version_to_end(result, version)
  move, keep = result.partition {|s| s.version.to_s == version.to_s }
  keep.concat(move)
end

def post_sort(result)

as not all elements are compared against each other.
Specific version moves can't always reliably be done during sorting
def post_sort(result)
  # default :major behavior in Bundler does not do this
  return result if major?
  if unlocking_gem?
    result
  else
    move_version_to_end(result, @locked_version)
  end
end

def segments_do_not_match(level)

def segments_do_not_match(level)
  index = [:major, :minor].index(level)
  @a_ver.segments[index] != @b_ver.segments[index]
end

def sort_dep_specs(spec_groups, locked_spec)

def sort_dep_specs(spec_groups, locked_spec)
  return spec_groups unless locked_spec
  @gem_name = locked_spec.name
  @locked_version = locked_spec.version
  result = spec_groups.sort do |a, b|
    @a_ver = a.version
    @b_ver = b.version
    if major?
      @a_ver <=> @b_ver
    elsif either_version_older_than_locked
      @a_ver <=> @b_ver
    elsif segments_do_not_match(:major)
      @b_ver <=> @a_ver
    elsif !minor? && segments_do_not_match(:minor)
      @b_ver <=> @a_ver
    else
      @a_ver <=> @b_ver
    end
  end
  post_sort(result)
end

def sort_versions(dep, spec_groups)

Returns:
  • (SpecGroup) - A new instance of the SpecGroup Array sorted and

Parameters:
  • spec_groups (SpecGroup) -- An array of SpecGroups for the same gem
  • dep (Dependency) -- The Dependency of the gem.
def sort_versions(dep, spec_groups)
  before_result = "before sort_versions: #{debug_format_result(dep, spec_groups).inspect}" if ENV["DEBUG_RESOLVER"]
  @sort_versions[dep] ||= begin
    gem_name = dep.name
    # An Array per version returned, different entries for different platforms.
    # We only need the version here so it's ok to hard code this to the first instance.
    locked_spec = locked_specs[gem_name].first
    if strict
      filter_dep_specs(spec_groups, locked_spec)
    else
      sort_dep_specs(spec_groups, locked_spec)
    end.tap do |specs|
      if ENV["DEBUG_RESOLVER"]
        STDERR.puts before_result
        STDERR.puts " after sort_versions: #{debug_format_result(dep, specs).inspect}"
      end
    end
  end
end

def unlocking_gem?

def unlocking_gem?
  unlock_gems.empty? || unlock_gems.include?(@gem_name)
end