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 = [])
-
(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 = {} @prerelease_specified = {} end
def level=(value)
-
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?
-
(bool)
- Convenience method for testing value of level variable.
def major? level == :major end
def minor?
-
(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)
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 unless @prerelease_specified[@gem_name] a_pre = @a_ver.prerelease? b_pre = @b_ver.prerelease? next -1 if a_pre && !b_pre next 1 if b_pre && !a_pre end 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)
-
(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 DEBUG @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 DEBUG puts before_result 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