class Dependabot::NpmAndYarn::UpdateChecker::RequirementsUpdater

Constants

ALLOWED_UPDATE_STRATEGIES
SEPARATOR
VERSION_REGEX

Attributes

latest_resolvable_version[R]
requirements[R]
update_strategy[R]
updated_source[R]

Public Class Methods

new(requirements:, updated_source:, update_strategy:, latest_resolvable_version:) click to toggle source
# File lib/dependabot/npm_and_yarn/update_checker/requirements_updater.rb, line 21
def initialize(requirements:, updated_source:, update_strategy:,
               latest_resolvable_version:)
  @requirements = requirements
  @updated_source = updated_source
  @update_strategy = update_strategy

  check_update_strategy

  return unless latest_resolvable_version

  @latest_resolvable_version =
    version_class.new(latest_resolvable_version)
end

Public Instance Methods

updated_requirements() click to toggle source
# File lib/dependabot/npm_and_yarn/update_checker/requirements_updater.rb, line 35
def updated_requirements
  requirements.map do |req|
    req = req.merge(source: updated_source)
    next req unless latest_resolvable_version
    next initial_req_after_source_change(req) unless req[:requirement]
    next req if req[:requirement].match?(/^([A-Za-uw-z]|v[^\d])/)

    case update_strategy
    when :widen_ranges then widen_requirement(req)
    when :bump_versions then update_version_requirement(req)
    when :bump_versions_if_necessary
      update_version_requirement_if_needed(req)
    else raise "Unexpected update strategy: #{update_strategy}"
    end
  end
end

Private Instance Methods

check_update_strategy() click to toggle source
# File lib/dependabot/npm_and_yarn/update_checker/requirements_updater.rb, line 57
def check_update_strategy
  return if ALLOWED_UPDATE_STRATEGIES.include?(update_strategy)

  raise "Unknown update strategy: #{update_strategy}"
end
initial_req_after_source_change(req) click to toggle source
# File lib/dependabot/npm_and_yarn/update_checker/requirements_updater.rb, line 70
def initial_req_after_source_change(req)
  return req unless updating_from_git_to_npm?
  return req unless req[:requirement].nil?

  req.merge(requirement: "^#{latest_resolvable_version}")
end
ruby_requirements(requirement_string) click to toggle source
# File lib/dependabot/npm_and_yarn/update_checker/requirements_updater.rb, line 125
def ruby_requirements(requirement_string)
  NpmAndYarn::Requirement.
    requirements_array(requirement_string)
end
update_greatest_version(old_version, version_to_be_permitted) click to toggle source
# File lib/dependabot/npm_and_yarn/update_checker/requirements_updater.rb, line 169
def update_greatest_version(old_version, version_to_be_permitted)
  version = version_class.new(old_version)
  version = version.release if version.prerelease?

  index_to_update =
    version.segments.map.with_index { |seg, i| seg.zero? ? 0 : i }.max

  version.segments.map.with_index do |_, index|
    if index < index_to_update
      version_to_be_permitted.segments[index]
    elsif index == index_to_update
      version_to_be_permitted.segments[index] + 1
    else 0
    end
  end.join(".")
end
update_range_requirement(req_string) click to toggle source
# File lib/dependabot/npm_and_yarn/update_checker/requirements_updater.rb, line 130
def update_range_requirement(req_string)
  range_requirements =
    req_string.split(SEPARATOR).select { |r| r.match?(/<|(\s+-\s+)/) }

  if range_requirements.count == 1
    range_requirement = range_requirements.first
    versions = range_requirement.scan(VERSION_REGEX)
    upper_bound = versions.map { |v| version_class.new(v) }.max
    new_upper_bound = update_greatest_version(
      upper_bound,
      latest_resolvable_version
    )

    req_string.sub(
      upper_bound.to_s,
      new_upper_bound.to_s
    )
  else
    req_string + " || ^#{latest_resolvable_version}"
  end
end
update_version_requirement(req) click to toggle source
# File lib/dependabot/npm_and_yarn/update_checker/requirements_updater.rb, line 77
def update_version_requirement(req)
  current_requirement = req[:requirement]

  if current_requirement.match?(/(<|-\s)/i)
    ruby_req = ruby_requirements(current_requirement).first
    return req if ruby_req.satisfied_by?(latest_resolvable_version)

    updated_req = update_range_requirement(current_requirement)
    return req.merge(requirement: updated_req)
  end

  reqs = current_requirement.strip.split(SEPARATOR).map(&:strip)
  req.merge(requirement: update_version_string(reqs.first))
end
update_version_requirement_if_needed(req) click to toggle source
# File lib/dependabot/npm_and_yarn/update_checker/requirements_updater.rb, line 92
def update_version_requirement_if_needed(req)
  current_requirement = req[:requirement]
  version = latest_resolvable_version
  return req if current_requirement.strip == ""

  ruby_reqs = ruby_requirements(current_requirement)
  return req if ruby_reqs.any? { |r| r.satisfied_by?(version) }

  update_version_requirement(req)
end
update_version_string(req_string) click to toggle source
# File lib/dependabot/npm_and_yarn/update_checker/requirements_updater.rb, line 152
def update_version_string(req_string)
  req_string.
    sub(VERSION_REGEX) do |old_version|
      if old_version.match?(/\d-/) ||
         latest_resolvable_version.to_s.match?(/\d-/)
        latest_resolvable_version.to_s
      else
        old_parts = old_version.split(".")
        new_parts = latest_resolvable_version.to_s.split(".").
                    first(old_parts.count)
        new_parts.map.with_index do |part, i|
          old_parts[i].match?(/^x\b/) ? "x" : part
        end.join(".")
      end
    end
end
updating_from_git_to_npm?() click to toggle source
# File lib/dependabot/npm_and_yarn/update_checker/requirements_updater.rb, line 63
def updating_from_git_to_npm?
  return false unless updated_source.nil?

  original_source = requirements.map { |r| r[:source] }.compact.first
  original_source&.fetch(:type) == "git"
end
version_class() click to toggle source
# File lib/dependabot/npm_and_yarn/update_checker/requirements_updater.rb, line 186
def version_class
  NpmAndYarn::Version
end
widen_requirement(req) click to toggle source
# File lib/dependabot/npm_and_yarn/update_checker/requirements_updater.rb, line 103
def widen_requirement(req)
  current_requirement = req[:requirement]
  version = latest_resolvable_version
  return req if current_requirement.strip == ""

  ruby_reqs = ruby_requirements(current_requirement)
  return req if ruby_reqs.any? { |r| r.satisfied_by?(version) }

  reqs = current_requirement.strip.split(SEPARATOR).map(&:strip)

  updated_requirement =
    if reqs.any? { |r| r.match?(/(<|-\s)/i) }
      update_range_requirement(current_requirement)
    elsif current_requirement.strip.split(SEPARATOR).count == 1
      update_version_string(current_requirement)
    else
      current_requirement
    end

  req.merge(requirement: updated_requirement)
end