gitlab-org--gitlab-foss/lib/gitlab/import_export/group_project_object_builde...

93 lines
2.6 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
2018-06-19 07:54:47 +00:00
module Gitlab
module ImportExport
2018-06-22 07:00:10 +00:00
# Given a class, it finds or creates a new object
2018-06-22 09:27:52 +00:00
# (initializes in the case of Label) at group or project level.
# If it does not exist in the group, it creates it at project level.
2018-06-22 07:00:10 +00:00
#
2018-06-22 09:27:52 +00:00
# Example:
# `GroupProjectObjectBuilder.build(Label, label_attributes)`
# finds or initializes a label with the given attributes.
2018-06-22 07:00:10 +00:00
#
# It also adds some logic around Group Labels/Milestones for edge cases.
class GroupProjectObjectBuilder
def self.build(*args)
2018-06-20 08:27:40 +00:00
Project.transaction do
2018-06-22 07:00:10 +00:00
new(*args).find
2018-06-20 08:27:40 +00:00
end
2018-06-19 07:54:47 +00:00
end
def initialize(klass, attributes)
@klass = klass < Label ? Label : klass
2018-06-19 07:54:47 +00:00
@attributes = attributes
2018-06-27 09:53:51 +00:00
@group = @attributes['group']
@project = @attributes['project']
2018-06-19 07:54:47 +00:00
end
2018-06-22 07:00:10 +00:00
def find
2018-06-27 09:53:51 +00:00
find_object || @klass.create(project_attributes)
2018-06-19 07:54:47 +00:00
end
private
2018-06-27 09:53:51 +00:00
def find_object
@klass.where(where_clause).first
2018-06-22 07:00:10 +00:00
end
2018-06-19 07:54:47 +00:00
def where_clause
@attributes.slice('title').map do |key, value|
2018-06-27 09:53:51 +00:00
scope_clause = table[:project_id].eq(@project.id)
scope_clause = scope_clause.or(table[:group_id].eq(@group.id)) if @group
2018-06-19 07:54:47 +00:00
2018-06-27 09:53:51 +00:00
table[key].eq(value).and(scope_clause)
end.reduce(:or)
2018-06-22 07:00:10 +00:00
end
2018-06-19 07:54:47 +00:00
def table
@table ||= @klass.arel_table
end
2018-06-19 13:27:30 +00:00
def project_attributes
2018-06-27 09:53:51 +00:00
@attributes.except('group').tap do |atts|
if label?
atts['type'] = 'ProjectLabel' # Always create project labels
elsif milestone?
if atts['group_id'] # Transform new group milestones into project ones
atts['iid'] = nil
atts.delete('group_id')
else
claim_iid
end
end
2018-06-19 13:27:30 +00:00
end
end
def label?
@klass == Label
2018-06-19 13:27:30 +00:00
end
def milestone?
@klass == Milestone
end
2018-06-27 09:53:51 +00:00
# If an existing group milestone used the IID
# claim the IID back and set the group milestone to use one available
2018-06-27 09:53:51 +00:00
# This is necessary to fix situations like the following:
# - Importing into a user namespace project with exported group milestones
# where the IID of the Group milestone could conflict with a project one.
def claim_iid
2018-06-22 09:27:52 +00:00
# The milestone has to be a group milestone, as it's the only case where
# we set the IID as the maximum. The rest of them are fixed.
2018-06-27 09:53:51 +00:00
milestone = @project.milestones.find_by(iid: @attributes['iid'])
2018-06-27 09:53:51 +00:00
return unless milestone
2018-06-25 07:42:07 +00:00
2018-06-27 09:53:51 +00:00
milestone.iid = nil
milestone.ensure_project_iid!
milestone.save!
end
2018-06-19 07:54:47 +00:00
end
end
end