debian-mirror-gitlab/app/services/merge_requests/merge_service.rb

152 lines
4.4 KiB
Ruby
Raw Normal View History

2018-11-18 11:00:15 +05:30
# frozen_string_literal: true
2014-09-02 18:07:02 +05:30
module MergeRequests
# MergeService class
#
2015-09-25 12:07:36 +05:30
# Do git merge and in case of success
# mark merge request as merged and execute all hooks and notifications
# Executed when you do merge via GitLab UI
#
class MergeService < MergeRequests::BaseService
2019-03-02 22:35:43 +05:30
include Gitlab::Utils::StrongMemoize
2017-08-17 22:00:37 +05:30
MergeError = Class.new(StandardError)
attr_reader :merge_request, :source
2015-09-25 12:07:36 +05:30
2018-03-17 18:26:18 +05:30
delegate :merge_jid, :state, to: :@merge_request
2015-09-25 12:07:36 +05:30
2018-03-17 18:26:18 +05:30
def execute(merge_request)
if project.merge_requests_ff_only_enabled && !self.is_a?(FfMergeService)
FfMergeService.new(project, current_user, params).execute(merge_request)
return
2017-08-17 22:00:37 +05:30
end
2018-03-17 18:26:18 +05:30
@merge_request = merge_request
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
error_check!
2015-09-25 12:07:36 +05:30
merge_request.in_locked_state do
if commit
after_merge
2018-03-17 18:26:18 +05:30
clean_merge_jid
2015-09-25 12:07:36 +05:30
success
end
end
2018-03-17 18:26:18 +05:30
log_info("Merge process finished on JID #{merge_jid} with state #{state}")
2017-08-17 22:00:37 +05:30
rescue MergeError => e
2018-03-17 18:26:18 +05:30
handle_merge_error(log_message: e.message, save_message_on_model: true)
2015-09-25 12:07:36 +05:30
end
2014-09-02 18:07:02 +05:30
2018-11-08 19:23:39 +05:30
def source
2019-03-02 22:35:43 +05:30
if merge_request.squash
squash_sha!
else
merge_request.diff_head_sha
2018-11-08 19:23:39 +05:30
end
end
2018-12-13 13:39:08 +05:30
# Overridden in EE.
def hooks_validation_pass?(_merge_request)
true
end
2015-09-25 12:07:36 +05:30
private
2018-03-17 18:26:18 +05:30
def error_check!
error =
if @merge_request.should_be_rebased?
'Only fast-forward merge is allowed for your project. Please update your source branch'
elsif !@merge_request.mergeable?
'Merge request is not mergeable'
elsif !source
'No source for merge'
end
raise MergeError, error if error
end
2015-09-25 12:07:36 +05:30
2018-03-17 18:26:18 +05:30
def commit
log_info("Git merge started on JID #{merge_jid}")
2018-10-15 14:42:47 +05:30
commit_id = try_merge
if commit_id
log_info("Git merge finished on JID #{merge_jid} commit #{commit_id}")
else
raise MergeError, 'Conflicts detected during merge'
end
2016-08-24 12:49:21 +05:30
2018-10-15 14:42:47 +05:30
merge_request.update!(merge_commit_sha: commit_id)
end
2019-03-02 22:35:43 +05:30
def squash_sha!
strong_memoize(:squash_sha) do
params[:merge_request] = merge_request
squash_result = ::MergeRequests::SquashService.new(project, current_user, params).execute
case squash_result[:status]
when :success
squash_result[:squash_sha]
when :error
raise ::MergeRequests::MergeService::MergeError, squash_result[:message]
end
end
end
2018-10-15 14:42:47 +05:30
def try_merge
2019-03-02 22:35:43 +05:30
message = params[:commit_message] || merge_request.default_merge_commit_message
2017-08-17 22:00:37 +05:30
2018-10-15 14:42:47 +05:30
repository.merge(current_user, source, merge_request, message)
2018-11-08 19:23:39 +05:30
rescue Gitlab::Git::PreReceiveError => e
2018-10-15 14:42:47 +05:30
handle_merge_error(log_message: e.message)
raise MergeError, 'Something went wrong during merge pre-receive hook'
rescue => e
handle_merge_error(log_message: e.message)
raise MergeError, 'Something went wrong during merge'
2016-08-24 12:49:21 +05:30
ensure
2018-10-15 14:42:47 +05:30
merge_request.update!(in_progress_merge_commit_sha: nil)
2015-09-25 12:07:36 +05:30
end
2014-09-02 18:07:02 +05:30
2015-09-25 12:07:36 +05:30
def after_merge
2018-03-17 18:26:18 +05:30
log_info("Post merge started on JID #{merge_jid} with state #{state}")
2015-09-25 12:07:36 +05:30
MergeRequests::PostMergeService.new(project, current_user).execute(merge_request)
2018-03-17 18:26:18 +05:30
log_info("Post merge finished on JID #{merge_jid} with state #{state}")
2015-12-23 02:04:40 +05:30
2018-03-17 18:26:18 +05:30
if delete_source_branch?
DeleteBranchService.new(@merge_request.source_project, branch_deletion_user)
.execute(merge_request.source_branch)
2015-12-23 02:04:40 +05:30
end
2014-09-02 18:07:02 +05:30
end
2016-06-02 11:05:42 +05:30
2018-03-17 18:26:18 +05:30
def clean_merge_jid
merge_request.update_column(:merge_jid, nil)
end
2016-06-02 11:05:42 +05:30
def branch_deletion_user
@merge_request.force_remove_source_branch? ? @merge_request.author : current_user
end
2016-11-03 12:29:30 +05:30
2018-03-17 18:26:18 +05:30
# Verify again that the source branch can be removed, since branch may be protected,
# or the source branch may have been updated, or the user may not have permission
#
def delete_source_branch?
params.fetch('should_remove_source_branch', @merge_request.force_remove_source_branch?) &&
@merge_request.can_remove_source_branch?(branch_deletion_user)
end
def handle_merge_error(log_message:, save_message_on_model: false)
Rails.logger.error("MergeService ERROR: #{merge_request_info} - #{log_message}")
@merge_request.update(merge_error: log_message) if save_message_on_model
end
2016-11-03 12:29:30 +05:30
2018-03-17 18:26:18 +05:30
def log_info(message)
@logger ||= Rails.logger
@logger.info("#{merge_request_info} - #{message}")
2016-11-03 12:29:30 +05:30
end
def merge_request_info
2017-08-17 22:00:37 +05:30
merge_request.to_reference(full: true)
end
2014-09-02 18:07:02 +05:30
end
end