Class: Bundler::GemVersionPromoter
Relationships & Source Files | |
Inherits: | Object |
Defined in: | lib/bundler/gem_version_promoter.rb |
Overview
This class contains all of the logic for determining the next version of a ::Gem
to update to based on the requested level (patch, minor, major). Primarily designed to work with Resolver
which will provide it the list of available dependency versions as found in its index, before returning it to to the resolution engine to select the best version.
Class Method Summary
-
.new ⇒ GemVersionPromoter
constructor
Creates a
GemVersionPromoter
instance.
Instance Attribute Summary
- #level rw
- #level=(value) rw
- #major? ⇒ bool readonly
- #minor? ⇒ bool readonly
- #pre rw
- #pre? ⇒ bool rw
-
#strict
rw
By default, strict is false, meaning every available version of a gem is returned from sort_versions.
Instance Method Summary
-
#sort_versions(package, specs) ⇒ Specification
Given a
Resolver::Package
and an Array of Specifications of available versions for a gem, this method will return the Array of Specifications sorted (and possibly truncated if strict is true) in an order to give preference to the current level (:major,:minor
or:patch
) when resolution is deciding what versions best resolve all dependencies in the bundle. - #either_version_older_than_locked?(a, b, locked_version) ⇒ Boolean private
- #filter_dep_specs(specs, package) private
- #move_version_to_end(result, version) private
-
#post_sort(result, unlock, locked_version)
private
Specific version moves can’t always reliably be done during sorting as not all elements are compared against each other.
- #segments_do_not_match?(a, b, level) ⇒ Boolean private
- #sort_dep_specs(specs, package) private
Constructor Details
.new ⇒ GemVersionPromoter
Creates a GemVersionPromoter
instance.
# File 'lib/bundler/gem_version_promoter.rb', line 29
def initialize @level = :major @strict = false @pre = false end
Instance Attribute Details
#level (rw)
[ GitHub ]# File 'lib/bundler/gem_version_promoter.rb', line 10
attr_reader :level
#level=(value) (rw)
# File 'lib/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? ⇒ bool
(readonly)
# File 'lib/bundler/gem_version_promoter.rb', line 62
def major? level == :major end
#minor? ⇒ bool
(readonly)
# File 'lib/bundler/gem_version_promoter.rb', line 67
def minor? level == :minor end
#pre (rw)
[ GitHub ]# File 'lib/bundler/gem_version_promoter.rb', line 11
attr_accessor :pre
#pre? ⇒ bool
(rw)
# File 'lib/bundler/gem_version_promoter.rb', line 72
def pre? pre == true end
#strict (rw)
By default, strict is false, meaning every available version of a gem is returned from sort_versions. The order gives preference to the requested level (:patch, :minor
, :major
) but in complicated requirement cases some gems will by necessity be promoted past the requested level, or even reverted to older versions.
If strict is set to true, the results from sort_versions will be truncated, eliminating any version outside the current level scope. This can lead to unexpected outcomes or even VersionConflict exceptions that report a version of a gem not existing for versions that indeed do existing in the referenced source.
# File 'lib/bundler/gem_version_promoter.rb', line 24
attr_accessor :strict
Instance Method Details
#either_version_older_than_locked?(a, b, locked_version) ⇒ Boolean
(private)
# File 'lib/bundler/gem_version_promoter.rb', line 119
def either_version_older_than_locked?(a, b, locked_version) locked_version && (a.version < locked_version || b.version < locked_version) end
#filter_dep_specs(specs, package) (private)
[ GitHub ]# File 'lib/bundler/gem_version_promoter.rb', line 78
def filter_dep_specs(specs, package) 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
#move_version_to_end(result, version) (private)
[ GitHub ]# File 'lib/bundler/gem_version_promoter.rb', line 140
def move_version_to_end(result, version) move, keep = result.partition {|s| s.version.to_s == version.to_s } keep.concat(move) end
#post_sort(result, unlock, locked_version) (private)
Specific version moves can’t always reliably be done during sorting as not all elements are compared against each other.
# File 'lib/bundler/gem_version_promoter.rb', line 130
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_end(result, locked_version) end end
#segments_do_not_match?(a, b, level) ⇒ Boolean
(private)
#sort_dep_specs(specs, package) (private)
[ GitHub ]# File 'lib/bundler/gem_version_promoter.rb', line 92
def sort_dep_specs(specs, package) 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? a <=> b elsif either_version_older_than_locked?(a, b, locked_version) a <=> b elsif segments_do_not_match?(a, b, :major) b <=> a elsif !minor? && segments_do_not_match?(a, b, :minor) b <=> a else a <=> b end end post_sort(result, package.unlock?, locked_version) end
#sort_versions(package, specs) ⇒ Specification
Given a Resolver::Package
and an Array of Specifications of available versions for a gem, this method will return the Array of Specifications sorted (and possibly truncated if strict is true) in an order to give preference to the current level (:major, :minor
or :patch
) when resolution is deciding what versions best resolve all dependencies in the bundle.
# File 'lib/bundler/gem_version_promoter.rb', line 55
def sort_versions(package, specs) specs = filter_dep_specs(specs, package) if strict sort_dep_specs(specs, package) end