class Dependabot::Maven::UpdateChecker::VersionFinder

Constants

TYPE_SUFFICES

Attributes

credentials[R]
dependency[R]
dependency_files[R]
forbidden_urls[R]
ignored_versions[R]
security_advisories[R]

Public Class Methods

new(dependency:, dependency_files:, credentials:, ignored_versions:, security_advisories:, raise_on_ignored: false) click to toggle source
# File lib/dependabot/maven/update_checker/version_finder.rb, line 18
def initialize(dependency:, dependency_files:, credentials:,
               ignored_versions:, security_advisories:,
               raise_on_ignored: false)
  @dependency          = dependency
  @dependency_files    = dependency_files
  @credentials         = credentials
  @ignored_versions    = ignored_versions
  @raise_on_ignored    = raise_on_ignored
  @security_advisories = security_advisories
  @forbidden_urls      = []
end

Public Instance Methods

latest_version_details() click to toggle source
# File lib/dependabot/maven/update_checker/version_finder.rb, line 30
def latest_version_details
  possible_versions = versions

  possible_versions = filter_prereleases(possible_versions)
  possible_versions = filter_date_based_versions(possible_versions)
  possible_versions = filter_version_types(possible_versions)
  possible_versions = filter_ignored_versions(possible_versions)

  possible_versions.reverse.find { |v| released?(v.fetch(:version)) }
end
lowest_security_fix_version_details() click to toggle source
# File lib/dependabot/maven/update_checker/version_finder.rb, line 41
def lowest_security_fix_version_details
  possible_versions = versions

  possible_versions = filter_prereleases(possible_versions)
  possible_versions = filter_date_based_versions(possible_versions)
  possible_versions = filter_version_types(possible_versions)
  possible_versions = Dependabot::UpdateCheckers::VersionFilters.filter_vulnerable_versions(possible_versions,
                                                                                            security_advisories)
  possible_versions = filter_ignored_versions(possible_versions)
  possible_versions = filter_lower_versions(possible_versions)

  possible_versions.find { |v| released?(v.fetch(:version)) }
end
versions() click to toggle source
# File lib/dependabot/maven/update_checker/version_finder.rb, line 55
def versions
  version_details =
    repositories.map do |repository_details|
      url = repository_details.fetch("url")
      dependency_metadata(repository_details).
        css("versions > version").
        select { |node| version_class.correct?(node.content) }.
        map { |node| version_class.new(node.content) }.
        map { |version| { version: version, source_url: url } }
    end.flatten

  raise PrivateSourceAuthenticationFailure, forbidden_urls.first if version_details.none? && forbidden_urls.any?

  version_details.sort_by { |details| details.fetch(:version) }
end

Private Instance Methods

auth_headers(maven_repo_url) click to toggle source
# File lib/dependabot/maven/update_checker/version_finder.rb, line 284
def auth_headers(maven_repo_url)
  auth_headers_finder.auth_headers(maven_repo_url)
end
auth_headers_finder() click to toggle source
# File lib/dependabot/maven/update_checker/version_finder.rb, line 280
def auth_headers_finder
  @auth_headers_finder ||= Utils::AuthHeadersFinder.new(credentials)
