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