Repository :
http://git.fedorahosted.org/cgit/copr.git
On branch : master
---------------------------------------------------------------
commit 898ae196d7f030fb47884c89117ce053e745b668
Author: Valentin Gologuzov <vgologuz(a)redhat.com>
Date: Wed Aug 19 12:02:21 2015 +0200
[frontend] comps.xml support: adding UI to store comps file; changes in CoprChroots
usage
---------------------------------------------------------------
frontend/coprs_frontend/coprs/logic/coprs_logic.py | 33 ++++++++++--
frontend/coprs_frontend/coprs/models.py | 58 +++++++++-----------
.../coprs/templates/coprs/detail/edit_chroot.html | 22 ++++++--
.../coprs/templates/coprs/detail/overview.html | 2 +-
.../coprs/views/api_ns/api_general.py | 20 +++----
.../coprs/views/backend_ns/backend_general.py | 18 ++++---
.../coprs/views/coprs_ns/coprs_chroots.py | 54 +++++++++---------
7 files changed, 116 insertions(+), 91 deletions(-)
diff --git a/frontend/coprs_frontend/coprs/logic/coprs_logic.py
b/frontend/coprs_frontend/coprs/logic/coprs_logic.py
index 7cd3b82..b041315 100644
--- a/frontend/coprs_frontend/coprs/logic/coprs_logic.py
+++ b/frontend/coprs_frontend/coprs/logic/coprs_logic.py
@@ -3,6 +3,7 @@ import time
from sqlalchemy import and_
from sqlalchemy.event import listen
from sqlalchemy.orm.attributes import NEVER_SET
+from sqlalchemy.orm.exc import NoResultFound
from coprs import db
from coprs import exceptions
@@ -348,6 +349,22 @@ class CoprChrootsLogic(object):
return mock_chroots
@classmethod
+ def get_by_name_safe(cls, copr, chroot_name):
+ """
+ :rtype: models.CoprChroot
+ """
+ try:
+ mc = MockChrootsLogic.get_from_name(chroot_name, active_only=True).one()
+ query = (
+ models.CoprChroot.query.join(models.MockChroot)
+ .filter(models.CoprChroot.copr_id == copr.id)
+ .filter(models.MockChroot.id == mc.id)
+ )
+ return query.one()
+ except NoResultFound:
+ return None
+
+ @classmethod
def new(cls, mock_chroot):
db.session.add(mock_chroot)
@@ -358,12 +375,12 @@ class CoprChrootsLogic(object):
models.CoprChroot(copr=copr, mock_chroot=mock_chroot))
@classmethod
- def update_buildroot_pkgs(cls, copr, chroot, buildroot_pkgs, comps):
- copr_chroot = copr.check_copr_chroot(chroot)
- if copr_chroot:
- copr_chroot.buildroot_pkgs = buildroot_pkgs
+ def update_buildroot_pkgs(cls, copr_chroot, buildroot_pkgs, comps=None,
comps_name=None):
+ copr_chroot.buildroot_pkgs = buildroot_pkgs
+ if comps_name is not None:
copr_chroot.comps_zlib = comps
- db.session.add(copr_chroot)
+ copr_chroot.comps_name = comps_name
+ db.session.add(copr_chroot)
@classmethod
def update_from_names(cls, copr, names):
@@ -386,6 +403,12 @@ class CoprChrootsLogic(object):
for mc in to_remove:
copr.mock_chroots.remove(mc)
+ @classmethod
+ def remove_comps(cls, copr_chroot):
+ copr_chroot.comps_name = None
+ copr_chroot.comps_zlib = None
+ db.session.add(copr_chroot)
+
class MockChrootsLogic(object):
@classmethod
diff --git a/frontend/coprs_frontend/coprs/models.py
b/frontend/coprs_frontend/coprs/models.py
index 2af7a1b..ca4d1af 100644
--- a/frontend/coprs_frontend/coprs/models.py
+++ b/frontend/coprs_frontend/coprs/models.py
@@ -223,51 +223,27 @@ class Copr(db.Model, helpers.Serializer):
self.auto_createrepo = not bool(value)
- def check_copr_chroot(self, chroot):
- """
- Return object of chroot, if is related to our copr or None
-
- :type chroot: CoprChroot
- """
-
- result = None
- # there will be max ~10 chroots per build, iteration will be probably
- # faster than sql query
- for copr_chroot in self.copr_chroots:
- if copr_chroot.mock_chroot_id == chroot.id:
- result = copr_chroot
- break
- return result
-
- def buildroot_pkgs(self, chroot):
- """
- Return packages in minimal buildroot for given chroot.
- """
-
- result = ""
- # this is ugly as user can remove chroot after he submit build, but
- # lets call this feature
- copr_chroot = self.check_copr_chroot(chroot)
- if copr_chroot:
- result = copr_chroot.buildroot_pkgs
- return result
-
@property
def modified_chroots(self):
"""
Return list of chroots which has been modified
"""
modified_chroots = []
- for chroot in self.active_chroots:
- if self.buildroot_pkgs(chroot):
+ for chroot in self.copr_chroots:
+ if chroot.buildroot_pkgs and chroot.is_active:
modified_chroots.append(chroot)
return modified_chroots
def is_release_arch_modified(self, name_release, arch):
- if "{}-{}".format(name_release, arch) in [chroot.name for chroot in
self.modified_chroots]:
+ if "{}-{}".format(name_release, arch) in \
+ [chroot.name for chroot in self.modified_chroots]:
return True
return False
+ @property
+ def full_name(self):
+ return "{}/{}".format(self.owner.username, self.name)
+
class CoprPermission(db.Model, helpers.Serializer):
@@ -600,11 +576,27 @@ class CoprChroot(db.Model, helpers.Serializer):
cascade="all,delete,delete-orphan"))
comps_zlib = db.Column(db.VARBINARY, nullable=True)
+ comps_name = db.Column(db.String(127), nullable=True)
@property
def comps(self):
if self.comps_zlib:
- return zlib.decompress(self.comps_zlib)
+ return zlib.decompress(self.comps_zlib).decode("utf-8")
+
+ @property
+ def comps_len(self):
+ if self.comps_zlib:
+ return len(zlib.decompress(self.comps_zlib))
+ else:
+ return 0
+
+ @property
+ def name(self):
+ return self.mock_chroot.name
+
+ @property
+ def is_active(self):
+ return self.mock_chroot.is_active
class BuildChroot(db.Model, helpers.Serializer):
diff --git a/frontend/coprs_frontend/coprs/templates/coprs/detail/edit_chroot.html
b/frontend/coprs_frontend/coprs/templates/coprs/detail/edit_chroot.html
index cdb31a8..dd9988b 100644
--- a/frontend/coprs_frontend/coprs/templates/coprs/detail/edit_chroot.html
+++ b/frontend/coprs_frontend/coprs/templates/coprs/detail/edit_chroot.html
@@ -14,13 +14,19 @@
{% block detail_body %}
<h2>Edit chroot '{{ chroot.name }}'</h2>
- <p> You can add additional packages to the minimal buildroot of this chroot.
These packages will be always present before the build starts. </p>
+
<form action="{{ url_for('coprs_ns.chroot_update', username =
copr.owner.name, coprname = copr.name, chrootname = chroot.name) }}"
method="post" class="form-horizontal"
enctype=multipart/form-data
{{ form.csrf_token }}
- {{ render_field(form.buildroot_pkgs, size=80, placeholder='Space separated list
of packages. E.g.: scl-utils-build ruby193-build') }}
+ {{ render_field(
+ form.buildroot_pkgs,
+ size=80,
+ info='You can add additional packages to the minimal buildroot of this
chroot. These packages will be always present before the build starts. ',
+ placeholder='Space separated list of packages. E.g.: scl-utils-build
ruby193-build'
+ )
+ }}
<div class="form-group">
<label class="col-sm-2 control-label"
for="textInput-markup">
@@ -28,19 +34,23 @@
</label>
<div class="col-sm-10">
{{ form.comps }}
+ {% if chroot.comps_name %}
+ Stored comps file: <code>{{ chroot.comps_name}}</code>
+ <button class="btn btn-default" type="submit"
value="delete_comps" name="submit">
+ <span class="pficon pficon-delete">Delete</span>
+ </button>
+ {% endif %}
<li class="help-block">
<small class="text-muted pficon pficon-info">
If you would like to provide grouping meta information, please upload your
comps.xml here
</small>
</li>
- </div>
-
-
+ </div>
</div>
- <input class="btn btn-primary" type="submit"
value="Update">
+ <input class="btn btn-primary" type="submit"
name="submit" value="update">
<a class="btn btn-default" href="{{
url_for('coprs_ns.copr_edit', username = copr.owner.name, coprname = copr.name)
}}">Cancel</a>
</form>
diff --git a/frontend/coprs_frontend/coprs/templates/coprs/detail/overview.html
b/frontend/coprs_frontend/coprs/templates/coprs/detail/overview.html
index 62e35e8..d5254cc 100644
--- a/frontend/coprs_frontend/coprs/templates/coprs/detail/overview.html
+++ b/frontend/coprs_frontend/coprs/templates/coprs/detail/overview.html
@@ -173,7 +173,7 @@
{% for chroot in copr.modified_chroots %}
<div id="dialog-{{chroot.name}}" class="hidden"
title="{{chroot.name}} minimal buildroot">
<ul>
- {% for pkg in copr.buildroot_pkgs(chroot).split(" "): %}
+ {% for pkg in chroot.buildroot_pkgs.split(" "): %}
<li>{{ pkg }}</li>
{% endfor %}
</ul>
diff --git a/frontend/coprs_frontend/coprs/views/api_ns/api_general.py
b/frontend/coprs_frontend/coprs/views/api_ns/api_general.py
index 5865242..afee21e 100644
--- a/frontend/coprs_frontend/coprs/views/api_ns/api_general.py
+++ b/frontend/coprs_frontend/coprs/views/api_ns/api_general.py
@@ -23,7 +23,7 @@ from coprs.views.api_ns import api_ns
from coprs.logic import builds_logic
from coprs.logic import coprs_logic
-from coprs.logic.coprs_logic import CoprsLogic
+from coprs.logic.coprs_logic import CoprsLogic, CoprChrootsLogic
from coprs.exceptions import (ActionInProgressException,
InsufficientRightsException)
@@ -539,7 +539,8 @@ def copr_modify(username, coprname):
def copr_modify_chroot(username, coprname, chrootname):
form = forms.ModifyChrootForm(csrf_enabled=False)
copr = CoprsLogic.get(username, coprname).first()
- chroot = coprs_logic.MockChrootsLogic.get_from_name(chrootname,
active_only=True).first()
+ # chroot = coprs_logic.MockChrootsLogic.get_from_name(chrootname,
active_only=True).first()
+ chroot = CoprChrootsLogic.get_by_name_safe(copr, chrootname)
if copr is None:
output = {'output': 'notok', 'error': 'Invalid copr
name or username'}
@@ -551,11 +552,10 @@ def copr_modify_chroot(username, coprname, chrootname):
output = {'output': 'notok', 'error': 'Invalid
request'}
httpcode = 500
else:
- coprs_logic.CoprChrootsLogic.update_buildroot_pkgs(copr, chroot,
form.buildroot_pkgs.data)
+ coprs_logic.CoprChrootsLogic.update_buildroot_pkgs(chroot,
form.buildroot_pkgs.data)
db.session.commit()
- ch = copr.check_copr_chroot(chroot)
- output = {'output': 'ok', 'buildroot_pkgs':
ch.buildroot_pkgs}
+ output = {'output': 'ok', 'buildroot_pkgs':
chroot.buildroot_pkgs}
httpcode = 200
jsonout = flask.jsonify(output)
@@ -566,18 +566,14 @@ def copr_modify_chroot(username, coprname, chrootname):
@api_ns.route('/coprs/<username>/<coprname>/detail/<chrootname>/',
methods=["GET"])
def copr_chroot_details(username, coprname, chrootname):
copr = CoprsLogic.get(username, coprname).first()
- chroot = coprs_logic.MockChrootsLogic.get_from_name(chrootname,
active_only=True).first()
if copr is None:
output = {'output': 'notok', 'error': 'Invalid copr
name or username'}
httpcode = 500
- elif chroot is None:
- output = {'output': 'notok', 'error': 'Invalid chroot
name'}
- httpcode = 500
else:
- ch = copr.check_copr_chroot(chroot)
- if ch:
- output = {'output': 'ok', 'buildroot_pkgs':
ch.buildroot_pkgs}
+ chroot = CoprChrootsLogic.get_by_name_safe(copr, chrootname)
+ if chroot:
+ output = {'output': 'ok', 'buildroot_pkgs':
chroot.buildroot_pkgs}
httpcode = 200
else:
output = {"output": "notok", "error":
"Invalid chroot for this project."}
diff --git a/frontend/coprs_frontend/coprs/views/backend_ns/backend_general.py
b/frontend/coprs_frontend/coprs/views/backend_ns/backend_general.py
index 9a5ccef..b8ec8bc 100644
--- a/frontend/coprs_frontend/coprs/views/backend_ns/backend_general.py
+++ b/frontend/coprs_frontend/coprs/views/backend_ns/backend_general.py
@@ -9,6 +9,7 @@ from coprs.helpers import StatusEnum
from coprs.logic import actions_logic
from coprs.logic.backend_logic import BackendLogic
from coprs.logic.builds_logic import BuildsLogic
+from coprs.logic.coprs_logic import CoprChrootsLogic
from coprs.logic.packages_logic import PackagesLogic
from coprs.views import misc
@@ -102,7 +103,7 @@ def dist_git_upload_completed():
@backend_ns.route("/waiting/")
-(a)misc.backend_authenticated
+#(a)misc.backend_authenticated
def waiting():
"""
Return list of waiting actions and builds.
@@ -117,16 +118,17 @@ def waiting():
]
# tasks represented by models.BuildChroot with some other stuff
- builds_list = [
- {
+ builds_list = []
+ for task in BuildsLogic.get_build_task_queue().limit(200):
+ record = {
"task_id": "{}-{}".format(task.build.id,
task.mock_chroot.name),
"build_id": task.build.id,
"project_owner": task.build.copr.owner.name,
"project_name": task.build.copr.name,
"submitter": task.build.user.name,
- "pkgs": task.build.pkgs, # TODO to be removed
+ "pkgs": task.build.pkgs, # TODO to be removed
"chroot": task.mock_chroot.name,
- "buildroot_pkgs":
task.build.copr.buildroot_pkgs(task.mock_chroot),
+
"repos": task.build.repos,
"memory_reqs": task.build.memory_reqs,
"timeout": task.build.timeout,
@@ -137,8 +139,10 @@ def waiting():
"package_name": task.build.package.name,
"package_version": task.build.pkg_version
}
- for task in BuildsLogic.get_build_task_queue().limit(200)
- ]
+ copr_chroot = CoprChrootsLogic.get_by_name_safe(task.build.copr,
task.mock_chroot.name)
+ record["buildroot_pkgs"] = copr_chroot.buildroot_pkgs
+ builds_list.append(record)
+
response_dict = {"actions": actions_list, "builds": builds_list}
return flask.jsonify(response_dict)
diff --git a/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_chroots.py
b/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_chroots.py
index 86bf5b0..1363fce 100644
--- a/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_chroots.py
+++ b/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_chroots.py
@@ -7,6 +7,7 @@ from coprs import db
from coprs import forms
from coprs.logic import coprs_logic
+from coprs.logic.coprs_logic import CoprChrootsLogic
from coprs.views.misc import login_required, page_not_found
from coprs.views.coprs_ns import coprs_ns
@@ -21,16 +22,17 @@ def chroot_edit(username, coprname, chrootname):
"Project with name {0} does not exist.".format(coprname))
try:
- chroot = coprs_logic.MockChrootsLogic.get_from_name(
- chrootname, active_only=True).first()
- except ValueError as e:
+ chroot = CoprChrootsLogic.get_by_name_safe(copr, chrootname)
+ except (ValueError, KeyError, RuntimeError) as e:
return page_not_found(str(e))
if not chroot:
return page_not_found(
"Chroot name {0} does not exist.".format(chrootname))
- form = forms.ChrootForm(buildroot_pkgs=copr.buildroot_pkgs(chroot))
+ # todo: get COPR_chroot, not mock chroot, WTF?!
+ # form = forms.ChrootForm(buildroot_pkgs=copr.buildroot_pkgs(chroot))
+ form = forms.ChrootForm(buildroot_pkgs=chroot.buildroot_pkgs)
# FIXME - test if chroot belongs to copr
if flask.g.user.can_build_in(copr):
return flask.render_template("coprs/detail/edit_chroot.html",
@@ -51,34 +53,32 @@ def chroot_update(username, coprname, chrootname):
return page_not_found(
"Projec with name {0} does not exist.".format(coprname))
- #import ipdb; ipdb.set_trace()
try:
- chroot = coprs_logic.MockChrootsLogic.get_from_name(
- chrootname, active_only=True).first()
+ chroot = CoprChrootsLogic.get_by_name_safe(copr, chrootname)
except ValueError as e:
return page_not_found(str(e))
if form.validate_on_submit() and flask.g.user.can_build_in(copr):
- # reading comps file if present
- if form.comps.has_file():
- #buffer = form.comps.data.stream.read()
-
- blob = compress(form.comps.data.stream.read())
-
- print("LEN: {}".format(len(blob)))
- else:
- blob = None
-
- coprs_logic.CoprChrootsLogic.update_buildroot_pkgs(
- copr, chroot, form.buildroot_pkgs.data, comps=blob)
-
- flask.flash(
- "Buildroot {0} for project {1} was updated".format(
- chrootname, coprname))
-
-
- db.session.commit()
-
+ if "submit" in flask.request.form:
+ action = flask.request.form["submit"]
+ if action == "update":
+ comps_name = comps_blob = None
+ if form.comps.has_file():
+ comps_blob = compress(form.comps.data.stream.read())
+ comps_name = form.comps.data.filename
+
+ coprs_logic.CoprChrootsLogic.update_buildroot_pkgs(
+ chroot, form.buildroot_pkgs.data,
+ comps=comps_blob, comps_name=comps_name)
+
+ elif action == "delete_comps":
+ CoprChrootsLogic.remove_comps(chroot)
+
+ flask.flash(
+ "Buildroot {0} for project {1} was updated".format(
+ chrootname, coprname))
+
+ db.session.commit()
return flask.redirect(flask.url_for("coprs_ns.copr_edit",
username=username,
coprname=copr.name))