diff options
Diffstat (limited to 'app/services/branches/delete_merged_service.rb')
-rw-r--r-- | app/services/branches/delete_merged_service.rb | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/app/services/branches/delete_merged_service.rb b/app/services/branches/delete_merged_service.rb new file mode 100644 index 00000000000..9fd5964bf94 --- /dev/null +++ b/app/services/branches/delete_merged_service.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module Branches + class DeleteMergedService < BaseService + def async_execute + DeleteMergedBranchesWorker.perform_async(project.id, current_user.id) + end + + def execute + raise Gitlab::Access::AccessDeniedError unless can?(current_user, :push_code, project) + + branches = project.repository.merged_branch_names + # Prevent deletion of branches relevant to open merge requests + branches -= merge_request_branch_names + # Prevent deletion of protected branches + branches = branches.reject { |branch| ProtectedBranch.protected?(project, branch) } + + branches.each do |branch| + ::Branches::DeleteService.new(project, current_user).execute(branch) + end + end + + private + + # rubocop: disable CodeReuse/ActiveRecord + def merge_request_branch_names + # reorder(nil) is necessary for SELECT DISTINCT because default scope adds an ORDER BY + source_names = project.origin_merge_requests.opened.reorder(nil).distinct.pluck(:source_branch) + target_names = project.merge_requests.opened.reorder(nil).distinct.pluck(:target_branch) + (source_names + target_names).uniq + end + # rubocop: enable CodeReuse/ActiveRecord + end +end |