diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-05-19 10:33:21 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-05-19 10:33:21 +0300 |
commit | 36a59d088eca61b834191dacea009677a96c052f (patch) | |
tree | e4f33972dab5d8ef79e3944a9f403035fceea43f /app/services/work_items | |
parent | a1761f15ec2cae7c7f7bbda39a75494add0dfd6f (diff) |
Add latest changes from gitlab-org/gitlab@15-0-stable-eev15.0.0-rc42
Diffstat (limited to 'app/services/work_items')
-rw-r--r-- | app/services/work_items/delete_task_service.rb | 45 | ||||
-rw-r--r-- | app/services/work_items/task_list_reference_removal_service.rb | 63 |
2 files changed, 108 insertions, 0 deletions
diff --git a/app/services/work_items/delete_task_service.rb b/app/services/work_items/delete_task_service.rb new file mode 100644 index 00000000000..3bb23576442 --- /dev/null +++ b/app/services/work_items/delete_task_service.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +module WorkItems + class DeleteTaskService + def initialize(work_item:, current_user: nil, task_params: {}, lock_version:) + @work_item = work_item + @current_user = current_user + @task_params = task_params + @lock_version = lock_version + @task = task_params[:task] + @errors = [] + end + + def execute + transaction_result = ::WorkItem.transaction do + replacement_result = TaskListReferenceRemovalService.new( + work_item: @work_item, + task: @task, + line_number_start: @task_params[:line_number_start], + line_number_end: @task_params[:line_number_end], + lock_version: @lock_version, + current_user: @current_user + ).execute + + break ::ServiceResponse.error(message: replacement_result.errors, http_status: 422) if replacement_result.error? + + delete_result = ::WorkItems::DeleteService.new( + project: @task.project, + current_user: @current_user + ).execute(@task) + + if delete_result.error? + @errors += delete_result.errors + raise ActiveRecord::Rollback + end + + delete_result + end + + return transaction_result if transaction_result + + ::ServiceResponse.error(message: @errors, http_status: 422) + end + end +end diff --git a/app/services/work_items/task_list_reference_removal_service.rb b/app/services/work_items/task_list_reference_removal_service.rb new file mode 100644 index 00000000000..e7ec73a96e0 --- /dev/null +++ b/app/services/work_items/task_list_reference_removal_service.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +module WorkItems + class TaskListReferenceRemovalService + STALE_OBJECT_MESSAGE = 'Stale work item. Check lock version' + + def initialize(work_item:, task:, line_number_start:, line_number_end:, lock_version:, current_user:) + @work_item = work_item + @task = task + @line_number_start = line_number_start + @line_number_end = line_number_end + @lock_version = lock_version + @current_user = current_user + end + + def execute + return ::ServiceResponse.error(message: 'line_number_start must be greater than 0') if @line_number_start < 1 + return ::ServiceResponse.error(message: "Work item description can't be blank") if @work_item.description.blank? + + if @line_number_end < @line_number_start + return ::ServiceResponse.error(message: 'line_number_end must be greater or equal to line_number_start') + end + + source_lines = @work_item.description.split("\n") + + line_matches_reference = (@line_number_start..@line_number_end).any? do |line_number| + markdown_line = source_lines[line_number - 1] + + /#{Regexp.escape(@task.to_reference)}(?!\d)/.match?(markdown_line) + end + + unless line_matches_reference + return ::ServiceResponse.error( + message: "Unable to detect a task on lines #{@line_number_start}-#{@line_number_end}" + ) + end + + remove_task_lines!(source_lines) + + ::WorkItems::UpdateService.new( + project: @work_item.project, + current_user: @current_user, + params: { description: source_lines.join("\n"), lock_version: @lock_version } + ).execute(@work_item) + + if @work_item.valid? + ::ServiceResponse.success + else + ::ServiceResponse.error(message: @work_item.errors.full_messages) + end + rescue ActiveRecord::StaleObjectError + ::ServiceResponse.error(message: STALE_OBJECT_MESSAGE) + end + + private + + def remove_task_lines!(source_lines) + source_lines.delete_if.each_with_index do |_line, index| + index >= @line_number_start - 1 && index < @line_number_end + end + end + end +end |