class Dependabot::Cargo::UpdateChecker

Public Instance Methods

latest_resolvable_version() click to toggle source
# File lib/dependabot/cargo/update_checker.rb, line 30
def latest_resolvable_version
  return if path_dependency?

  @latest_resolvable_version ||=
    if git_dependency?
      latest_resolvable_version_for_git_dependency
    elsif git_subdependency?
      # TODO: Dependabot can't update git sub-dependencies yet, because
      # they can't be passed to GitCommitChecker.
      nil
    else
      fetch_latest_resolvable_version(unlock_requirement: true)
    end
end
latest_resolvable_version_with_no_unlock() click to toggle source
# File lib/dependabot/cargo/update_checker.rb, line 58
def latest_resolvable_version_with_no_unlock
  return if path_dependency?

  @latest_resolvable_version_with_no_unlock ||=
    if git_dependency?
      latest_resolvable_commit_with_unchanged_git_source
    else
      fetch_latest_resolvable_version(unlock_requirement: false)
    end
end
latest_version() click to toggle source
# File lib/dependabot/cargo/update_checker.rb, line 15
def latest_version
  return if path_dependency?

  @latest_version =
    if git_dependency?
      latest_version_for_git_dependency
    elsif git_subdependency?
      # TODO: Dependabot can't update git sub-dependencies yet, because
      # they can't be passed to GitCommitChecker.
      nil
    else
      latest_version_finder.latest_version
    end
end
lowest_resolvable_security_fix_version() click to toggle source
# File lib/dependabot/cargo/update_checker.rb, line 49
def lowest_resolvable_security_fix_version
  raise "Dependency not vulnerable!" unless vulnerable?

  return @lowest_resolvable_security_fix_version if defined?(@lowest_resolvable_security_fix_version)

  @lowest_resolvable_security_fix_version =
    fetch_lowest_resolvable_security_fix_version
end
lowest_security_fix_version() click to toggle source
# File lib/dependabot/cargo/update_checker.rb, line 45
def lowest_security_fix_version
  latest_version_finder.lowest_security_fix_version
end
requirements_update_strategy() click to toggle source
# File lib/dependabot/cargo/update_checker.rb, line 78
def requirements_update_strategy
  library? ? :bump_versions_if_necessary : :bump_versions
end
updated_requirements() click to toggle source
# File lib/dependabot/cargo/update_checker.rb, line 69
def updated_requirements
  RequirementsUpdater.new(
    requirements: dependency.requirements,
    updated_source: updated_source,
    target_version: target_version,
    update_strategy: requirements_update_strategy
  ).updated_requirements
end

Private Instance Methods

dependency_source_details() click to toggle source
# File lib/dependabot/cargo/update_checker.rb, line 254
def dependency_source_details
  sources =
    dependency.requirements.map { |r| r.fetch(:source) }.uniq.compact

  raise "Multiple sources! #{sources.join(', ')}" if sources.count > 1

  sources.first
end
fetch_latest_resolvable_version(unlock_requirement:) click to toggle source
# File lib/dependabot/cargo/update_checker.rb, line 198
def fetch_latest_resolvable_version(unlock_requirement:)
  prepared_files = FilePreparer.new(
    dependency_files: dependency_files,
    dependency: dependency,
    unlock_requirement: unlock_requirement,
    latest_allowable_version: latest_version
  ).prepared_dependency_files

  VersionResolver.new(
    dependency: dependency,
    prepared_dependency_files: prepared_files,
    original_dependency_files: dependency_files,
    credentials: credentials
  ).latest_resolvable_version
end
fetch_lowest_resolvable_security_fix_version() click to toggle source
# File lib/dependabot/cargo/update_checker.rb, line 214
def fetch_lowest_resolvable_security_fix_version
  fix_version = lowest_security_fix_version
  return latest_resolvable_version if fix_version.nil?

  return latest_resolvable_version if path_dependency? || git_dependency? || git_subdependency?

  prepared_files = FilePreparer.new(
    dependency_files: dependency_files,
    dependency: dependency,
    unlock_requirement: true,
    latest_allowable_version: fix_version
  ).prepared_dependency_files

  resolved_fix_version = VersionResolver.new(
    dependency: dependency,
    prepared_dependency_files: prepared_files,
    original_dependency_files: dependency_files,
    credentials: credentials
  ).latest_resolvable_version

  return fix_version if fix_version == resolved_fix_version

  latest_resolvable_version
end
git_commit_checker() click to toggle source
# File lib/dependabot/cargo/update_checker.rb, line 282
def git_commit_checker
  @git_commit_checker ||=
    GitCommitChecker.new(
      dependency: dependency,
      credentials: credentials
    )
end
git_dependency?() click to toggle source
# File lib/dependabot/cargo/update_checker.rb, line 263
def git_dependency?
  git_commit_checker.git_dependency?
end
git_subdependency?() click to toggle source
# File lib/dependabot/cargo/update_checker.rb, line 267
def git_subdependency?
  return false if dependency.top_level?

  !version_class.correct?(dependency.version)
