класс Bundler::GemVersionPromoter
Этот класс содержит всю логику для определения следующей версии Gem для обновления на основе запрошенного уровня (patch, minor, major). В основном предназначен для работы с Resolver, который предоставит ему список доступных версий зависимостей, как найденных в его индексе, прежде чем вернуть его обратно в движок разрешения для выбора лучшей версии.
Константы
- DEBUG
Атрибуты
По умолчанию strict равен false, что означает, что каждая доступная версия gem возвращается из sort_versions. Порядок отдает предпочтение запрошенному уровню (:patch, :minor, :major), но в сложных случаях требований некоторые gem будут по необходимости продвинуты за запрошенный уровень или даже возвращены к более старым версиям.
Если strict установлен в true, результаты из sort_versions будут усечены, исключая любые версии за пределами текущего уровня. Это может привести к неожиданным результатам или даже к исключениям VersionConflict, которые сообщают о том, что версия gem не существует для версий, которые на самом деле существуют в исходном источнике.
Публичные методы класса
# File lib/bundler/gem_version_promoter.rb, line 38
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 На основе списка locked_specs и списка gem для разблокирования создает экземпляр GemVersionPromoter.
@param locked_specs [SpecSet] Все текущие заблокированные спецификации. В отличие от Definition
where this list is empty if all gems are being updated, this should always be populated for all gems so this class can properly function.
@param unlock_gems [String] Список имен gem, которые разблокируются. Если пустой,
all gems will be considered unlocked.
@return [GemVersionPromoter]
Публичные методы экземпляра
# File lib/bundler/gem_version_promoter.rb, line 48
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 @param value [Symbol] Один из трех символов: :major, :minor или :patch.
# File lib/bundler/gem_version_promoter.rb, line 92 def major? level == :major end
@return [bool] Удобный метод для проверки значения переменной level.
# File lib/bundler/gem_version_promoter.rb, line 97 def minor? level == :minor end
@return [bool] Удобный метод для проверки значения переменной level.
# File lib/bundler/gem_version_promoter.rb, line 68
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
warn before_result
warn " after sort_versions: #{debug_format_result(dep, specs).inspect}"
end
end
end
end На основе Dependency и массива SpecGroups доступных версий gem, этот метод вернет массив SpecGroups, отсортированный (и возможно, усеченный, если strict равен true) в порядке, чтобы предоставить приоритет текущему уровню (:major, :minor или :patch) при принятии решений о том, какие версии лучше всего решают все зависимости в пакете. @param dep [Dependency] Dependency gem. @param spec_groups [SpecGroup] Массив SpecGroups для того же gem
named in the @dep param.
@return [SpecGroup] Новый экземпляр отсортированного массива SpecGroup
possibly filtered.
Приватные методы экземпляра
# File lib/bundler/gem_version_promoter.rb, line 183
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 # File lib/bundler/gem_version_promoter.rb, line 153 def either_version_older_than_locked @a_ver < @locked_version || @b_ver < @locked_version end
# File lib/bundler/gem_version_promoter.rb, line 103
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 # File lib/bundler/gem_version_promoter.rb, line 178
def move_version_to_end(result, version)
move, keep = result.partition {|s| s.version.to_s == version.to_s }
keep.concat(move)
end # File lib/bundler/gem_version_promoter.rb, line 168
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 Уточнения по перемещению версий не всегда могут надежно выполняться во время сортировки, так как не все элементы сравниваются между собой.
# File lib/bundler/gem_version_promoter.rb, line 157 def segments_do_not_match(level) index = [:major, :minor].index(level) @a_ver.segments[index] != @b_ver.segments[index] end
# File lib/bundler/gem_version_promoter.rb, line 121
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 # File lib/bundler/gem_version_promoter.rb, line 162 def unlocking_gem? unlock_gems.empty? || unlock_gems.include?(@gem_name) end
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.