1# frozen_string_literal: true 2 3module Gitlab 4 module Git 5 module Conflict 6 class Resolver 7 include Gitlab::Git::WrapsGitalyErrors 8 9 ConflictSideMissing = Class.new(StandardError) 10 ResolutionError = Class.new(StandardError) 11 12 def initialize(target_repository, our_commit_oid, their_commit_oid, allow_tree_conflicts: false) 13 @target_repository = target_repository 14 @our_commit_oid = our_commit_oid 15 @their_commit_oid = their_commit_oid 16 @allow_tree_conflicts = allow_tree_conflicts 17 end 18 19 def conflicts 20 @conflicts ||= wrapped_gitaly_errors do 21 gitaly_conflicts_client(@target_repository).list_conflict_files(allow_tree_conflicts: @allow_tree_conflicts).to_a 22 rescue GRPC::FailedPrecondition => e 23 raise Gitlab::Git::Conflict::Resolver::ConflictSideMissing, e.message 24 end 25 rescue GRPC::BadStatus => e 26 raise Gitlab::Git::CommandError, e 27 end 28 29 def resolve_conflicts(source_repository, resolution, source_branch:, target_branch:) 30 wrapped_gitaly_errors do 31 gitaly_conflicts_client(source_repository).resolve_conflicts(@target_repository, resolution, source_branch, target_branch) 32 end 33 end 34 35 def conflict_for_path(conflicts, old_path, new_path) 36 conflicts.find do |conflict| 37 conflict.their_path == old_path && conflict.our_path == new_path 38 end 39 end 40 41 private 42 43 def conflict_files(repository, index) 44 index.conflicts.map do |conflict| 45 raise ConflictSideMissing unless conflict[:theirs] && conflict[:ours] 46 47 Gitlab::Git::Conflict::File.new( 48 repository, 49 @our_commit_oid, 50 conflict, 51 index.merge_file(conflict[:ours][:path])[:data] 52 ) 53 end 54 end 55 56 def gitaly_conflicts_client(repository) 57 repository.gitaly_conflicts_client(@our_commit_oid, @their_commit_oid) 58 end 59 end 60 end 61 end 62end 63