1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
module Gitlab
module ImportExport
class RelationFactory
OVERRIDES = { snippets: :project_snippets,
pipelines: 'Ci::Pipeline',
statuses: 'commit_status',
variables: 'Ci::Variable',
triggers: 'Ci::Trigger',
builds: 'Ci::Build',
hooks: 'ProjectHook' }.freeze
USER_REFERENCES = %w[author_id assignee_id updated_by_id user_id].freeze
BUILD_MODELS = %w[Ci::Build commit_status].freeze
def self.create(*args)
new(*args).create
end
def initialize(relation_sym:, relation_hash:, members_mapper:, user:)
@relation_name = OVERRIDES[relation_sym] || relation_sym
@relation_hash = relation_hash.except('id', 'noteable_id')
@members_mapper = members_mapper
@user = user
end
# Creates an object from an actual model with name "relation_sym" with params from
# the relation_hash, updating references with new object IDs, mapping users using
# the "members_mapper" object, also updating notes if required.
def create
set_note_author if @relation_name == :notes
update_user_references
update_project_references
reset_ci_tokens if @relation_name == 'Ci::Trigger'
@relation_hash['data'].deep_symbolize_keys! if @relation_name == :events && @relation_hash['data']
generate_imported_object
end
private
def update_user_references
USER_REFERENCES.each do |reference|
if @relation_hash[reference]
@relation_hash[reference] = @members_mapper.map[@relation_hash[reference]]
end
end
end
# Sets the author for a note. If the user importing the project
# has admin access, an actual mapping with new project members
# will be used. Otherwise, a note stating the original author name
# is left.
def set_note_author
old_author_id = @relation_hash['author_id']
# Users with admin access can map users
@relation_hash['author_id'] = admin_user? ? @members_mapper.map[old_author_id] : @members_mapper.default_user_id
author = @relation_hash.delete('author')
update_note_for_missing_author(author['name']) if missing_author?(old_author_id)
end
def missing_author?(old_author_id)
!admin_user? || @members_mapper.missing_author_ids.include?(old_author_id)
end
def missing_author_note(updated_at, author_name)
timestamp = updated_at.split('.').first
"\n\n *By #{author_name} on #{timestamp} (imported from GitLab project)*"
end
def generate_imported_object
if BUILD_MODELS.include?(@relation_name) # call #trace= method after assigning the other attributes
trace = @relation_hash.delete('trace')
imported_object do |object|
object.trace = trace
object.commit_id = nil
end
else
imported_object
end
end
def update_project_references
project_id = @relation_hash.delete('project_id')
# project_id may not be part of the export, but we always need to populate it if required.
@relation_hash['project_id'] = project_id if relation_class.column_names.include?('project_id')
@relation_hash['gl_project_id'] = project_id if @relation_hash['gl_project_id']
@relation_hash['target_project_id'] = project_id if @relation_hash['target_project_id']
@relation_hash['source_project_id'] = -1 if @relation_hash['source_project_id']
# If source and target are the same, populate them with the new project ID.
if @relation_hash['source_project_id'] && @relation_hash['target_project_id'] &&
@relation_hash['target_project_id'] == @relation_hash['source_project_id']
@relation_hash['source_project_id'] = project_id
end
end
def reset_ci_tokens
return unless Gitlab::ImportExport.reset_tokens?
# If we import/export a project to the same instance, tokens will have to be reset.
@relation_hash['token'] = nil
end
def relation_class
@relation_class ||= @relation_name.to_s.classify.constantize
end
def imported_object
imported_object = relation_class.new(@relation_hash)
yield(imported_object) if block_given?
imported_object.importing = true if imported_object.respond_to?(:importing)
imported_object
end
def update_note_for_missing_author(author_name)
@relation_hash['note'] = '*Blank note*' if @relation_hash['note'].blank?
@relation_hash['note'] += missing_author_note(@relation_hash['updated_at'], author_name)
end
def admin_user?
@user.is_admin?
end
end
end
end
|