# frozen_string_literal: true require "dependabot/utils/java/version" module Dependabot module Utils module Java class Requirement < Gem::Requirement quoted = OPS.keys.map { |k| Regexp.quote k }.join("|") PATTERN_RAW = "\\s*(#{quoted})?\\s*(#{Utils::Java::Version::VERSION_PATTERN})\\s*" PATTERN = /\A#{PATTERN_RAW}\z/.freeze def self.parse(obj) if obj.is_a?(Gem::Version) return ["=", Utils::Java::Version.new(obj.to_s)] end unless (matches = PATTERN.match(obj.to_s)) msg = "Illformed requirement [#{obj.inspect}]" raise BadRequirementError, msg end return DefaultRequirement if matches[1] == ">=" && matches[2] == "0" [matches[1] || "=", Utils::Java::Version.new(matches[2])] end def self.requirements_array(requirement_string) split_java_requirement(requirement_string).map do |str| new(str) end end def initialize(*requirements) requirements = requirements.flatten.flat_map do |req_string| convert_java_constraint_to_ruby_constraint(req_string) end super(requirements) end def satisfied_by?(version) version = Utils::Java::Version.new(version.to_s) super end private def self.split_java_requirement(req_string) req_string.split(/(?<=\]|\)),/).flat_map do |str| next str if str.start_with?("(", "[") exacts, *rest = str.split(/,(?=\[|\()/) [*exacts.split(","), *rest] end end private_class_method :split_java_requirement def convert_java_constraint_to_ruby_constraint(req_string) return unless req_string if self.class.send(:split_java_requirement, req_string).count > 1 raise "Can't convert multiple Java reqs to a single Ruby one" end if req_string&.include?(",") return convert_java_range_to_ruby_range(req_string) end convert_java_equals_req_to_ruby(req_string) end def convert_java_range_to_ruby_range(req_string) lower_b, upper_b = req_string.split(",").map(&:strip) lower_b = if ["(", "["].include?(lower_b) then nil elsif lower_b.start_with?("(") then "> #{lower_b.sub(/\(\s*/, '')}" else ">= #{lower_b.sub(/\[\s*/, '').strip}" end upper_b = if [")", "]"].include?(upper_b) then nil elsif upper_b.end_with?(")") then "< #{upper_b.sub(/\s*\)/, '')}" else "<= #{upper_b.sub(/\s*\]/, '').strip}" end [lower_b, upper_b].compact end def convert_java_equals_req_to_ruby(req_string) return convert_wildcard_req(req_string) if req_string&.include?("+") # If a soft requirement is being used, treat it as an equality matcher return req_string unless req_string&.start_with?("[") req_string.gsub(/[\[\]\(\)]/, "") end def convert_wildcard_req(req_string) version = req_string.gsub(/(?:\.|^)\+/, "") return ">= 0" if version.empty? "~> #{version}.0" end end end end end