Package coprs :: Package logic :: Module modules_logic
[hide private]
[frames] | no frames]

Source Code for Module coprs.logic.modules_logic

  1  import os 
  2  import time 
  3  import base64 
  4  import requests 
  5  from collections import defaultdict 
  6  from sqlalchemy import and_ 
  7  from datetime import datetime 
  8  from coprs import models 
  9  from coprs import db 
 10  from coprs import exceptions 
 11  from coprs.logic import builds_logic 
 12  from wtforms import ValidationError 
 13   
 14  import gi 
 15  gi.require_version('Modulemd', '1.0') 
 16  from gi.repository import Modulemd 
17 18 19 -class ModulesLogic(object):
20 @classmethod
21 - def get(cls, module_id):
22 """ 23 Return single module identified by `module_id` 24 """ 25 return models.Module.query.filter(models.Module.id == module_id)
26 27 @classmethod
28 - def get_by_nsv(cls, copr, name, stream, version):
34 35 @classmethod
36 - def get_by_nsv_str(cls, copr, nsv):
37 name, stream, version = nsv.split("-") 38 return cls.get_by_nsv(copr, name, stream, version)
39 40 @classmethod
41 - def get_multiple(cls):
42 return models.Module.query.order_by(models.Module.id.desc())
43 44 @classmethod
45 - def get_multiple_by_copr(cls, copr):
47 48 @classmethod
49 - def yaml2modulemd(cls, yaml):
50 mmd = Modulemd.ModuleStream() 51 mmd.import_from_string(yaml) 52 return mmd
53 54 @classmethod
55 - def from_modulemd(cls, mmd):
56 yaml_b64 = base64.b64encode(mmd.dumps().encode("utf-8")).decode("utf-8") 57 return models.Module(name=mmd.get_name(), stream=mmd.get_stream(), version=mmd.get_version(), 58 summary=mmd.get_summary(), description=mmd.get_description(), yaml_b64=yaml_b64)
59 60 @classmethod
61 - def validate(cls, mmd):
62 if not all([mmd.get_name(), mmd.get_stream(), mmd.get_version()]): 63 raise ValidationError("Module should contain name, stream and version")
64 65 @classmethod
66 - def add(cls, user, copr, module):
67 if not user.can_build_in(copr): 68 raise exceptions.InsufficientRightsException("You don't have permissions to build in this copr.") 69 70 module.copr_id = copr.id 71 module.copr = copr 72 module.created_on = time.time() 73 74 db.session.add(module) 75 return module
76 77 @classmethod
78 - def set_defaults_for_optional_params(cls, mmd, filename=None):
79 mmd.set_name(mmd.get_name() or str(os.path.splitext(filename)[0])) 80 mmd.set_stream(mmd.get_stream() or "master") 81 mmd.set_version(mmd.get_version() or int(datetime.now().strftime("%Y%m%d%H%M%S")))
82
83 84 -class ModuleBuildFacade(object):
85 - def __init__(self, user, copr, yaml, filename=None):
86 self.user = user 87 self.copr = copr 88 self.yaml = yaml 89 self.filename = filename 90 91 self.modulemd = ModulesLogic.yaml2modulemd(yaml) 92 ModulesLogic.set_defaults_for_optional_params(self.modulemd, filename=filename) 93 ModulesLogic.validate(self.modulemd)
94
95 - def submit_build(self):
96 module = ModulesLogic.add(self.user, self.copr, ModulesLogic.from_modulemd(self.modulemd)) 97 self.add_builds(self.modulemd.get_rpm_components(), module) 98 return module
99 100 @classmethod
101 - def get_build_batches(cls, rpms):
102 """ 103 Determines Which component should be built in which batch. Returns an ordered list of grouped components, 104 first group of components should be built as a first batch, second as second and so on. 105 Particular components groups are represented by dicts and can by built in a random order within the batch. 106 :return: list of lists 107 """ 108 batches = defaultdict(dict) 109 for pkgname, rpm in rpms.items(): 110 batches[rpm.get_buildorder()][pkgname] = rpm 111 return [batches[number] for number in sorted(batches.keys())]
112
113 - def add_builds(self, rpms, module):
114 blocked_by_id = None 115 for group in self.get_build_batches(rpms): 116 batch = models.Batch() 117 batch.blocked_by_id = blocked_by_id 118 db.session.add(batch) 119 for pkgname, rpm in group.items(): 120 clone_url = self.get_clone_url(pkgname, rpm) 121 build = builds_logic.BuildsLogic.create_new_from_scm(self.user, self.copr, scm_type="git", 122 clone_url=clone_url, committish=rpm.get_ref()) 123 build.batch = batch 124 build.batch_id = batch.id 125 build.module_id = module.id 126 db.session.add(build) 127 128 # Every batch needs to by blocked by the previous one 129 blocked_by_id = batch.id
130
131 - def get_clone_url(self, pkgname, rpm):
132 if rpm.get_repository(): 133 return rpm.get_repository() 134 return self.default_distgit.format(pkgname=pkgname)
135 136 @property
137 - def default_distgit(self):
138 # @TODO move to better place 139 return "https://src.fedoraproject.org/rpms/{pkgname}"
140
141 142 -class ModulemdGenerator(object):
143 - def __init__(self, name="", stream="", version=0, summary="", config=None):
144 self.config = config 145 licenses = Modulemd.SimpleSet() 146 licenses.add("unknown") 147 self.mmd = Modulemd.ModuleStream(mdversion=1, name=name, stream=stream, version=version, summary=summary, 148 description="", content_licenses=licenses, module_licenses=licenses)
149 150 @property
151 - def nsv(self):
152 return "{}-{}-{}".format(self.mmd.get_name(), self.mmd.get_stream(), self.mmd.get_version())
153
154 - def add_api(self, packages):
155 mmd_set = Modulemd.SimpleSet() 156 for package in packages: 157 mmd_set.add(str(package)) 158 self.mmd.set_rpm_api(mmd_set)
159
160 - def add_filter(self, packages):
161 mmd_set = Modulemd.SimpleSet() 162 for package in packages: 163 mmd_set.add(str(package)) 164 self.mmd.set_rpm_filter(mmd_set)
165
166 - def add_profiles(self, profiles):
167 for i, values in profiles: 168 name, packages = values 169 profile = Modulemd.Profile(name=name) 170 for package in packages: 171 profile.add_rpm(str(package)) 172 self.mmd.add_profile(profile)
173
174 - def add_components(self, packages, filter_packages, builds):
175 build_ids = sorted(list(set([int(id) for p, id in zip(packages, builds) 176 if p in filter_packages]))) 177 for package in filter_packages: 178 build_id = builds[packages.index(package)] 179 build = builds_logic.BuildsLogic.get_by_id(build_id).first() 180 build_chroot = self._build_chroot(build) 181 buildorder = build_ids.index(int(build.id)) 182 rationale = "User selected the package as a part of the module" 183 self.add_component(package, build, build_chroot, rationale, buildorder)
184
185 - def _build_chroot(self, build):
186 chroot = None 187 for chroot in build.build_chroots: 188 if chroot.name == "custom-1-x86_64": 189 break 190 return chroot
191
192 - def add_component(self, package_name, build, chroot, rationale, buildorder=1):
193 ref = str(chroot.git_hash) if chroot else "" 194 distgit_url = self.config["DIST_GIT_URL"].replace("/cgit", "/git") 195 url = os.path.join(distgit_url, build.copr.full_name, "{}.git".format(build.package.name)) 196 component = Modulemd.ComponentRpm(name=str(package_name), rationale=rationale, 197 repository=url, ref=ref, buildorder=1) 198 self.mmd.add_rpm_component(component)
199
200 - def generate(self):
201 return self.mmd.dumps()
202
203 204 -class ModuleProvider(object):
205 - def __init__(self, filename, yaml):
206 self.filename = filename 207 self.yaml = yaml
208 209 @classmethod
210 - def from_input(cls, obj):
211 if hasattr(obj, "read"): 212 return cls.from_file(obj) 213 return cls.from_url(obj)
214 215 @classmethod
216 - def from_file(cls, ref):
217 return cls(ref.filename, ref.read().decode("utf-8"))
218 219 @classmethod
220 - def from_url(cls, url):
221 if not url.endswith(".yaml"): 222 raise ValidationError("This URL doesn't point to a .yaml file") 223 224 request = requests.get(url) 225 if request.status_code != 200: 226 raise requests.RequestException("This URL seems to be wrong") 227 return cls(os.path.basename(url), request.text)
228