diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-07-20 18:40:28 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-07-20 18:40:28 +0300 |
commit | b595cb0c1dec83de5bdee18284abe86614bed33b (patch) | |
tree | 8c3d4540f193c5ff98019352f554e921b3a41a72 /lib/gitlab/issuable | |
parent | 2f9104a328fc8a4bddeaa4627b595166d24671d0 (diff) |
Add latest changes from gitlab-org/gitlab@15-2-stable-eev15.2.0-rc42
Diffstat (limited to 'lib/gitlab/issuable')
-rw-r--r-- | lib/gitlab/issuable/clone/attributes_rewriter.rb | 66 | ||||
-rw-r--r-- | lib/gitlab/issuable/clone/copy_resource_events_service.rb | 116 |
2 files changed, 182 insertions, 0 deletions
diff --git a/lib/gitlab/issuable/clone/attributes_rewriter.rb b/lib/gitlab/issuable/clone/attributes_rewriter.rb new file mode 100644 index 00000000000..fd9b2f086fc --- /dev/null +++ b/lib/gitlab/issuable/clone/attributes_rewriter.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +module Gitlab + module Issuable + module Clone + class AttributesRewriter + attr_reader :current_user, :original_entity, :target_parent + + def initialize(current_user, original_entity, target_parent) + raise ArgumentError, 'target_parent cannot be nil' if target_parent.nil? + + @current_user = current_user + @original_entity = original_entity + @target_parent = target_parent + end + + def execute(include_milestone: true) + attributes = { label_ids: cloneable_labels.pluck_primary_key } + + if include_milestone + milestone = matching_milestone(original_entity.milestone&.title) + attributes[:milestone_id] = milestone.id if milestone.present? + end + + attributes + end + + private + + def cloneable_labels + params = { + project_id: project&.id, + group_id: group&.id, + title: original_entity.labels.select(:title), + include_ancestor_groups: true + } + + params[:only_group_labels] = true if target_parent.is_a?(Group) + + LabelsFinder.new(current_user, params).execute + end + + def matching_milestone(title) + return if title.blank? + + params = { title: title, project_ids: project&.id, group_ids: group&.id } + + milestones = MilestonesFinder.new(params).execute + milestones.first + end + + def project + target_parent if target_parent.is_a?(Project) + end + + def group + if target_parent.is_a?(Group) + target_parent + elsif target_parent&.group && current_user.can?(:read_group, target_parent.group) + target_parent.group + end + end + end + end + end +end diff --git a/lib/gitlab/issuable/clone/copy_resource_events_service.rb b/lib/gitlab/issuable/clone/copy_resource_events_service.rb new file mode 100644 index 00000000000..563805fcb01 --- /dev/null +++ b/lib/gitlab/issuable/clone/copy_resource_events_service.rb @@ -0,0 +1,116 @@ +# frozen_string_literal: true + +module Gitlab + module Issuable + module Clone + class CopyResourceEventsService + attr_reader :current_user, :original_entity, :new_entity + + def initialize(current_user, original_entity, new_entity) + @current_user = current_user + @original_entity = original_entity + @new_entity = new_entity + end + + def execute + copy_resource_label_events + copy_resource_milestone_events + copy_resource_state_events + end + + private + + def copy_resource_label_events + copy_events(ResourceLabelEvent.table_name, original_entity.resource_label_events) do |event| + event.attributes + .except('id', 'reference', 'reference_html') + .merge(entity_key => new_entity.id, 'action' => ResourceLabelEvent.actions[event.action]) + end + end + + def copy_resource_milestone_events + return unless milestone_events_supported? + + copy_events(ResourceMilestoneEvent.table_name, original_entity.resource_milestone_events) do |event| + if event.remove? + event_attributes_with_milestone(event, nil) + else + destination_milestone = matching_milestone(event.milestone_title) + + event_attributes_with_milestone(event, destination_milestone) if destination_milestone.present? + end + end + end + + def copy_resource_state_events + return unless state_events_supported? + + copy_events(ResourceStateEvent.table_name, original_entity.resource_state_events) do |event| + event.attributes + .except(*blocked_state_event_attributes) + .merge(entity_key => new_entity.id, + 'state' => ResourceStateEvent.states[event.state]) + end + end + + # Overriden on EE::Gitlab::Issuable::Clone::CopyResourceEventsService + def blocked_state_event_attributes + ['id'] + end + + def event_attributes_with_milestone(event, milestone) + event.attributes + .except('id') + .merge(entity_key => new_entity.id, + 'milestone_id' => milestone&.id, + 'action' => ResourceMilestoneEvent.actions[event.action], + 'state' => ResourceMilestoneEvent.states[event.state]) + end + + def copy_events(table_name, events_to_copy) + events_to_copy.find_in_batches do |batch| + events = batch.map do |event| + yield(event) + end.compact + + ApplicationRecord.legacy_bulk_insert(table_name, events) # rubocop:disable Gitlab/BulkInsert + end + end + + def entity_key + new_entity.class.name.underscore.foreign_key + end + + def milestone_events_supported? + both_respond_to?(:resource_milestone_events) + end + + def state_events_supported? + both_respond_to?(:resource_state_events) + end + + def both_respond_to?(method) + original_entity.respond_to?(method) && + new_entity.respond_to?(method) + end + + def matching_milestone(title) + return if title.blank? || !new_entity.supports_milestone? + + params = { title: title, project_ids: new_entity.project&.id, group_ids: group&.id } + + milestones = MilestonesFinder.new(params).execute + milestones.first + end + + def group + if new_entity.project&.group && current_user.can?(:read_group, new_entity.project.group) + new_entity.project.group + end + end + end + end + end +end + +Gitlab::Issuable::Clone::CopyResourceEventsService.prepend_mod |