/
bs_request_action_maintenance_incident.rb
259 lines (224 loc) · 10.6 KB
/
bs_request_action_maintenance_incident.rb
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
class BsRequestActionMaintenanceIncident < BsRequestAction
#### Includes and extends
include BsRequestAction::Differ
#### Constants
#### Self config
class NoMaintenanceReleaseTarget < APIError
setup 'no_maintenance_release_target'
end
#### Attributes
#### Associations macros (Belongs to, Has one, Has many)
#### Callbacks macros: before_save, after_save, etc.
#### Scopes (first the default_scope macro if is used)
#### Validations macros
#### Class methods using self. (public and then private)
def self.sti_name
:maintenance_incident
end
#### To define class methods as private use private_class_method
#### private
#### Instance methods (public and then protected/private)
def is_maintenance_incident?
true
end
def uniq_key
# source_package should be actually release_name, but this would be a speed burden here atm.
"#{target_project}/#{source_package}/#{target_releaseproject}"
end
def get_releaseproject(pkg, tprj)
return if pkg.is_patchinfo?
releaseproject = target_releaseproject ? Project.get_by_name(target_releaseproject) : tprj
if releaseproject.try(:name).blank?
raise NoMaintenanceReleaseTarget, 'Maintenance incident request contains no defined release ' \
"target project for package #{pkg.name}"
end
# Automatically switch to update project
releaseproject = releaseproject.update_instance_or_self
unless releaseproject.is_maintenance_release?
raise NoMaintenanceReleaseTarget, 'Maintenance incident request contains release target ' \
"project #{releaseproject.name} with invalid project " \
"kind \"#{releaseproject.kind}\" (should be " \
"\"maintenance_release\") for package #{pkg.name}"
end
releaseproject
end
def sourcediff(opts = {})
unless opts[:view] == 'xml'
# skip local links
hash = Directory.hashed(project: source_project, package: source_package)
return '' if hash['linkinfo'] && hash['linkinfo']['project'] == source_project
end
super(opts)
end
def merge_into_maintenance_incident(incident_project)
# copy all or selected packages and project source files from base project
# we don't branch from it to keep the link target.
pkg = _merge_pkg_into_maintenance_incident(incident_project)
incident_project.save!
incident_project.store(comment: "maintenance_incident request #{bs_request.number}", request: bs_request)
pkg
end
def execute_accept(opts)
# create or merge into incident project
incident_project = Project.get_by_name(target_project)
# the incident got created before
self.target_package = merge_into_maintenance_incident(incident_project)
# update action with real target project
self.target_project = incident_project.name
source_cleanup if sourceupdate == 'cleanup'
# create a patchinfo if missing and incident has just been created
Patchinfo.new.create_patchinfo_from_request(incident_project, bs_request) if opts[:check_for_patchinfo] && !incident_project.packages.joins(:package_kinds).where("kind = 'patchinfo'").exists?
save
end
def expand_targets(ignore_build_state, ignore_delegate)
# find maintenance project
maintenance_project = nil
if target_project
maintenance_project = Project.get_by_name(target_project)
else
maintenance_project = Project.get_maintenance_project!
self.target_project = maintenance_project.name
end
unless maintenance_project.is_maintenance_incident? || maintenance_project.is_maintenance?
raise NoMaintenanceProject,
'Maintenance incident requests have to go to projects of type maintenance or maintenance_incident'
end
raise IllegalRequest, 'Target package must not be specified in maintenance_incident actions' if target_package
super(ignore_build_state, ignore_delegate)
end
def name
"Incident #{uniq_key}"
end
def short_name
"Incident #{source_package}"
end
private
def _merge_pkg_into_maintenance_incident(incident_project)
# recreate package based on link target and throw everything away, except source changes
# silently as maintenance teams requests ...
new_pkg = nil
# find link target
dir_hash = Directory.hashed(project: source_project, package: source_package)
linkinfo = dir_hash['linkinfo']
if linkinfo && linkinfo['project'] == source_project
# local link, skip it, it will come via branch command
return
end
kinds = Package.detect_package_kinds(dir_hash)
pkg_title = ''
pkg_description = ''
# patchinfos are handled as new packages
if kinds.include?('patchinfo')
if Package.exists_by_project_and_name(incident_project.name, source_package, follow_project_links: false)
new_pkg = Package.get_by_project_and_name(incident_project.name, source_package, use_source: false, follow_project_links: false)
else
new_pkg = incident_project.packages.create(name: source_package, title: pkg_title, description: pkg_description)
new_pkg.flags.create(status: 'enable', flag: 'build')
new_pkg.flags.create(status: 'enable', flag: 'publish') unless incident_project.flags.find_by_flag_and_status('access', 'disable')
new_pkg.store(comment: "maintenance_incident request #{bs_request.number}", request: bs_request)
end
# use specified release project if defined
elsif target_releaseproject
package_name = source_package
package_name = linkinfo['package'] if linkinfo
branch_params = { target_project: incident_project.name,
olinkrev: 'base',
requestid: bs_request.number,
maintenance: 1,
force: 1,
newinstance: 1,
comment: 'Initial new branch from specified release project',
project: target_releaseproject, package: package_name }
# accept branching from former update incidents or GM (for kgraft case)
linkprj = Project.find_by_name(linkinfo['project']) if linkinfo
if defined?(linkprj) && linkprj && (linkprj.is_maintenance_incident? || linkprj != linkprj.update_instance_or_self || kinds.include?('channel'))
branch_params[:project] = linkinfo['project']
branch_params[:ignoredevel] = '1'
end
# it is fine to have new packages
branch_params[:missingok] = 1 unless Package.exists_by_project_and_name(branch_params[:project], package_name)
ret = BranchPackage.new(branch_params).branch
new_pkg = Package.get_by_project_and_name(ret[:data][:targetproject], ret[:data][:targetpackage])
# use link target as fallback
elsif linkinfo && !linkinfo['missingok']
# linked to an existing package in an external project
linked_project = linkinfo['project']
linked_package = linkinfo['package']
branch_params = { target_project: incident_project.name,
olinkrev: 'base',
requestid: bs_request.number,
maintenance: 1,
force: 1,
comment: 'Initial new branch',
project: linked_project, package: linked_package }
ret = BranchPackage.new(branch_params).branch
new_pkg = Package.get_by_project_and_name(ret[:data][:targetproject], ret[:data][:targetpackage])
elsif linkinfo && linkinfo['package'] # a new package for all targets
if Package.exists_by_project_and_name(incident_project.name, source_package, follow_project_links: false)
new_pkg = Package.get_by_project_and_name(incident_project.name, source_package, use_source: false, follow_project_links: false)
else
new_pkg = Package.new(name: source_package, title: pkg.title, description: pkg.description)
incident_project.packages << new_pkg
new_pkg.store(comment: "maintenance_incident request #{bs_request.number}", request: bs_request)
end
else
# no link and not a patchinfo
return # error out instead ?
end
# backend copy of submitted sources, but keep link
cp_params = {
requestid: bs_request.number,
keeplink: 1,
expand: 1,
withacceptinfo: 1,
comment: "Maintenance incident copy from project #{source_project}"
}
cp_params[:orev] = source_rev if source_rev
response = Backend::Api::Sources::Package.copy(incident_project.name, new_pkg.name, source_project, source_package, User.session!.login, cp_params)
result = Xmlhash.parse(response)
set_acceptinfo(result['acceptinfo'])
new_pkg.sources_changed
new_pkg
end
#### Alias of methods
end
# == Schema Information
#
# Table name: bs_request_actions
#
# id :integer not null, primary key
# group_name :string(255)
# makeoriginolder :boolean default(FALSE)
# person_name :string(255)
# role :string(255)
# source_package :string(255) indexed
# source_project :string(255) indexed
# source_rev :string(255)
# sourceupdate :string(255)
# target_package :string(255) indexed
# target_project :string(255) indexed
# target_releaseproject :string(255)
# target_repository :string(255)
# type :string(255)
# updatelink :boolean default(FALSE)
# created_at :datetime
# bs_request_id :integer indexed, indexed => [target_package_id], indexed => [target_project_id]
# target_package_id :integer indexed => [bs_request_id], indexed
# target_project_id :integer indexed => [bs_request_id], indexed
#
# Indexes
#
# bs_request_id (bs_request_id)
# index_bs_request_actions_on_bs_request_id_and_target_package_id (bs_request_id,target_package_id)
# index_bs_request_actions_on_bs_request_id_and_target_project_id (bs_request_id,target_project_id)
# index_bs_request_actions_on_source_package (source_package)
# index_bs_request_actions_on_source_project (source_project)
# index_bs_request_actions_on_target_package (target_package)
# index_bs_request_actions_on_target_package_id (target_package_id)
# index_bs_request_actions_on_target_project (target_project)
# index_bs_request_actions_on_target_project_id (target_project_id)
#
# Foreign Keys
#
# bs_request_actions_ibfk_1 (bs_request_id => bs_requests.id)
#