end
central_repo_urls() click to toggle source
# File lib/dependabot/maven/update_checker/version_finder.rb, line 272
def central_repo_urls
  central_url_without_protocol =
    Maven::FileParser::RepositoriesFinder::CENTRAL_REPO_URL.
    gsub(%r{^.*://}, "")

  %w(http:// https://).map { |p| p + central_url_without_protocol }
end
check_response(response, repository_url) click to toggle source
# File lib/dependabot/maven/update_checker/version_finder.rb, line 178
def check_response(response, repository_url)
  return unless [401, 403].include?(response.status)
  return if @forbidden_urls.include?(repository_url)
  return if central_repo_urls.include?(repository_url)

  @forbidden_urls << repository_url
end
credentials_repository_details() click to toggle source
# File lib/dependabot/maven/update_checker/version_finder.rb, line 210
def credentials_repository_details
  credentials.
    select { |cred| cred["type"] == "maven_repository" }.
    map do |cred|
      {
        "url" => cred.fetch("url").gsub(%r{/+$}, ""),
        "auth_headers" => auth_headers(cred.fetch("url").gsub(%r{/+$}, ""))
      }
    end
end
dependency_files_url(repository_url, version) click to toggle source
# File lib/dependabot/maven/update_checker/version_finder.rb, line 255
def dependency_files_url(repository_url, version)
  group_id, artifact_id, classifier = dependency.name.split(":")
  type = dependency.requirements.first.
         dig(:metadata, :packaging_type)

  actual_classifier = classifier.nil? ? "" : "-#{classifier}"
  "#{repository_url}/"\
  "#{group_id.tr('.', '/')}/"\
  "#{artifact_id}/"\
  "#{version}/"\
  "#{artifact_id}-#{version}#{actual_classifier}.#{type}"
end
dependency_metadata(repository_details) click to toggle source
# File lib/dependabot/maven/update_checker/version_finder.rb, line 156
def dependency_metadata(repository_details)
  @dependency_metadata ||= {}
  @dependency_metadata[repository_details.hash] ||=
    begin
      response = Excon.get(
        dependency_metadata_url(repository_details.fetch("url")),
        idempotent: true,
        **Dependabot::SharedHelpers.excon_defaults(headers: repository_details.fetch("auth_headers"))
      )
      check_response(response, repository_details.fetch("url"))

      Nokogiri::XML(response.body)
    rescue URI::InvalidURIError
      Nokogiri::XML("")
    rescue Excon::Error::Socket, Excon::Error::Timeout,
           Excon::Error::TooManyRedirects
      raise if central_repo_urls.include?(repository_details["url"])

      Nokogiri::XML("")
    end
end
dependency_metadata_url(repository_url) click to toggle source
# File lib/dependabot/maven/update_checker/version_finder.rb, line 246
def dependency_metadata_url(repository_url)
  group_id, artifact_id, _classifier = dependency.name.split(":")

  "#{repository_url}/"\
  "#{group_id.tr('.', '/')}/"\
  "#{artifact_id}/"\
  "maven-metadata.xml"
end
filter_date_based_versions(possible_versions) click to toggle source
# File lib/dependabot/maven/update_checker/version_finder.rb, line 82
def filter_date_based_versions(possible_versions)
  return possible_versions if wants_date_based_version?

  possible_versions.
    reject { |v| v.fetch(:version) > version_class.new(1900) }
end
filter_ignored_versions(possible_versions) click to toggle source
# File lib/dependabot/maven/update_checker/version_finder.rb, line 94
def filter_ignored_versions(possible_versions)
  filtered = possible_versions

  ignored_versions.each do |req|
    ignore_requirements = Maven::Requirement.requirements_array(req)
    filtered =
      filtered.
      reject { |v| ignore_requirements.any? { |r| r.satisfied_by?(v.fetch(:version)) } }
  end

  if @raise_on_ignored && filter_lower_versions(filtered).empty? &&
     filter_lower_versions(possible_versions).any?
    raise AllVersionsIgnored
  end

  filtered
end
filter_lower_versions(possible_versions) click to toggle source
# File lib/dependabot/maven/update_checker/version_finder.rb, line 112
def filter_lower_versions(possible_versions)
  return possible_versions unless dependency.version && version_class.correct?(dependency.version)

  possible_versions.select do |v|
    v.fetch(:version) > version_class.new(dependency.version)
  end
end
filter_prereleases(possible_versions) click to toggle source
# File lib/dependabot/maven/update_checker/version_finder.rb, line 76
def filter_prereleases(possible_versions)
  return possible_versions if wants_prerelease?

  possible_versions.reject { |v| v.fetch(:version).prerelease? }
end
filter_version_types(possible_versions) click to toggle source
# File lib/dependabot/maven/update_checker/version_finder.rb, line 89
def filter_version_types(possible_versions)
  possible_versions.
    select { |v| matches_dependency_version_type?(v.fetch(:version)) }
end
matches_dependency_version_type?(comparison_version) click to toggle source
# File lib/dependabot/maven/update_checker/version_finder.rb, line 221
def matches_dependency_version_type?(comparison_version)
  return true unless dependency.version

  current_type = dependency.version.
                 gsub("native-mt", "native_mt").
                 split(/[.\-]/).
                 find do |type|
                   TYPE_SUFFICES.find { |s| type.include?(s) }
                 end

  version_type = comparison_version.to_s.
                 gsub("native-mt", "native_mt").
                 split(/[.\-]/).
                 find do |type|
                   TYPE_SUFFICES.find { |s| type.include?(s) }
                 end

  current_type == version_type
end
pom() click to toggle source
# File lib/dependabot/maven/update_checker/version_finder.rb, line 241
def pom
  filename = dependency.requirements.first.fetch(:file)
  dependency_files.find { |f| f.name == filename }
end
pom_repository_details() click to toggle source
# File lib/dependabot/maven/update_checker/version_finder.rb, line 200
def pom_repository_details
  @pom_repository_details ||=
    Maven::FileParser::RepositoriesFinder.
    new(dependency_files: dependency_files).
    repository_urls(pom: pom).
    map do |url|
      { "url" => url, "auth_headers" => {} }
    end
end
released?(version) click to toggle source
# File lib/dependabot/maven/update_checker/version_finder.rb, line 134
def released?(version)
  @released_check ||= {}
  return @released_check[version] if @released_check.key?(version)

  @released_check[version] =
    repositories.any? do |repository_details|
      url = repository_details.fetch("url")
      response = Excon.head(
        dependency_files_url(url, version),
        idempotent: true,
        **SharedHelpers.excon_defaults(headers: repository_details.fetch("auth_headers"))
      )

      response.status < 400
    rescue Excon::Error::Socket, Excon::Error::Timeout,
           Excon::Error::TooManyRedirects
      false
    rescue URI::InvalidURIError => e
      raise DependencyFileNotResolvable, e.message
    end
end
repositories() click to toggle source
# File lib/dependabot/maven/update_checker/version_finder.rb, line 186
def repositories
  return @repositories if @repositories

  details = pom_repository_details + credentials_repository_details

  @repositories =
    details.reject do |repo|
      next if repo["auth_headers"]

      # Reject this entry if an identical one with non-empty auth_headers exists
      details.any? { |r| r["url"] == repo["url"] && r["auth_headers"] != {} }
    end
end
version_class() click to toggle source
# File lib/dependabot/maven/update_checker/version_finder.rb, line 268
def version_class
  Maven::Version
end
wants_date_based_version?() click to toggle source
# File lib/dependabot/maven/update_checker/version_finder.rb, line 127
def wants_date_based_version?
  return false unless dependency.version
  return false unless version_class.correct?(dependency.version)

  version_class.new(dependency.version) >= version_class.new(100)
end
wants_prerelease?() click to toggle source
# File lib/dependabot/maven/update_checker/version_finder.rb, line 120
def wants_prerelease?
  return false unless dependency.version
  return false unless version_class.correct?(dependency.version)

  version_class.new(dependency.version).prerelease?
end