class Bundler::Patch::ConservativeResolver

Attributes

gems_to_update[RW]
locked_specs[RW]
minor_preferred[RW]
prefer_minimal[RW]
strict[RW]

Public Class Methods

new(index, source_requirements, base) click to toggle source
Calls superclass method
# File lib/bundler/patch/conservative_resolver.rb, line 5
def initialize(index, source_requirements, base)
  case Bundler::Resolver.instance_method(:initialize).arity
  when 3 # 1.9 1.10
    super(index, source_requirements, base)
  when 4 # 1.11 1.12
    super(index, source_requirements, base, nil)
  end
end

Public Instance Methods

both_versions_gt_or_equal_to_version(version) click to toggle source
# File lib/bundler/patch/conservative_resolver.rb, line 144
def both_versions_gt_or_equal_to_version(version)
  version && @a_ver >= version && @b_ver >= version
end
debug_format_result(dep, res) click to toggle source
# File lib/bundler/patch/conservative_resolver.rb, line 45
def debug_format_result(dep, res)
  a = [dep.to_s,
       res.map { |sg| [sg.version, sg.dependencies_for_activated_platforms.map { |dp| [dp.name, dp.requirement.to_s] }] }]
  [a.first, a.last.map { |sg_data| [sg_data.first.version, sg_data.last.map { |aa| aa.join(' ') }] }]
end
either_version_older_than_locked(locked_version) click to toggle source
# File lib/bundler/patch/conservative_resolver.rb, line 123
def either_version_older_than_locked(locked_version)
  @a_ver < locked_version || @b_ver < locked_version
end
filter_specs(specs, locked_spec) click to toggle source
# File lib/bundler/patch/conservative_resolver.rb, line 51
def filter_specs(specs, locked_spec)
  res = specs.select do |sg|
    # SpecGroup is grouped by name/version, multiple entries for multiple platforms.
    # We only need the name, which will be the same, so hard coding to first is ok.
    gem_spec = sg.first

    if locked_spec
      gsv = gem_spec.version
      lsv = locked_spec.version

      must_match = @minor_preferred ? [0] : [0, 1]

      matches = must_match.map { |idx| gsv.segments[idx] == lsv.segments[idx] }
      (matches.uniq == [true]) ? gsv.send(:>=, lsv) : false
    else
      true
    end
  end

  sort_specs(res, locked_spec)
end
move_version_to_end(result, version) click to toggle source
# File lib/bundler/patch/conservative_resolver.rb, line 148
def move_version_to_end(result, version)
  move, keep = result.partition { |s| s.first.version.to_s == version.to_s }
  keep.concat(move)
end
neither_version_matches(match_version) click to toggle source
# File lib/bundler/patch/conservative_resolver.rb, line 136
def neither_version_matches(match_version)
  !one_version_matches(match_version)
end
one_version_matches(match_version) click to toggle source
# File lib/bundler/patch/conservative_resolver.rb, line 140
def one_version_matches(match_version)
  [@a_ver, @b_ver].include?(match_version)
end
post_sort(result) click to toggle source
# File lib/bundler/patch/conservative_resolver.rb, line 105
def post_sort(result)
  unless unlocking_gem?
    result = move_version_to_end(result, @locked_version)
  end

  if @new_version && unlocking_gem? && segments_match(:major, @new_version, @locked_version)
    if @prefer_minimal || (!@prefer_minimal && (result.last.first.version < @new_version))
      result = move_version_to_end(result, @new_version)
    end
  end

  result
end
search_for(dependency) click to toggle source
Calls superclass method
# File lib/bundler/patch/conservative_resolver.rb, line 14
def search_for(dependency)
  res = super(dependency)

  dep = dependency.dep unless dependency.is_a? Gem::Dependency

  super_result = "super search_for: #{debug_format_result(dep, res).inspect}"

  @conservative_search_for ||= {}
  res = @conservative_search_for[dep] ||= begin
    gem_name = dep.name

    # An Array per version returned, different entries for different platforms.
    # We just need the version here so it's ok to hard code this to the first instance.
    locked_spec = @locked_specs[gem_name].first

    (@strict ?
      filter_specs(res, locked_spec) :
      sort_specs(res, locked_spec)).tap do |result|
      if ENV['DEBUG_PATCH_RESOLVER']
        STDERR.puts super_result
        STDERR.puts "after search_for: #{debug_format_result(dep, result).inspect}"
      end
    end
  end

  # dup is important, in weird (large) cases Bundler will empty the result array corrupting the cache.
  # Bundler itself doesn't have this problem because the super search_for does a select on its cached
  # search results, effectively duping it.
  res.dup
end
segments_do_not_match(level, a_ver=@a_ver, b_ver=@b_ver) click to toggle source
# File lib/bundler/patch/conservative_resolver.rb, line 131
def segments_do_not_match(level, a_ver=@a_ver, b_ver=@b_ver)
  index = [:major, :minor].index(level)
  a_ver.segments[index] != b_ver.segments[index]
end
segments_match(level, a_ver=@a_ver, b_ver=@b_ver) click to toggle source
# File lib/bundler/patch/conservative_resolver.rb, line 127
def segments_match(level, a_ver=@a_ver, b_ver=@b_ver)
  !segments_do_not_match(level, a_ver, b_ver)
end
sort_specs(specs, locked_spec) click to toggle source

reminder: sort still filters anything older than locked version

# File lib/bundler/patch/conservative_resolver.rb, line 74
def sort_specs(specs, locked_spec)
  return specs unless locked_spec
  @gem_name = locked_spec.name
  @locked_version = locked_spec.version

  filtered = specs.select { |s| s.first.version >= @locked_version }

  @gem_patch = @gems_to_update.gem_patch_for(@gem_name)
  @new_version = @gem_patch ? @gem_patch.new_version : nil

  result = filtered.sort do |a, b|
    @a_ver = a.first.version
    @b_ver = b.first.version
    case
    when segments_do_not_match(:major)
      @b_ver <=> @a_ver
    when !@minor_preferred && segments_do_not_match(:minor)
      @b_ver <=> @a_ver
    when @prefer_minimal && !unlocking_gem?
      @b_ver <=> @a_ver
    when @prefer_minimal && unlocking_gem? &&
      (neither_version_matches(@locked_version) &&
        (!@new_version || both_versions_gt_or_equal_to_version(@new_version)))
      @b_ver <=> @a_ver
    else
      @a_ver <=> @b_ver
    end
  end
  post_sort(result)
end
unlocking_gem?() click to toggle source
# File lib/bundler/patch/conservative_resolver.rb, line 119
def unlocking_gem?
  @gems_to_update.unlocking_gem?(@gem_name)
end