end
latest_git_tag_is_resolvable?() click to toggle source
# File lib/dependabot/cargo/update_checker.rb, line 159
def latest_git_tag_is_resolvable?
  return @git_tag_resolvable if @latest_git_tag_is_resolvable_checked

  @latest_git_tag_is_resolvable_checked = true

  return false if git_commit_checker.local_tag_for_latest_version.nil?

  replacement_tag = git_commit_checker.local_tag_for_latest_version

  prepared_files = FilePreparer.new(
    dependency_files: dependency_files,
    dependency: dependency,
    unlock_requirement: true,
    replacement_git_pin: replacement_tag.fetch(:tag)
  ).prepared_dependency_files

  VersionResolver.new(
    dependency: dependency,
    prepared_dependency_files: prepared_files,
    original_dependency_files: dependency_files,
    credentials: credentials
  ).latest_resolvable_version
  @git_tag_resolvable = true
rescue SharedHelpers::HelperSubprocessFailed => e
  raise e unless e.message.include?("versions conflict")

  @git_tag_resolvable = false
end
latest_git_version_sha() click to toggle source
# File lib/dependabot/cargo/update_checker.rb, line 123
def latest_git_version_sha
  # If the gem isn't pinned, the latest version is just the latest
  # commit for the specified branch.
  return git_commit_checker.head_commit_for_current_branch unless git_commit_checker.pinned?

  # If the dependency is pinned to a tag that looks like a version then
  # we want to update that tag. The latest version will then be the SHA
  # of the latest tag that looks like a version.
  if git_commit_checker.pinned_ref_looks_like_version?
    latest_tag = git_commit_checker.local_tag_for_latest_version
    return latest_tag&.fetch(:commit_sha) || dependency.version
  end

  # If the dependency is pinned to a tag that doesn't look like a
  # version then there's nothing we can do.
  dependency.version
end
latest_resolvable_commit_with_unchanged_git_source() click to toggle source
# File lib/dependabot/cargo/update_checker.rb, line 188
def latest_resolvable_commit_with_unchanged_git_source
  fetch_latest_resolvable_version(unlock_requirement: false)
rescue SharedHelpers::HelperSubprocessFailed => e
  # Resolution may fail, as Cargo updates straight to the tip of the
  # branch. Just return `nil` if it does (so no update).
  return if e.message.include?("versions conflict")

  raise e
end
latest_resolvable_version_for_git_dependency() click to toggle source
# File lib/dependabot/cargo/update_checker.rb, line 141
def latest_resolvable_version_for_git_dependency
  # If the gem isn't pinned, the latest version is just the latest
  # commit for the specified branch.
  return latest_resolvable_commit_with_unchanged_git_source unless git_commit_checker.pinned?

  # If the dependency is pinned to a tag that looks like a version then
  # we want to update that tag. The latest version will then be the SHA
  # of the latest tag that looks like a version.
  if git_commit_checker.pinned_ref_looks_like_version? &&
     latest_git_tag_is_resolvable?
    new_tag = git_commit_checker.local_tag_for_latest_version
    return new_tag.fetch(:commit_sha)
  end

  # If the dependency is pinned then there's nothing we can do.
  dependency.version
end
latest_version_finder() click to toggle source
# File lib/dependabot/cargo/update_checker.rb, line 108
def latest_version_finder
  @latest_version_finder ||= LatestVersionFinder.new(
    dependency: dependency,
    dependency_files: dependency_files,
    credentials: credentials,
    ignored_versions: ignored_versions,
    raise_on_ignored: raise_on_ignored,
    security_advisories: security_advisories
  )
end
latest_version_for_git_dependency() click to toggle source
# File lib/dependabot/cargo/update_checker.rb, line 119
def latest_version_for_git_dependency
  latest_git_version_sha
end
latest_version_resolvable_with_full_unlock?() click to toggle source
# File lib/dependabot/cargo/update_checker.rb, line 84
def latest_version_resolvable_with_full_unlock?
  # Full unlock checks aren't implemented for Rust (yet)
  false
end
library?() click to toggle source
# File lib/dependabot/cargo/update_checker.rb, line 102
def library?
  # If it has a lockfile, treat it as an application. Otherwise treat it
  # as a library.
  dependency_files.none? { |f| f.name == "Cargo.lock" }
end
path_dependency?() click to toggle source
# File lib/dependabot/cargo/update_checker.rb, line 273
def path_dependency?
  sources = dependency.requirements.
            map { |r| r.fetch(:source) }.uniq.compact

  raise "Multiple sources! #{sources.join(', ')}" if sources.count > 1

  sources.first&.fetch(:type) == "path"
end
target_version() click to toggle source
# File lib/dependabot/cargo/update_checker.rb, line 93
def target_version
  # Unless we can resolve a new version, don't try to update to a latest
  # version (even for a library) as we rely on a resolvable version being
  # present in other areas
  return unless preferred_resolvable_version

  library? ? latest_version&.to_s : preferred_resolvable_version.to_s
end
updated_dependencies_after_full_unlock() click to toggle source
# File lib/dependabot/cargo/update_checker.rb, line 89
def updated_dependencies_after_full_unlock
  raise NotImplementedError
end
updated_source() click to toggle source
# File lib/dependabot/cargo/update_checker.rb, line 239
def updated_source
  # Never need to update source, unless a git_dependency
  return dependency_source_details unless git_dependency?

  # Update the git tag if updating a pinned version
  if git_commit_checker.pinned_ref_looks_like_version? &&
     latest_git_tag_is_resolvable?
    new_tag = git_commit_checker.local_tag_for_latest_version
    return dependency_source_details.merge(ref: new_tag.fetch(:tag))
  end

  # Otherwise return the original source
  dependency_source_details
end