diff --git a/swift/lib/dependabot/swift/native_requirement.rb b/swift/lib/dependabot/swift/native_requirement.rb index cde4864e7b94..246a2af585e5 100644 --- a/swift/lib/dependabot/swift/native_requirement.rb +++ b/swift/lib/dependabot/swift/native_requirement.rb @@ -2,13 +2,26 @@ require "dependabot/utils" require "dependabot/swift/requirement" -require "dependabot/swift/version" module Dependabot module Swift class NativeRequirement attr_reader :declaration + def self.map_requirements(requirements) + requirements.map do |requirement| + declaration = new(requirement[:metadata][:requirement_string]) + + new_declaration = yield(declaration) + new_requirement = new(new_declaration) + + requirement.merge( + requirement: new_requirement.to_s, + metadata: { requirement_string: new_declaration } + ) + end + end + def initialize(declaration) @declaration = declaration @@ -23,26 +36,24 @@ def to_s requirement.to_s end - def bump_to_satisfy(str) - version = Version.new(str) + def update_if_needed(version) + return declaration if requirement.satisfied_by?(version) - return self if requirement.satisfied_by?(version) + update(version) + end - new_declaration = if up_to_next_major? - new_version = min.end_with?(".0.0") ? "#{version.segments.first}.0.0" : str - declaration.sub(min, new_version) + def update(version) + if up_to_next_major? + declaration.sub(min, version.to_s) elsif up_to_next_minor? - new_version = min.end_with?(".0") ? "#{version.segments.first}.#{version.segments.second}.0" : str - declaration.sub(min, new_version) + declaration.sub(min, version.to_s) elsif inclusive_range? - declaration.sub(max, str) + declaration.sub(max, version.to_s) elsif exclusive_range? - declaration.sub(max, bump_major(str)) + declaration.sub(max, bump_major(version.to_s)) elsif exact_version? - declaration.sub(min, str) + declaration.sub(min, version.to_s) end - - self.class.new(new_declaration) end private diff --git a/swift/lib/dependabot/swift/update_checker.rb b/swift/lib/dependabot/swift/update_checker.rb index ca5ed7c9040d..809db22a1a64 100644 --- a/swift/lib/dependabot/swift/update_checker.rb +++ b/swift/lib/dependabot/swift/update_checker.rb @@ -3,11 +3,13 @@ require "dependabot/update_checkers" require "dependabot/update_checkers/base" require "dependabot/git_commit_checker" +require "dependabot/swift/native_requirement" require "dependabot/swift/file_updater/manifest_updater" module Dependabot module Swift class UpdateChecker < Dependabot::UpdateCheckers::Base + require_relative "update_checker/requirements_updater" require_relative "update_checker/version_resolver" def latest_version @@ -31,10 +33,11 @@ def lowest_resolvable_security_fix_version end def updated_requirements - map_requirements do |requirement| - parsed_requirement = NativeRequirement.new(requirement[:metadata][:requirement_string]) - parsed_requirement.bump_to_satisfy(preferred_resolvable_version) - end + RequirementsUpdater.new( + requirements: old_requirements, + target_version: preferred_resolvable_version, + update_strategy: requirements_update_strategy + ).updated_requirements end def requirements_unlocked_or_can_be? @@ -55,17 +58,6 @@ def old_requirements dependency.requirements end - def map_requirements - old_requirements.map do |old_requirement| - new_requirement = yield(old_requirement) - - old_requirement.merge( - requirement: new_requirement.to_s, - metadata: { requirement_string: new_requirement.declaration } - ) - end - end - def fetch_latest_version return unless git_commit_checker.pinned_ref_looks_like_version? && latest_version_tag @@ -96,14 +88,14 @@ def version_resolver_for(requirements) end def unlocked_requirements - map_requirements do |_old_requirement| - NativeRequirement.new("\"#{dependency.version}\"...\"#{latest_version}\"") + NativeRequirement.map_requirements(old_requirements) do |_old_requirement| + "\"#{dependency.version}\"...\"#{latest_version}\"" end end def force_lowest_security_fix_requirements - map_requirements do |_old_requirement| - NativeRequirement.new("exact: \"#{lowest_security_fix_version}\"") + NativeRequirement.map_requirements(old_requirements) do |_old_requirement| + "exact: \"#{lowest_security_fix_version}\"" end end diff --git a/swift/lib/dependabot/swift/update_checker/requirements_updater.rb b/swift/lib/dependabot/swift/update_checker/requirements_updater.rb new file mode 100644 index 000000000000..8fc2692135a6 --- /dev/null +++ b/swift/lib/dependabot/swift/update_checker/requirements_updater.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +require "dependabot/update_checkers/base" +require "dependabot/swift/native_requirement" +require "dependabot/swift/version" + +module Dependabot + module Swift + class UpdateChecker < Dependabot::UpdateCheckers::Base + class RequirementsUpdater + ALLOWED_UPDATE_STRATEGIES = + %i(lockfile_only bump_versions bump_versions_if_necessary).freeze + + def initialize(requirements:, update_strategy:, target_version:) + @requirements = requirements + @update_strategy = update_strategy + + check_update_strategy + + return unless target_version && Version.correct?(target_version) + + @target_version = Version.new(target_version) + end + + def updated_requirements + return requirements if update_strategy == :lockfile_only + + NativeRequirement.map_requirements(requirements) do |requirement| + if update_strategy == :bump_versions_if_necessary + requirement.update_if_needed(target_version) + else + requirement.update(target_version) + end + end + end + + private + + attr_reader :requirements, :update_strategy, :target_version + + def check_update_strategy + return if ALLOWED_UPDATE_STRATEGIES.include?(update_strategy) + + raise "Unknown update strategy: #{update_strategy}" + end + end + end + end +end