1
2
3 import os
4 import time
5 import fnmatch
6 import re
7 import uuid
8 import subprocess
9 from six.moves.urllib.parse import urljoin
10
11 import flask
12 from flask import render_template, url_for, stream_with_context
13 import platform
14 import smtplib
15 import tempfile
16 import sqlalchemy
17 import modulemd
18 from email.mime.text import MIMEText
19 from itertools import groupby
20
21 from pygments import highlight
22 from pygments.lexers import get_lexer_by_name
23 from pygments.formatters import HtmlFormatter
24
25 from coprs import app
26 from coprs import db
27 from coprs import rcp
28 from coprs import exceptions
29 from coprs import forms
30 from coprs import helpers
31 from coprs import models
32 from coprs.exceptions import ObjectNotFound
33 from coprs.logic.coprs_logic import CoprsLogic
34 from coprs.logic.packages_logic import PackagesLogic
35 from coprs.logic.stat_logic import CounterStatLogic
36 from coprs.logic.users_logic import UsersLogic
37 from coprs.logic.modules_logic import ModulesLogic, ModulemdGenerator, MBSProxy
38 from coprs.rmodels import TimedStatEvents
39
40 from coprs.logic.complex_logic import ComplexLogic
41
42 from coprs.views.misc import login_required, page_not_found, req_with_copr, req_with_copr, generic_error
43
44 from coprs.views.coprs_ns import coprs_ns
45 from coprs.views.groups_ns import groups_ns
46
47 from coprs.logic import builds_logic, coprs_logic, actions_logic, users_logic
48 from coprs.helpers import parse_package_name, generate_repo_url, CHROOT_RPMS_DL_STAT_FMT, CHROOT_REPO_MD_DL_STAT_FMT, \
49 str2bool, url_for_copr_view
57
64
65
66 @coprs_ns.route("/", defaults={"page": 1})
67 @coprs_ns.route("/<int:page>/")
68 -def coprs_show(page=1):
86
87
88 @coprs_ns.route("/<username>/", defaults={"page": 1})
89 @coprs_ns.route("/<username>/<int:page>/")
90 -def coprs_by_user(username=None, page=1):
113
114
115 @coprs_ns.route("/fulltext/", defaults={"page": 1})
116 @coprs_ns.route("/fulltext/<int:page>/")
117 -def coprs_fulltext_search(page=1):
118 fulltext = flask.request.args.get("fulltext", "")
119 try:
120 query = coprs_logic.CoprsLogic.get_multiple_fulltext(fulltext)
121 except ValueError as e:
122 flask.flash(str(e), "error")
123 return flask.redirect(flask.request.referrer or
124 flask.url_for("coprs_ns.coprs_show"))
125
126 paginator = helpers.Paginator(query, query.count(), page,
127 additional_params={"fulltext": fulltext})
128
129 coprs = paginator.sliced_query
130 return render_template(
131 "coprs/show/fulltext.html",
132 coprs=coprs,
133 paginator=paginator,
134 fulltext=fulltext,
135 tasks_info=ComplexLogic.get_queues_size(),
136 )
137
138
139 @coprs_ns.route("/<username>/add/")
140 @login_required
141 -def copr_add(username):
145
146
147 @coprs_ns.route("/g/<group_name>/add/")
148 @login_required
149 -def group_copr_add(group_name):
155
156
157 @coprs_ns.route("/g/<group_name>/new/", methods=["POST"])
160 group = ComplexLogic.get_group_by_name_safe(group_name)
161 form = forms.CoprFormFactory.create_form_cls(group=group)()
162
163 if form.validate_on_submit():
164 try:
165 copr = coprs_logic.CoprsLogic.add(
166 flask.g.user,
167 name=form.name.data,
168 homepage=form.homepage.data,
169 contact=form.contact.data,
170 repos=form.repos.data.replace("\n", " "),
171 selected_chroots=form.selected_chroots,
172 description=form.description.data,
173 instructions=form.instructions.data,
174 disable_createrepo=form.disable_createrepo.data,
175 build_enable_net=form.build_enable_net.data,
176 unlisted_on_hp=form.unlisted_on_hp.data,
177 group=group,
178 persistent=form.persistent.data,
179 auto_prune=(form.auto_prune.data if flask.g.user.admin else True),
180 use_bootstrap_container=form.use_bootstrap_container.data,
181 )
182 except (exceptions.DuplicateException, exceptions.NonAdminCannotCreatePersistentProject) as e:
183 flask.flash(str(e), "error")
184 return flask.render_template("coprs/group_add.html", form=form, group=group)
185
186 db.session.add(copr)
187 db.session.commit()
188 after_the_project_creation(copr, form)
189
190 return flask.redirect(url_for_copr_details(copr))
191 else:
192 return flask.render_template("coprs/group_add.html", form=form, group=group)
193
194
195 @coprs_ns.route("/<username>/new/", methods=["POST"])
196 @login_required
197 -def copr_new(username):
198 """
199 Receive information from the user on how to create its new copr
200 and create it accordingly.
201 """
202
203 form = forms.CoprFormFactory.create_form_cls()()
204 if form.validate_on_submit():
205 try:
206 copr = coprs_logic.CoprsLogic.add(
207 flask.g.user,
208 name=form.name.data,
209 homepage=form.homepage.data,
210 contact=form.contact.data,
211 repos=form.repos.data.replace("\n", " "),
212 selected_chroots=form.selected_chroots,
213 description=form.description.data,
214 instructions=form.instructions.data,
215 disable_createrepo=form.disable_createrepo.data,
216 build_enable_net=form.build_enable_net.data,
217 unlisted_on_hp=form.unlisted_on_hp.data,
218 persistent=form.persistent.data,
219 auto_prune=(form.auto_prune.data if flask.g.user.admin else True),
220 use_bootstrap_container=form.use_bootstrap_container.data,
221 )
222 except (exceptions.DuplicateException, exceptions.NonAdminCannotCreatePersistentProject) as e:
223 flask.flash(str(e), "error")
224 return flask.render_template("coprs/add.html", form=form)
225
226 db.session.commit()
227 after_the_project_creation(copr, form)
228
229 return flask.redirect(url_for_copr_details(copr))
230 else:
231 return flask.render_template("coprs/add.html", form=form)
232
235 flask.flash("New project has been created successfully.", "success")
236 _check_rpmfusion(copr.repos)
237 if form.initial_pkgs.data:
238 pkgs = form.initial_pkgs.data.replace("\n", " ").split(" ")
239
240
241 bad_urls = []
242 for pkg in pkgs:
243 if not re.match("^.*\.src\.rpm$", pkg):
244 bad_urls.append(pkg)
245 flask.flash("Bad url: {0} (skipped)".format(pkg))
246 for bad_url in bad_urls:
247 pkgs.remove(bad_url)
248
249 if not pkgs:
250 flask.flash("No initial packages submitted")
251 else:
252
253 for pkg in pkgs:
254 builds_logic.BuildsLogic.add(
255 flask.g.user,
256 pkgs=pkg,
257 copr=copr,
258 enable_net=form.build_enable_net.data
259 )
260
261 db.session.commit()
262 flask.flash("Initial packages were successfully submitted "
263 "for building.")
264
265
266 @coprs_ns.route("/<username>/<coprname>/report-abuse")
267 @req_with_copr
268 @login_required
269 -def copr_report_abuse(copr):
271
272
273 @coprs_ns.route("/g/<group_name>/<coprname>/report-abuse")
274 @req_with_copr
275 @login_required
276 -def group_copr_report_abuse(copr):
278
283
284
285 @coprs_ns.route("/g/<group_name>/<coprname>/")
286 @req_with_copr
287 -def group_copr_detail(copr):
289
290
291 @coprs_ns.route("/<username>/<coprname>/")
292 @req_with_copr
293 -def copr_detail(copr):
297
300 repo_dl_stat = CounterStatLogic.get_copr_repo_dl_stat(copr)
301 form = forms.CoprLegalFlagForm()
302 repos_info = {}
303 for chroot in copr.active_chroots:
304
305
306
307
308
309 chroot_rpms_dl_stat_key = CHROOT_RPMS_DL_STAT_FMT.format(
310 copr_user=copr.user.name,
311 copr_project_name=copr.name,
312 copr_chroot=chroot.name,
313 )
314 chroot_rpms_dl_stat = TimedStatEvents.get_count(
315 rconnect=rcp.get_connection(),
316 name=chroot_rpms_dl_stat_key,
317 )
318
319 logoset = set()
320 logodir = app.static_folder + "/chroot_logodir"
321 for logo in os.listdir(logodir):
322
323 if fnmatch.fnmatch(logo, "*.png"):
324 logoset.add(logo.strip(".png"))
325
326 if chroot.name_release not in repos_info:
327 logo = None
328 if chroot.name_release in logoset:
329 logo = chroot.name_release + ".png"
330 elif chroot.os_release in logoset:
331 logo = chroot.os_release + ".png"
332
333 repos_info[chroot.name_release] = {
334 "name_release": chroot.name_release,
335 "name_release_human": chroot.name_release_human,
336 "os_release": chroot.os_release,
337 "os_version": chroot.os_version,
338 "logo": logo,
339 "arch_list": [chroot.arch],
340 "repo_file": "{}-{}.repo".format(copr.repo_id, chroot.name_release),
341 "dl_stat": repo_dl_stat[chroot.name_release],
342 "rpm_dl_stat": {
343 chroot.arch: chroot_rpms_dl_stat
344 }
345 }
346 else:
347 repos_info[chroot.name_release]["arch_list"].append(chroot.arch)
348 repos_info[chroot.name_release]["rpm_dl_stat"][chroot.arch] = chroot_rpms_dl_stat
349 repos_info_list = sorted(repos_info.values(), key=lambda rec: rec["name_release"])
350 builds = builds_logic.BuildsLogic.get_multiple_by_copr(copr=copr).limit(1).all()
351
352 return flask.render_template(
353 "coprs/detail/overview.html",
354 copr=copr,
355 user=flask.g.user,
356 form=form,
357 repo_dl_stat=repo_dl_stat,
358 repos_info_list=repos_info_list,
359 latest_build=builds[0] if len(builds) == 1 else None,
360 )
361
362
363 @coprs_ns.route("/<username>/<coprname>/permissions/")
364 @req_with_copr
365 -def copr_permissions(copr):
393
414
415
416 @coprs_ns.route("/g/<group_name>/<coprname>/webhooks/")
417 @login_required
418 @req_with_copr
419 -def group_copr_webhooks(copr):
421
422
423 @coprs_ns.route("/<username>/<coprname>/webhooks/")
424 @login_required
425 @req_with_copr
426 -def copr_webhooks(copr):
428
437
438
439 @coprs_ns.route("/g/<group_name>/<coprname>/edit/")
440 @login_required
441 @req_with_copr
442 -def group_copr_edit(copr, form=None):
444
445
446 @coprs_ns.route("/<username>/<coprname>/edit/")
447 @login_required
448 @req_with_copr
449 -def copr_edit(copr, form=None):
451
454 if "rpmfusion" in repos:
455 message = flask.Markup('Using rpmfusion as dependency is nearly always wrong. Please see <a href="https://docs.pagure.org/copr.copr/user_documentation.html#what-i-can-build-in-copr">What I can build in Copr</a>.')
456 flask.flash(message, "error")
457
488
489
490 @coprs_ns.route("/g/<group_name>/<coprname>/update/", methods=["POST"])
505
506
507 @coprs_ns.route("/<username>/<coprname>/update/", methods=["POST"])
508 @login_required
509 @req_with_copr
510 -def copr_update(copr):
518
519
520 @coprs_ns.route("/<username>/<coprname>/permissions_applier_change/",
521 methods=["POST"])
525 permission = coprs_logic.CoprPermissionsLogic.get(copr, flask.g.user).first()
526 applier_permissions_form = \
527 forms.PermissionsApplierFormFactory.create_form_cls(permission)()
528
529 if copr.user == flask.g.user:
530 flask.flash("Owner cannot request permissions for his own project.", "error")
531 elif applier_permissions_form.validate_on_submit():
532
533 if permission is not None:
534 old_builder = permission.copr_builder
535 old_admin = permission.copr_admin
536 else:
537 old_builder = 0
538 old_admin = 0
539 new_builder = applier_permissions_form.copr_builder.data
540 new_admin = applier_permissions_form.copr_admin.data
541 coprs_logic.CoprPermissionsLogic.update_permissions_by_applier(
542 flask.g.user, copr, permission, new_builder, new_admin)
543 db.session.commit()
544 flask.flash(
545 "Successfuly updated permissions for project '{0}'."
546 .format(copr.name))
547 admin_mails = [copr.user.mail]
548 for perm in copr.copr_permissions:
549
550 if perm.copr_admin == 2:
551 admin_mails.append(perm.user.mail)
552
553
554 if flask.current_app.config.get("SEND_EMAILS", False):
555 for mail in admin_mails:
556 msg = MIMEText(
557 "{6} is asking for these permissions:\n\n"
558 "Builder: {0} -> {1}\nAdmin: {2} -> {3}\n\n"
559 "Project: {4}\nOwner: {5}".format(
560 helpers.PermissionEnum(old_builder),
561 helpers.PermissionEnum(new_builder),
562 helpers.PermissionEnum(old_admin),
563 helpers.PermissionEnum(new_admin),
564 copr.name, copr.user.name, flask.g.user.name))
565
566 msg["Subject"] = "[Copr] {0}: {1} is asking permissons".format(copr.name, flask.g.user.name)
567 msg["From"] = "root@{0}".format(platform.node())
568 msg["To"] = mail
569 s = smtplib.SMTP("localhost")
570 s.sendmail("root@{0}".format(platform.node()), mail, msg.as_string())
571 s.quit()
572
573 return flask.redirect(flask.url_for("coprs_ns.copr_detail",
574 username=copr.user.name,
575 coprname=copr.name))
576
577
578 @coprs_ns.route("/<username>/<coprname>/update_permissions/", methods=["POST"])
582 permissions = copr.copr_permissions
583 permissions_form = forms.PermissionsFormFactory.create_form_cls(
584 permissions)()
585
586 if permissions_form.validate_on_submit():
587
588 try:
589
590
591 permissions.sort(
592 key=lambda x: -1 if x.user_id == flask.g.user.id else 1)
593 for perm in permissions:
594 old_builder = perm.copr_builder
595 old_admin = perm.copr_admin
596 new_builder = permissions_form[
597 "copr_builder_{0}".format(perm.user_id)].data
598 new_admin = permissions_form[
599 "copr_admin_{0}".format(perm.user_id)].data
600 coprs_logic.CoprPermissionsLogic.update_permissions(
601 flask.g.user, copr, perm, new_builder, new_admin)
602 if flask.current_app.config.get("SEND_EMAILS", False) and \
603 (old_builder is not new_builder or old_admin is not new_admin):
604
605 msg = MIMEText(
606 "Your permissions have changed:\n\n"
607 "Builder: {0} -> {1}\nAdmin: {2} -> {3}\n\n"
608 "Project: {4}\nOwner: {5}".format(
609 helpers.PermissionEnum(old_builder),
610 helpers.PermissionEnum(new_builder),
611 helpers.PermissionEnum(old_admin),
612 helpers.PermissionEnum(new_admin),
613 copr.name, copr.user.name))
614
615 msg["Subject"] = "[Copr] {0}: Your permissions have changed".format(copr.name)
616 msg["From"] = "root@{0}".format(platform.node())
617 msg["To"] = perm.user.mail
618 s = smtplib.SMTP("localhost")
619 s.sendmail("root@{0}".format(platform.node()), perm.user.mail, msg.as_string())
620 s.quit()
621
622
623 except exceptions.InsufficientRightsException as e:
624 db.session.rollback()
625 flask.flash(str(e), "error")
626 else:
627 db.session.commit()
628 flask.flash("Project permissions were updated successfully.", "success")
629
630 return flask.redirect(url_for_copr_details(copr))
631
632
633 @coprs_ns.route("/id/<copr_id>/createrepo/", methods=["POST"])
650
653 form = forms.CoprDeleteForm()
654 if form.validate_on_submit():
655
656 try:
657 ComplexLogic.delete_copr(copr)
658 except (exceptions.ActionInProgressException,
659 exceptions.InsufficientRightsException) as e:
660
661 db.session.rollback()
662 flask.flash(str(e), "error")
663 return flask.redirect(url_on_error)
664 else:
665 db.session.commit()
666 flask.flash("Project has been deleted successfully.")
667 return flask.redirect(url_on_success)
668 else:
669 return render_template("coprs/detail/settings/delete.html", form=form, copr=copr)
670
671
672 @coprs_ns.route("/<username>/<coprname>/delete/", methods=["GET", "POST"])
673 @login_required
674 @req_with_copr
675 -def copr_delete(copr):
682
683
684 @coprs_ns.route("/g/<group_name>/<coprname>/delete/", methods=["GET", "POST"])
696
697
698 @coprs_ns.route("/<username>/<coprname>/legal_flag/", methods=["POST"])
704
705
706 @coprs_ns.route("/g/<group_name>/<coprname>/legal_flag/", methods=["POST"])
712
715 form = forms.CoprLegalFlagForm()
716 legal_flag = models.LegalFlag(raise_message=form.comment.data,
717 raised_on=int(time.time()),
718 copr=copr,
719 reporter=flask.g.user)
720 db.session.add(legal_flag)
721 db.session.commit()
722 send_to = app.config["SEND_LEGAL_TO"] or ["root@localhost"]
723 hostname = platform.node()
724 navigate_to = "\nNavigate to http://{0}{1}".format(
725 hostname, flask.url_for("admin_ns.legal_flag"))
726 contact = "\nContact on owner is: {}".format(contact_info)
727 reported_by = "\nReported by {0} <{1}>".format(flask.g.user.name,
728 flask.g.user.mail)
729 try:
730 msg = MIMEText(
731 form.comment.data + navigate_to + contact + reported_by, "plain")
732 except UnicodeEncodeError:
733 msg = MIMEText(form.comment.data.encode(
734 "utf-8") + navigate_to + contact + reported_by, "plain", "utf-8")
735 msg["Subject"] = "Legal flag raised on {0}".format(copr.name)
736 msg["From"] = "root@{0}".format(hostname)
737 msg["To"] = ", ".join(send_to)
738 s = smtplib.SMTP("localhost")
739 s.sendmail("root@{0}".format(hostname), send_to, msg.as_string())
740 s.quit()
741 flask.flash("Admin has been noticed about your report"
742 " and will investigate the project shortly.")
743 return flask.redirect(url_for_copr_details(copr))
744
745
746 @coprs_ns.route("/<username>/<coprname>/repo/<name_release>/", defaults={"repofile": None})
747 @coprs_ns.route("/<username>/<coprname>/repo/<name_release>/<repofile>")
748 -def generate_repo_file(username, coprname, name_release, repofile):
763
764
765 @coprs_ns.route("/g/<group_name>/<coprname>/repo/<name_release>/", defaults={"repofile": None})
766 @coprs_ns.route("/g/<group_name>/<coprname>/repo/<name_release>/<repofile>")
767 @req_with_copr
768 -def group_generate_repo_file(copr, name_release, repofile):
776
779
780
781 if name_release in [c.name for c in copr.mock_chroots]:
782 chroot = [c for c in copr.mock_chroots if c.name == name_release][0]
783 kwargs = dict(coprname=copr.name, name_release=chroot.name_release)
784 if copr.is_a_group_project:
785 fixed_url = url_for("coprs_ns.group_generate_repo_file",
786 group_name=copr.group.name, **kwargs)
787 else:
788 fixed_url = url_for("coprs_ns.generate_repo_file",
789 username=copr.user.username, **kwargs)
790 return flask.redirect(fixed_url)
791
792 mock_chroot = coprs_logic.MockChrootsLogic.get_from_name(name_release, noarch=True).first()
793 if not mock_chroot:
794 raise ObjectNotFound("Chroot {} does not exist".format(name_release))
795
796 url = os.path.join(copr.repo_url, '')
797 repo_url = generate_repo_url(mock_chroot, url)
798 pubkey_url = urljoin(url, "pubkey.gpg")
799 response = flask.make_response(
800 flask.render_template("coprs/copr.repo", copr=copr, url=repo_url, pubkey_url=pubkey_url))
801 response.mimetype = "text/plain"
802 response.headers["Content-Disposition"] = \
803 "filename={0}.repo".format(copr.repo_name)
804 return response
805
806
807
808
809
810
811 @coprs_ns.route("/<username>/<coprname>/repo/modules/")
812 @coprs_ns.route("/@<group_name>/<coprname>/repo/modules/")
813 @coprs_ns.route("/g/<group_name>/<coprname>/repo/modules/")
814 @req_with_copr
815 -def generate_module_repo_file(copr):
818
820 url = os.path.join(copr.repo_url, '')
821 pubkey_url = urljoin(url, "pubkey.gpg")
822 response = flask.make_response(
823 flask.render_template("coprs/copr-modules.cfg", copr=copr, url=url, pubkey_url=pubkey_url))
824 response.mimetype = "text/plain"
825 response.headers["Content-Disposition"] = \
826 "filename={0}.cfg".format(copr.repo_name)
827 return response
828
829
830
831 @coprs_ns.route("/<username>/<coprname>/rpm/<name_release>/<rpmfile>")
832 -def copr_repo_rpm_file(username, coprname, name_release, rpmfile):
833 try:
834 packages_dir = os.path.join(app.config["DATA_DIR"], "repo-rpm-packages")
835 with open(os.path.join(packages_dir, rpmfile), "rb") as rpm:
836 response = flask.make_response(rpm.read())
837 response.mimetype = "application/x-rpm"
838 response.headers["Content-Disposition"] = \
839 "filename={0}".format(rpmfile)
840 return response
841 except IOError:
842 return flask.render_template("404.html")
843
860
861
862 @coprs_ns.route("/<username>/<coprname>/monitor/")
863 @coprs_ns.route("/<username>/<coprname>/monitor/<detailed>")
864 @req_with_copr
865 -def copr_build_monitor(copr, detailed=False):
867
868
869 @coprs_ns.route("/g/<group_name>/<coprname>/monitor/")
870 @coprs_ns.route("/g/<group_name>/<coprname>/monitor/<detailed>")
871 @req_with_copr
872 -def group_copr_build_monitor(copr, detailed=False):
874
875
876 @coprs_ns.route("/<username>/<coprname>/fork/")
877 @coprs_ns.route("/g/<group_name>/<coprname>/fork/")
878 @login_required
879 @req_with_copr
880 -def copr_fork(copr):
883
886 return flask.render_template("coprs/fork.html", copr=copr, form=form, confirm=confirm)
887
888
889 @coprs_ns.route("/<username>/<coprname>/fork/", methods=["POST"])
890 @coprs_ns.route("/g/<group_name>/<coprname>/fork/", methods=["POST"])
891 @login_required
892 @req_with_copr
893 -def copr_fork_post(copr):
894 form = forms.CoprForkFormFactory.create_form_cls(copr=copr, user=flask.g.user, groups=flask.g.user.user_groups)()
895 if form.validate_on_submit():
896 dstgroup = ([g for g in flask.g.user.user_groups if g.at_name == form.owner.data] or [None])[0]
897 if flask.g.user.name != form.owner.data and not dstgroup:
898 return generic_error("There is no such group: {}".format(form.owner.data))
899
900 fcopr, created = ComplexLogic.fork_copr(copr, flask.g.user, dstname=form.name.data, dstgroup=dstgroup)
901 if created:
902 msg = ("Forking project {} for you into {}. Please be aware that it may take a few minutes "
903 "to duplicate a backend data.".format(copr.full_name, fcopr.full_name))
904 elif not created and form.confirm.data == True:
905 msg = ("Updating packages in {} from {}. Please be aware that it may take a few minutes "
906 "to duplicate a backend data.".format(copr.full_name, fcopr.full_name))
907 else:
908 return render_copr_fork(copr, form, confirm=True)
909
910 db.session.commit()
911 flask.flash(msg)
912
913 return flask.redirect(url_for_copr_details(fcopr))
914 return render_copr_fork(copr, form)
915
916
917 @coprs_ns.route("/update_search_index/", methods=["POST"])
919 subprocess.call(['/usr/share/copr/coprs_frontend/manage.py', 'update_indexes_quick', '1'])
920 return "OK"
921
922
923 @coprs_ns.route("/<username>/<coprname>/modules/")
924 @coprs_ns.route("/g/<group_name>/<coprname>/modules/")
925 @req_with_copr
926 -def copr_modules(copr):
928
933
934
935 @coprs_ns.route("/<username>/<coprname>/create_module/")
936 @coprs_ns.route("/g/<group_name>/<coprname>/create_module/")
937 @login_required
938 @req_with_copr
939 -def copr_create_module(copr):
942
951
952
953 @coprs_ns.route("/<username>/<coprname>/create_module/", methods=["POST"])
954 @coprs_ns.route("/g/<group_name>/<coprname>/create_module/", methods=["POST"])
955 @login_required
956 @req_with_copr
957 -def copr_create_module_post(copr):
958 form = forms.CreateModuleForm(copr=copr, csrf_enabled=False)
959 args = [copr, form]
960 if "add_profile" in flask.request.values:
961 return add_profile(*args)
962 if "build_module" in flask.request.values:
963 return build_module(*args)
964
973
976 if not form.validate_on_submit():
977
978 for i in range(2, len(form.profile_names)):
979 form.profile_pkgs.append_entry()
980 return render_create_module(copr, form, profiles=len(form.profile_names))
981
982 summary = "Module from Copr repository: {}".format(copr.full_name)
983 generator = ModulemdGenerator(str(copr.name), str(form.stream.data),
984 form.version.data, summary, app.config)
985 generator.add_filter(form.filter.data)
986 generator.add_api(form.api.data)
987 generator.add_profiles(enumerate(zip(form.profile_names.data, form.profile_pkgs.data)))
988 generator.add_components(form.packages.data, form.filter.data, form.builds.data)
989 generator.add_base_runtime()
990 tmp = tempfile.mktemp()
991 generator.dump(tmp)
992
993 proxy = MBSProxy(mbs_url=flask.current_app.config["MBS_URL"], user_name=flask.g.user.name)
994 with open(tmp) as tmp_handle:
995 response = proxy.build_module(copr.owner_name, copr.name, generator.nsv, tmp_handle)
996 os.remove(tmp)
997
998 if response.failed:
999 flask.flash(response.message, "error")
1000 return render_create_module(copr, form, len(form.profile_names))
1001 flask.flash("Modulemd yaml file successfully generated and submitted to be build", "success")
1002 return flask.redirect(url_for_copr_details(copr))
1003
1004
1005 @coprs_ns.route("/<username>/<coprname>/module/<id>")
1006 @coprs_ns.route("/g/<group_name>/<coprname>/module/<id>")
1007 @req_with_copr
1008 -def copr_module(copr, id):
1009 module = ModulesLogic.get(id).first()
1010 formatter = HtmlFormatter(style="autumn", linenos=False, noclasses=True)
1011 pretty_yaml = highlight(module.yaml, get_lexer_by_name("YAML"), formatter)
1012 return flask.render_template("coprs/detail/module.html", copr=copr, module=module, yaml=pretty_yaml)
1013
1014
1015 @coprs_ns.route("/<username>/<coprname>/module/<id>/raw")
1016 @coprs_ns.route("/g/<group_name>/<coprname>/module/<id>/raw")
1017 @req_with_copr
1018 -def copr_module_raw(copr, id):
1019 module = ModulesLogic.get(id).first()
1020 response = flask.make_response(module.yaml)
1021 response.mimetype = "text/plain"
1022 response.headers["Content-Disposition"] = \
1023 "filename={}.yaml".format("-".join([str(module.id), module.name, module.stream, str(module.version)]))
1024 return response
1025