Class: Bundler::GemVersionPromoter

Inherits:
Object
  • Object
show all
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.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeGemVersionPromoter

Creates a GemVersionPromoter instance.



29
30
31
32
33
# File 'lib/bundler/gem_version_promoter.rb', line 29

def initialize
  @level = :major
  @strict = false
  @pre = false
end

Instance Attribute Details

#levelObject

Returns the value of attribute level.



10
11
12
# File 'lib/bundler/gem_version_promoter.rb', line 10

def level
  @level
end

#preObject

Returns the value of attribute pre.



11
12
13
# File 'lib/bundler/gem_version_promoter.rb', line 11

def pre
  @pre
end

#strictObject

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.



24
25
26
# File 'lib/bundler/gem_version_promoter.rb', line 24

def strict
  @strict
end

Instance Method Details

#filter_versions(package, specs) ⇒ Specification

Given a Resolver::Package and an Array of Specifications of available versions for a gem, this method will truncate the Array if strict is true. That means filtering out downgrades from the version currently locked, and filtering out upgrades that go past the selected level (major, minor, or patch).

Parameters:

  • package (Resolver::Package)

    The package being resolved.

  • specs (Specification)

    An array of Specifications for the package.

Returns:

  • (Specification)

    A new instance of the Specification Array truncated.



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/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

#major?bool

Returns Convenience method for testing value of level variable.

Returns:

  • (bool)

    Convenience method for testing value of level variable.



82
83
84
# File 'lib/bundler/gem_version_promoter.rb', line 82

def major?
  level == :major
end

#minor?bool

Returns Convenience method for testing value of level variable.

Returns:

  • (bool)

    Convenience method for testing value of level variable.



87
88
89
# File 'lib/bundler/gem_version_promoter.rb', line 87

def minor?
  level == :minor
end

#pre?bool

Returns Convenience method for testing value of pre variable.

Returns:

  • (bool)

    Convenience method for testing value of pre variable.



92
93
94
# File 'lib/bundler/gem_version_promoter.rb', line 92

def pre?
  pre == true
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 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.

Parameters:

  • package (Resolver::Package)

    The package being resolved.

  • specs (Specification)

    An array of Specifications for the package.

Returns:

  • (Specification)

    A new instance of the Specification Array sorted.



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/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