1 import os
2 import flask
3
4 from werkzeug.datastructures import MultiDict
5 from werkzeug.utils import secure_filename
6
7 from . import get_copr, file_upload, query_params, pagination, Paginator, json2form, GET, POST, PUT, DELETE
8 from .json2form import get_form_compatible_data
9 from copr_common.enums import StatusEnum
10 from coprs import db, forms, models
11 from coprs.exceptions import (BadRequest, AccessRestricted)
12 from coprs.views.misc import api_login_required
13 from coprs.views.apiv3_ns import apiv3_ns
14 from coprs.logic.complex_logic import ComplexLogic
15 from coprs.logic.builds_logic import BuildsLogic
19 return {
20 "id": build.id,
21 "state": build.state,
22 "projectname": build.copr.name,
23 "ownername": build.copr.owner_name,
24 "repo_url": build.copr.repo_url,
25 "source_package": {"name": build.package_name, "version": build.pkg_version, "url": build.srpm_url},
26 "submitted_on": build.submitted_on,
27 "started_on": build.min_started_on,
28 "ended_on": build.max_ended_on,
29 "submitter": build.user.name if build.user else None,
30 "chroots": [chroot.name for chroot in build.build_chroots],
31 "project_dirname": build.copr_dir.name,
32 }
33
43
53
56 replace = {
57 "source_build_method": "srpm_build_method",
58 }
59 output = input.copy()
60 for from_name, to_name in replace.items():
61 if from_name not in output:
62 continue
63 output[to_name] = output.pop(from_name)
64 return output
65
69
70
71 @apiv3_ns.route("/build/<int:build_id>/", methods=GET)
72 -def get_build(build_id):
75
76
77 @apiv3_ns.route("/build/list/", methods=GET)
78 @pagination()
79 @query_params()
80 -def get_build_list(ownername, projectname, packagename=None, status=None, **kwargs):
103
104
105 @apiv3_ns.route("/build/source-chroot/<int:build_id>/", methods=GET)
106 -def get_source_chroot(build_id):
109
115
116
117 @apiv3_ns.route("/build/cancel/<int:build_id>", methods=PUT)
118 @api_login_required
119 -def cancel_build(build_id):
124
125
126 @apiv3_ns.route("/build/create/url", methods=POST)
127 @api_login_required
128 -def create_from_url():
141 return process_creating_new_build(copr, form, create_new_build)
142
143
144 @apiv3_ns.route("/build/create/upload", methods=POST)
145 @api_login_required
146 @file_upload()
147 -def create_from_upload():
159 return process_creating_new_build(copr, form, create_new_build)
160
161
162 @apiv3_ns.route("/build/create/scm", methods=POST)
163 @api_login_required
164 -def create_from_scm():
165 copr = get_copr()
166 data = rename_fields(get_form_compatible_data())
167 form = forms.BuildFormScmFactory(copr.active_chroots)(data, meta={'csrf': False})
168
169 def create_new_build(options):
170 return BuildsLogic.create_new_from_scm(
171 flask.g.user,
172 copr,
173 scm_type=form.scm_type.data,
174 clone_url=form.clone_url.data,
175 committish=form.committish.data,
176 subdirectory=form.subdirectory.data,
177 spec=form.spec.data,
178 srpm_build_method=form.srpm_build_method.data,
179 **options,
180 )
181 return process_creating_new_build(copr, form, create_new_build)
182
204 return process_creating_new_build(copr, form, create_new_build)
205
206 @apiv3_ns.route("/build/create/pypi", methods=POST)
207 @api_login_required
208 -def create_from_pypi():
227 return process_creating_new_build(copr, form, create_new_build)
228
244 return process_creating_new_build(copr, form, create_new_build)
245
246
247 @apiv3_ns.route("/build/create/custom", methods=POST)
248 @api_login_required
249 -def create_from_custom():
264 return process_creating_new_build(copr, form, create_new_build)
265
268 if not form.validate_on_submit():
269 raise BadRequest("Bad request parameters: {0}".format(form.errors))
270
271 if not flask.g.user.can_build_in(copr):
272 raise AccessRestricted("User {} is not allowed to build in the copr: {}"
273 .format(flask.g.user.username, copr.full_name))
274
275 generic_build_options = {
276 'chroot_names': form.selected_chroots,
277 'background': form.background.data,
278 'copr_dirname': form.project_dirname.data,
279 'timeout': form.timeout.data,
280 'bootstrap': form.bootstrap.data,
281 'after_build_id': form.after_build_id.data,
282 'with_build_id': form.with_build_id.data,
283 }
284
285
286
287 build = create_new_build(generic_build_options)
288 db.session.commit()
289
290 if type(build) == list:
291 builds = [build] if type(build) != list else build
292 return flask.jsonify(items=[to_dict(b) for b in builds], meta={})
293 return flask.jsonify(to_dict(build))
294
295
296 @apiv3_ns.route("/build/delete/<int:build_id>", methods=DELETE)
297 @api_login_required
298 -def delete_build(build_id):
304
305
306 @apiv3_ns.route("/build/delete/list", methods=POST)
307 @api_login_required
308 -def delete_builds():
309 """
310 Delete builds specified by a list of IDs.
311 """
312 build_ids = flask.request.json["builds"]
313 BuildsLogic.delete_builds(flask.g.user, build_ids)
314 db.session.commit()
315 return flask.jsonify({"builds": build_ids})
316