1 import flask
2 from flask import request, render_template, stream_with_context
3
4 from copr_common.enums import StatusEnum
5 from coprs import app
6 from coprs import db
7 from coprs import forms
8 from coprs import helpers
9
10 from coprs.logic import builds_logic
11 from coprs.logic.builds_logic import BuildsLogic
12 from coprs.logic.complex_logic import ComplexLogic
13
14 from coprs.views.misc import (login_required, req_with_copr, send_build_icon)
15 from coprs.views.coprs_ns import coprs_ns
16
17 from coprs.exceptions import (
18 ActionInProgressException,
19 BadRequest,
20 ConflictingRequest,
21 InsufficientRightsException,
22 UnrepeatableBuildException,
23 )
31
32
33 @coprs_ns.route("/build/<int:build_id>/status_image.png")
34 -def copr_build_icon(build_id):
36
37
38
39
40 @coprs_ns.route("/<username>/<coprname>/build/<int:build_id>/")
41 @coprs_ns.route("/g/<group_name>/<coprname>/build/<int:build_id>/")
42 @req_with_copr
43 -def copr_build(copr, build_id):
45
50
51
52
53
54 @coprs_ns.route("/<username>/<coprname>/builds/")
55 @coprs_ns.route("/g/<group_name>/<coprname>/builds/")
56 @req_with_copr
57 -def copr_builds(copr):
58 flashes = flask.session.pop('_flashes', [])
59 dirname = flask.request.args.get('dirname')
60 builds_query = builds_logic.BuildsLogic.get_copr_builds_list(copr, dirname)
61 builds = builds_query.yield_per(1000)
62 response = flask.Response(stream_with_context(helpers.stream_template("coprs/detail/builds.html",
63 copr=copr,
64 builds=builds,
65 current_dirname=dirname,
66 flashes=flashes)))
67
68 flask.session.pop('_flashes', [])
69 return response
70
71
72
73 @coprs_ns.route("/<username>/<coprname>/add_build/")
74 @coprs_ns.route("/g/<group_name>/<coprname>/add_build/")
75 @login_required
76 @req_with_copr
77 -def copr_add_build(copr, form=None):
80
87
88
89 @coprs_ns.route("/<username>/<coprname>/new_build/", methods=["POST"])
90 @coprs_ns.route("/g/<group_name>/<coprname>/new_build/", methods=["POST"])
91 @login_required
92 @req_with_copr
93 -def copr_new_build(copr):
98
101 def factory(**build_options):
102 pkgs = form.pkgs.data.split("\n")
103 for pkg in pkgs:
104 BuildsLogic.create_new_from_url(
105 flask.g.user, copr, pkg,
106 chroot_names=form.selected_chroots,
107 **build_options
108 )
109 for pkg in pkgs:
110 flask.flash("New build has been created: {}".format(pkg), "success")
111
112 form = forms.BuildFormUrlFactory(copr.active_chroots)()
113 return process_new_build(copr, form, factory, render_add_build,
114 add_view, url_on_success, msg_on_success=False)
115
116
117 -def process_new_build(copr, form, create_new_build_factory, add_function, add_view, url_on_success, msg_on_success=True):
118 if form.validate_on_submit():
119 build_options = {
120 "enable_net": form.enable_net.data,
121 "timeout": form.timeout.data,
122 "bootstrap": form.bootstrap.data,
123 "with_build_id": form.with_build_id.data,
124 "after_build_id": form.after_build_id.data,
125 }
126
127 try:
128 create_new_build_factory(**build_options)
129 db.session.commit()
130 except (ActionInProgressException, InsufficientRightsException, UnrepeatableBuildException, BadRequest) as e:
131 db.session.rollback()
132 flask.flash(str(e), "error")
133 else:
134 if msg_on_success:
135 flask.flash("New build has been created.", "success")
136
137 return flask.redirect(url_on_success)
138 else:
139 return add_function(copr, form, add_view)
140
141
142
143
144 @coprs_ns.route("/<username>/<coprname>/add_build_scm/")
145 @coprs_ns.route("/g/<group_name>/<coprname>/add_build_scm/")
146 @login_required
147 @req_with_copr
148 -def copr_add_build_scm(copr, form=None):
151
158
159
160 @coprs_ns.route("/<username>/<coprname>/new_build_scm/", methods=["POST"])
161 @coprs_ns.route("/g/<group_name>/<coprname>/new_build_scm/", methods=["POST"])
162 @login_required
163 @req_with_copr
164 -def copr_new_build_scm(copr):
168
184 form = forms.BuildFormScmFactory(copr.active_chroots)()
185 return process_new_build(copr, form, factory, render_add_build_scm, add_view, url_on_success)
186
187
188
189 @coprs_ns.route("/<username>/<coprname>/add_build_distgit/")
190 @coprs_ns.route("/g/<group_name>/<coprname>/add_build_distgit/")
191 @login_required
192 @req_with_copr
193 -def copr_add_build_distgit(copr, form=None):
197
198 @coprs_ns.route("/<username>/<coprname>/new_build_distgit/", methods=["POST"])
199 @coprs_ns.route("/g/<group_name>/<coprname>/new_build_distgit/", methods=["POST"])
200 @login_required
201 @req_with_copr
202 -def copr_new_build_distgit(copr):
203 """ POST request for distgit build """
204 view = 'coprs_ns.copr_new_build_distgit'
205 url_on_success = helpers.copr_url("coprs_ns.copr_builds", copr)
206 return process_new_build_distgit(copr, view, url_on_success)
207
215
229
230 form = forms.BuildFormDistGitSimpleFactory(copr.active_chroots)()
231 return process_new_build(copr, form, factory, render_add_build_distgit, add_view, url_on_success)
232
233
234
235 @coprs_ns.route("/<username>/<coprname>/add_build_pypi/")
236 @coprs_ns.route("/g/<group_name>/<coprname>/add_build_pypi/")
237 @login_required
238 @req_with_copr
239 -def copr_add_build_pypi(copr, form=None):
242
249
250
251 @coprs_ns.route("/<username>/<coprname>/new_build_pypi/", methods=["POST"])
252 @coprs_ns.route("/g/<group_name>/<coprname>/new_build_pypi/", methods=["POST"])
253 @login_required
254 @req_with_copr
255 -def copr_new_build_pypi(copr):
259
273 form = forms.BuildFormPyPIFactory(copr.active_chroots)()
274 return process_new_build(copr, form, factory, render_add_build_pypi, add_view, url_on_success)
275
276
277
278
279 @coprs_ns.route("/<username>/<coprname>/add_build_rubygems/")
280 @coprs_ns.route("/g/<group_name>/<coprname>/add_build_rubygems/")
281 @login_required
282 @req_with_copr
283 -def copr_add_build_rubygems(copr, form=None):
286
293
294
295 @coprs_ns.route("/<username>/<coprname>/new_build_rubygems/", methods=["POST"])
296 @coprs_ns.route("/g/<group_name>/<coprname>/new_build_rubygems/", methods=["POST"])
297 @login_required
298 @req_with_copr
299 -def copr_new_build_rubygems(copr):
303
314 form = forms.BuildFormRubyGemsFactory(copr.active_chroots)()
315 return process_new_build(copr, form, factory, render_add_build_rubygems, add_view, url_on_success)
316
317
318
319 @coprs_ns.route("/g/<group_name>/<coprname>/new_build_custom/", methods=["POST"])
320 @coprs_ns.route("/<username>/<coprname>/new_build_custom/", methods=["POST"])
321 @login_required
322 @req_with_copr
323 -def copr_new_build_custom(copr):
341
342 form = forms.BuildFormCustomFactory(copr.active_chroots)()
343
344 return process_new_build(copr, form, factory, render_add_build_custom,
345 view, url_on_success)
346
347
348
349 @coprs_ns.route("/g/<group_name>/<coprname>/add_build_custom/")
350 @coprs_ns.route("/<username>/<coprname>/add_build_custom/")
351 @login_required
352 @req_with_copr
353 -def copr_add_build_custom(copr, form=None):
356
362
363
364
365
366 @coprs_ns.route("/<username>/<coprname>/add_build_upload/")
367 @coprs_ns.route("/g/<group_name>/<coprname>/add_build_upload/")
368 @login_required
369 @req_with_copr
370 -def copr_add_build_upload(copr, form=None):
373
380
381
382 @coprs_ns.route("/<username>/<coprname>/new_build_upload/", methods=["POST"])
383 @coprs_ns.route("/g/<group_name>/<coprname>/new_build_upload/", methods=["POST"])
384 @login_required
385 @req_with_copr
386 -def copr_new_build_upload(copr):
390
401 form = forms.BuildFormUploadFactory(copr.active_chroots)()
402 return process_new_build(copr, form, factory, render_add_build_upload, add_view, url_on_success)
403
404
405
406
407 @coprs_ns.route("/<username>/<coprname>/new_build_rebuild/<int:build_id>/", methods=["POST"])
408 @coprs_ns.route("/g/<group_name>/<coprname>/new_build_rebuild/<int:build_id>/", methods=["POST"])
409 @login_required
410 @req_with_copr
411 -def copr_new_build_rebuild(copr, build_id):
415
425
426 form = forms.BuildFormRebuildFactory.create_form_cls(copr.active_chroots)()
427 return process_new_build(copr, form, factory, render_add_build, view, url_on_success)
428
429
430
431
432 @coprs_ns.route("/<username>/<coprname>/repeat_build/<int:build_id>/", methods=["GET", "POST"])
433 @coprs_ns.route("/g/<group_name>/<coprname>/repeat_build/<int:build_id>/", methods=["GET", "POST"])
434 @login_required
435 @req_with_copr
436 -def copr_repeat_build(copr, build_id):
438
441 build = ComplexLogic.get_build_safe(build_id)
442 if not flask.g.user.can_build_in(build.copr):
443 flask.flash("You are not allowed to repeat this build.")
444
445 if build.source_type == helpers.BuildSourceEnum('upload'):
446
447
448 available_chroots = build.chroots
449
450 else:
451
452
453 available_chroots = copr.active_chroots
454
455
456 form = forms.BuildFormRebuildFactory.create_form_cls(available_chroots)(
457 build_id=build_id, enable_net=build.enable_net)
458
459
460 for ch in available_chroots:
461 field = getattr(form, ch.name)
462 field.data = False
463 chroot_to_build = request.args.get("chroot")
464 app.logger.debug("got param chroot: {}".format(chroot_to_build))
465 if chroot_to_build:
466
467 if hasattr(form, chroot_to_build):
468 getattr(form, chroot_to_build).data = True
469 else:
470 build_chroot_names = set(ch.name for ch in build.chroots)
471 build_failed_chroot_names = set(ch.name for ch in build.get_chroots_by_status([
472 StatusEnum('failed'), StatusEnum('canceled'),
473 ]))
474 for ch in available_chroots:
475
476 if (ch.name not in build_chroot_names) or (ch.name in build_failed_chroot_names):
477 getattr(form, ch.name).data = True
478 return flask.render_template(
479 "coprs/detail/add_build/rebuild.html",
480 copr=copr, build=build, form=form)
481
494
495
496 @coprs_ns.route("/<username>/<coprname>/cancel_build/<int:build_id>/", methods=["POST"])
497 @coprs_ns.route("/g/<group_name>/<coprname>/cancel_build/<int:build_id>/", methods=["POST"])
498 @login_required
499 @req_with_copr
500 -def copr_cancel_build(copr, build_id):
504
505
506
507
508 @coprs_ns.route("/<username>/<coprname>/delete_build/<int:build_id>/",
509 methods=["POST"])
523
524
525
526 @coprs_ns.route("/<username>/<coprname>/delete_builds/", methods=["POST"])
527 @coprs_ns.route("/g/<group_name>/<coprname>/delete_builds/", methods=["POST"])
528 @login_required
529 @req_with_copr
530 -def copr_delete_builds(copr):
531 build_ids = flask.request.form.getlist("build_ids[]")
532
533 to_delete = []
534 for build_id in build_ids:
535 to_delete.append(int(build_id))
536
537 try:
538 builds_logic.BuildsLogic.delete_builds(flask.g.user, to_delete)
539
540 db.session.commit()
541 build_ids_str = ", ".join(build_ids).strip(", ")
542 flask.flash("Builds {} have been deleted successfully.".format(build_ids_str), "success")
543 return flask.jsonify({"msg": "success"})
544 except BadRequest as e:
545 flask.flash(e, "error")
546 return flask.jsonify({"msg": "error"})
547