1 import flask
2 from flask import request, render_template, url_for, stream_with_context
3 import re
4 import os
5 import shutil
6 import tempfile
7
8 from functools import wraps
9 from werkzeug import secure_filename
10
11 from copr_common.enums import StatusEnum
12 from coprs import app
13 from coprs import db
14 from coprs import forms
15 from coprs import helpers
16
17 from coprs.logic import builds_logic
18 from coprs.logic import coprs_logic
19 from coprs.logic.builds_logic import BuildsLogic
20 from coprs.logic.complex_logic import ComplexLogic
21
22 from coprs.views.misc import (login_required, page_not_found, req_with_copr,
23 req_with_copr, send_build_icon)
24 from coprs.views.coprs_ns import coprs_ns
25
26 from coprs.exceptions import (ActionInProgressException,
27 InsufficientRightsException,
28 UnrepeatableBuildException)
36
37
38 @coprs_ns.route("/build/<int:build_id>/status_image.png")
39 -def copr_build_icon(build_id):
41
42
43
44
45 @coprs_ns.route("/<username>/<coprname>/build/<int:build_id>/")
46 @coprs_ns.route("/g/<group_name>/<coprname>/build/<int:build_id>/")
47 @req_with_copr
48 -def copr_build(copr, build_id):
50
55
56
57
58
59 @coprs_ns.route("/<username>/<coprname>/builds/")
60 @coprs_ns.route("/g/<group_name>/<coprname>/builds/")
61 @req_with_copr
62 -def copr_builds(copr):
64
79
80
81
82 @coprs_ns.route("/<username>/<coprname>/add_build/")
83 @coprs_ns.route("/g/<group_name>/<coprname>/add_build/")
84 @login_required
85 @req_with_copr
86 -def copr_add_build(copr, form=None):
89
96
97
98 @coprs_ns.route("/<username>/<coprname>/new_build/", methods=["POST"])
99 @coprs_ns.route("/g/<group_name>/<coprname>/new_build/", methods=["POST"])
100 @login_required
101 @req_with_copr
102 -def copr_new_build(copr):
107
110 def factory(**build_options):
111 pkgs = form.pkgs.data.split("\n")
112 for pkg in pkgs:
113 BuildsLogic.create_new_from_url(
114 flask.g.user, copr, pkg,
115 chroot_names=form.selected_chroots,
116 **build_options
117 )
118 for pkg in pkgs:
119 flask.flash("New build has been created: {}".format(pkg), "success")
120
121 form = forms.BuildFormUrlFactory(copr.active_chroots)()
122 return process_new_build(copr, form, factory, render_add_build,
123 add_view, url_on_success, msg_on_success=False)
124
125
126 -def process_new_build(copr, form, create_new_build_factory, add_function, add_view, url_on_success, msg_on_success=True):
127 if form.validate_on_submit():
128 build_options = {
129 "enable_net": form.enable_net.data,
130 "timeout": form.timeout.data,
131 }
132
133 try:
134 create_new_build_factory(**build_options)
135 db.session.commit()
136 except (ActionInProgressException, InsufficientRightsException, UnrepeatableBuildException) as e:
137 db.session.rollback()
138 flask.flash(str(e), "error")
139 else:
140 if msg_on_success:
141 flask.flash("New build has been created.", "success")
142
143 return flask.redirect(url_on_success)
144 else:
145 return add_function(copr, form, add_view)
146
147
148
149
150 @coprs_ns.route("/<username>/<coprname>/add_build_scm/")
151 @coprs_ns.route("/g/<group_name>/<coprname>/add_build_scm/")
152 @login_required
153 @req_with_copr
154 -def copr_add_build_scm(copr, form=None):
157
164
165
166 @coprs_ns.route("/<username>/<coprname>/new_build_scm/", methods=["POST"])
167 @coprs_ns.route("/g/<group_name>/<coprname>/new_build_scm/", methods=["POST"])
168 @login_required
169 @req_with_copr
170 -def copr_new_build_scm(copr):
174
190 form = forms.BuildFormScmFactory(copr.active_chroots)()
191 return process_new_build(copr, form, factory, render_add_build_scm, add_view, url_on_success)
192
193
194
195
196 @coprs_ns.route("/<username>/<coprname>/add_build_pypi/")
197 @coprs_ns.route("/g/<group_name>/<coprname>/add_build_pypi/")
198 @login_required
199 @req_with_copr
200 -def copr_add_build_pypi(copr, form=None):
203
210
211
212 @coprs_ns.route("/<username>/<coprname>/new_build_pypi/", methods=["POST"])
213 @coprs_ns.route("/g/<group_name>/<coprname>/new_build_pypi/", methods=["POST"])
214 @login_required
215 @req_with_copr
216 -def copr_new_build_pypi(copr):
220
234 form = forms.BuildFormPyPIFactory(copr.active_chroots)()
235 return process_new_build(copr, form, factory, render_add_build_pypi, add_view, url_on_success)
236
237
238
239
240 @coprs_ns.route("/<username>/<coprname>/add_build_rubygems/")
241 @coprs_ns.route("/g/<group_name>/<coprname>/add_build_rubygems/")
242 @login_required
243 @req_with_copr
244 -def copr_add_build_rubygems(copr, form=None):
247
254
255
256 @coprs_ns.route("/<username>/<coprname>/new_build_rubygems/", methods=["POST"])
257 @coprs_ns.route("/g/<group_name>/<coprname>/new_build_rubygems/", methods=["POST"])
258 @login_required
259 @req_with_copr
260 -def copr_new_build_rubygems(copr):
264
275 form = forms.BuildFormRubyGemsFactory(copr.active_chroots)()
276 return process_new_build(copr, form, factory, render_add_build_rubygems, add_view, url_on_success)
277
278
279
280 @coprs_ns.route("/g/<group_name>/<coprname>/new_build_custom/", methods=["POST"])
281 @coprs_ns.route("/<username>/<coprname>/new_build_custom/", methods=["POST"])
282 @login_required
283 @req_with_copr
284 -def copr_new_build_custom(copr):
302
303 form = forms.BuildFormCustomFactory(copr.active_chroots)()
304
305 return process_new_build(copr, form, factory, render_add_build_custom,
306 view, url_on_success)
307
308
309
310 @coprs_ns.route("/g/<group_name>/<coprname>/add_build_custom/")
311 @coprs_ns.route("/<username>/<coprname>/add_build_custom/")
312 @login_required
313 @req_with_copr
314 -def copr_add_build_custom(copr, form=None):
317
323
324
325
326
327 @coprs_ns.route("/<username>/<coprname>/add_build_upload/")
328 @coprs_ns.route("/g/<group_name>/<coprname>/add_build_upload/")
329 @login_required
330 @req_with_copr
331 -def copr_add_build_upload(copr, form=None):
334
341
342
343 @coprs_ns.route("/<username>/<coprname>/new_build_upload/", methods=["POST"])
344 @coprs_ns.route("/g/<group_name>/<coprname>/new_build_upload/", methods=["POST"])
345 @login_required
346 @req_with_copr
347 -def copr_new_build_upload(copr):
351
362 form = forms.BuildFormUploadFactory(copr.active_chroots)()
363 return process_new_build(copr, form, factory, render_add_build_upload, add_view, url_on_success)
364
365
366
367
368 @coprs_ns.route("/<username>/<coprname>/new_build_rebuild/<int:build_id>/", methods=["POST"])
369 @coprs_ns.route("/g/<group_name>/<coprname>/new_build_rebuild/<int:build_id>/", methods=["POST"])
370 @login_required
371 @req_with_copr
372 -def copr_new_build_rebuild(copr, build_id):
376
386 form = forms.BuildFormRebuildFactory.create_form_cls(copr.active_chroots)()
387 return process_new_build(copr, form, factory, render_add_build, view, url_on_success)
388
389
390
391
392 @coprs_ns.route("/<username>/<coprname>/repeat_build/<int:build_id>/", methods=["GET", "POST"])
393 @coprs_ns.route("/g/<group_name>/<coprname>/repeat_build/<int:build_id>/", methods=["GET", "POST"])
394 @login_required
395 @req_with_copr
396 -def copr_repeat_build(copr, build_id):
398
401 build = ComplexLogic.get_build_safe(build_id)
402 if not flask.g.user.can_build_in(build.copr):
403 flask.flash("You are not allowed to repeat this build.")
404
405 if build.source_type == helpers.BuildSourceEnum('upload'):
406
407
408 available_chroots = build.chroots
409
410 else:
411
412
413 available_chroots = copr.active_chroots
414
415 form = forms.BuildFormRebuildFactory.create_form_cls(available_chroots)(
416 build_id=build_id, enable_net=build.enable_net)
417
418
419 for ch in available_chroots:
420 field = getattr(form, ch.name)
421 field.data = False
422 chroot_to_build = request.args.get("chroot")
423 app.logger.debug("got param chroot: {}".format(chroot_to_build))
424 if chroot_to_build:
425
426 if hasattr(form, chroot_to_build):
427 getattr(form, chroot_to_build).data = True
428 else:
429 build_chroot_names = set(ch.name for ch in build.chroots)
430 build_failed_chroot_names = set(ch.name for ch in build.get_chroots_by_status([
431 StatusEnum('failed'), StatusEnum('canceled'),
432 ]))
433 for ch in available_chroots:
434
435 if (ch.name not in build_chroot_names) or (ch.name in build_failed_chroot_names):
436 getattr(form, ch.name).data = True
437 return flask.render_template(
438 "coprs/detail/add_build/rebuild.html",
439 copr=copr, build=build, form=form)
440
453
454
455 @coprs_ns.route("/<username>/<coprname>/cancel_build/<int:build_id>/", methods=["POST"])
456 @coprs_ns.route("/g/<group_name>/<coprname>/cancel_build/<int:build_id>/", methods=["POST"])
457 @login_required
458 @req_with_copr
459 -def copr_cancel_build(copr, build_id):
463
464
465
466
467 @coprs_ns.route("/<username>/<coprname>/delete_build/<int:build_id>/",
468 methods=["POST"])
482