2016-08-04 09:20:04 -04:00
|
|
|
module MergeRequests
|
|
|
|
class ResolveService < MergeRequests::BaseService
|
2016-09-01 08:59:10 -04:00
|
|
|
class MissingFiles < Gitlab::Conflict::ResolutionError
|
|
|
|
end
|
|
|
|
|
2016-08-29 07:43:09 -04:00
|
|
|
attr_accessor :conflicts, :rugged, :merge_index, :merge_request
|
2016-08-04 09:20:04 -04:00
|
|
|
|
|
|
|
def execute(merge_request)
|
|
|
|
@conflicts = merge_request.conflicts
|
|
|
|
@rugged = project.repository.rugged
|
|
|
|
@merge_index = conflicts.merge_index
|
2016-08-29 07:43:09 -04:00
|
|
|
@merge_request = merge_request
|
|
|
|
|
|
|
|
fetch_their_commit!
|
2016-08-04 09:20:04 -04:00
|
|
|
|
2016-09-01 08:59:10 -04:00
|
|
|
params[:files].each do |file_params|
|
|
|
|
conflict_file = merge_request.conflicts.file_for_path(file_params[:old_path], file_params[:new_path])
|
|
|
|
|
|
|
|
write_resolved_file_to_index(conflict_file, file_params)
|
|
|
|
end
|
|
|
|
|
|
|
|
unless merge_index.conflicts.empty?
|
|
|
|
missing_files = merge_index.conflicts.map { |file| file[:ours][:path] }
|
|
|
|
|
|
|
|
raise MissingFiles, "Missing resolutions for the following files: #{missing_files.join(', ')}"
|
2016-08-04 09:20:04 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
commit_params = {
|
|
|
|
message: params[:commit_message] || conflicts.default_commit_message,
|
|
|
|
parents: [conflicts.our_commit, conflicts.their_commit].map(&:oid),
|
|
|
|
tree: merge_index.write_tree(rugged)
|
|
|
|
}
|
|
|
|
|
|
|
|
project.repository.resolve_conflicts(current_user, merge_request.source_branch, commit_params)
|
|
|
|
end
|
|
|
|
|
2016-09-01 08:59:10 -04:00
|
|
|
def write_resolved_file_to_index(file, params)
|
|
|
|
new_file = if params[:sections]
|
|
|
|
file.resolve_lines(params[:sections]).map(&:text).join("\n")
|
|
|
|
elsif params[:content]
|
|
|
|
file.resolve_content(params[:content])
|
|
|
|
end
|
|
|
|
|
2016-08-04 09:20:04 -04:00
|
|
|
our_path = file.our_path
|
|
|
|
|
|
|
|
merge_index.add(path: our_path, oid: rugged.write(new_file, :blob), mode: file.our_mode)
|
|
|
|
merge_index.conflict_remove(our_path)
|
|
|
|
end
|
2016-08-29 07:43:09 -04:00
|
|
|
|
|
|
|
# If their commit (in the target project) doesn't exist in the source project, it
|
|
|
|
# can't be a parent for the merge commit we're about to create. If that's the case,
|
|
|
|
# fetch the target branch ref into the source project so the commit exists in both.
|
|
|
|
#
|
|
|
|
def fetch_their_commit!
|
|
|
|
return if rugged.include?(conflicts.their_commit.oid)
|
|
|
|
|
2016-08-30 11:23:45 -04:00
|
|
|
random_string = SecureRandom.hex
|
|
|
|
|
|
|
|
project.repository.fetch_ref(
|
|
|
|
merge_request.target_project.repository.path_to_repo,
|
|
|
|
"refs/heads/#{merge_request.target_branch}",
|
|
|
|
"refs/tmp/#{random_string}/head"
|
|
|
|
)
|
2016-08-29 07:43:09 -04:00
|
|
|
end
|
2016-08-04 09:20:04 -04:00
|
|
|
end
|
|
|
|
end
|