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

Source Code for Module coprs.logic.packages_logic

  1  import json 
  2  import time 
  3  import re 
  4   
  5  from sqlalchemy import or_ 
  6  from sqlalchemy import and_, bindparam, Integer 
  7  from sqlalchemy.sql import false, true, text 
  8   
  9  from coprs import app 
 10  from coprs import db 
 11  from coprs import exceptions 
 12  from coprs import models 
 13  from coprs import helpers 
 14  from coprs import forms 
 15   
 16  from coprs.logic import coprs_logic 
 17  from coprs.logic import users_logic 
 18  from coprs.logic import builds_logic 
 19   
 20  from coprs.constants import DEFAULT_BUILD_TIMEOUT 
 21   
 22  log = app.logger 
23 24 25 -class PackagesLogic(object):
26 27 @classmethod
28 - def get_by_id(cls, package_id):
30 31 @classmethod
32 - def get_all(cls, copr_id):
33 return (models.Package.query 34 .filter(models.Package.copr_id == copr_id))
35 36 @classmethod
37 - def get_copr_packages_list(cls, copr):
38 query_select = """ 39 SELECT package.name, build.pkg_version, build.submitted_on, package.webhook_rebuild, order_to_status(subquery2.min_order_for_a_build) AS status, build.source_status 40 FROM package 41 LEFT OUTER JOIN (select MAX(build.id) as max_build_id_for_a_package, package_id 42 FROM build 43 WHERE build.copr_id = :copr_id 44 GROUP BY package_id) as subquery1 ON subquery1.package_id = package.id 45 LEFT OUTER JOIN build ON build.id = subquery1.max_build_id_for_a_package 46 LEFT OUTER JOIN (select build_id, min(status_to_order(status)) as min_order_for_a_build 47 FROM build_chroot 48 GROUP BY build_id) as subquery2 ON subquery2.build_id = subquery1.max_build_id_for_a_package 49 WHERE package.copr_id = :copr_id; 50 """ 51 52 if db.engine.url.drivername == "sqlite": 53 def sqlite_status_to_order(x): 54 if x == 3: 55 return 1 56 elif x == 6: 57 return 2 58 elif x == 7: 59 return 3 60 elif x == 4: 61 return 4 62 elif x == 0: 63 return 5 64 elif x == 1: 65 return 6 66 elif x == 5: 67 return 7 68 elif x == 2: 69 return 8 70 elif x == 8: 71 return 9 72 elif x == 9: 73 return 10 74 return 1000
75 76 def sqlite_order_to_status(x): 77 if x == 1: 78 return 3 79 elif x == 2: 80 return 6 81 elif x == 3: 82 return 7 83 elif x == 4: 84 return 4 85 elif x == 5: 86 return 0 87 elif x == 6: 88 return 1 89 elif x == 7: 90 return 5 91 elif x == 8: 92 return 2 93 elif x == 9: 94 return 8 95 elif x == 10: 96 return 9 97 return 1000
98 99 conn = db.engine.connect() 100 conn.connection.create_function("status_to_order", 1, sqlite_status_to_order) 101 conn.connection.create_function("order_to_status", 1, sqlite_order_to_status) 102 statement = text(query_select) 103 statement.bindparams(bindparam("copr_id", Integer)) 104 result = conn.execute(statement, {"copr_id": copr.id}) 105 else: 106 statement = text(query_select) 107 statement.bindparams(bindparam("copr_id", Integer)) 108 result = db.engine.execute(statement, {"copr_id": copr.id}) 109 110 return result 111 112 @classmethod
113 - def get(cls, copr_id, package_name):
114 return models.Package.query.filter(models.Package.copr_id == copr_id, 115 models.Package.name == package_name)
116 117 @classmethod
118 - def get_for_webhook_rebuild(cls, copr_id, webhook_secret, clone_url, commits, ref_type, ref):
119 packages = (models.Package.query.join(models.Copr) 120 .filter(models.Copr.webhook_secret == webhook_secret) 121 .filter(models.Package.source_type == helpers.BuildSourceEnum("scm")) 122 .filter(models.Package.copr_id == copr_id) 123 .filter(models.Package.webhook_rebuild == true()) 124 .filter(models.Package.source_json.contains(clone_url.strip(".git")))) 125 126 result = [] 127 for package in packages: 128 if cls.commits_belong_to_package(package, commits, ref_type, ref): 129 result += [package] 130 return result
131 132 @classmethod
133 - def commits_belong_to_package(cls, package, commits, ref_type, ref):
134 if ref_type == "tag": 135 matches = re.search(r'(.*)-[^-]+-[^-]+$', ref) 136 if matches and package.name != matches.group(1): 137 return False 138 else: 139 return True 140 141 committish = package.source_json_dict.get("committish") or '' 142 if committish and not ref.endswith(committish): 143 return False 144 145 path_match = True 146 for commit in commits: 147 for file_path in commit['added'] + commit['removed'] + commit['modified']: 148 path_match = False 149 if cls.path_belong_to_package(package, file_path): 150 path_match = True 151 break 152 if not path_match: 153 return False 154 155 return True
156 157 @classmethod
158 - def path_belong_to_package(cls, package, file_path):
159 data = package.source_json_dict 160 norm_file_path = file_path.strip('./') 161 package_subdir = data.get('subdirectory') or '' 162 return norm_file_path.startswith(package_subdir.strip('./'))
163 164 @classmethod
165 - def add(cls, user, copr, package_name, source_type=helpers.BuildSourceEnum("unset"), source_json=json.dumps({})):
166 users_logic.UsersLogic.raise_if_cant_build_in_copr( 167 user, copr, 168 "You don't have permissions to build in this copr.") 169 170 if cls.exists(copr.id, package_name).all(): 171 raise exceptions.DuplicateException( 172 "Project {}/{} already has a package '{}'" 173 .format(copr.owner_name, copr.name, package_name)) 174 175 package = models.Package( 176 name=package_name, 177 copr_id=copr.id, 178 source_type=source_type, 179 source_json=source_json 180 ) 181 182 db.session.add(package) 183 184 return package
185 186 @classmethod
187 - def exists(cls, copr_id, package_name):
188 return (models.Package.query 189 .filter(models.Package.copr_id == copr_id) 190 .filter(models.Package.name == package_name))
191 192 193 @classmethod
194 - def delete_package(cls, user, package):
195 if not user.can_edit(package.copr): 196 raise exceptions.InsufficientRightsException( 197 "You are not allowed to delete package `{}`.".format(package.id)) 198 199 for build in package.builds: 200 builds_logic.BuildsLogic.delete_build(user, build) 201 202 db.session.delete(package)
203 204 205 @classmethod
206 - def reset_package(cls, user, package):
207 if not user.can_edit(package.copr): 208 raise exceptions.InsufficientRightsException( 209 "You are not allowed to reset package `{}`.".format(package.id)) 210 211 package.source_json = json.dumps({}) 212 package.source_type = helpers.BuildSourceEnum("unset") 213 214 db.session.add(package)
215 216 217 @classmethod
218 - def build_package(cls, user, copr, package, chroot_names=None, **build_options):
219 if not package.has_source_type_set or not package.source_json: 220 raise exceptions.NoPackageSourceException('Unset default source for package {0}'.format(package.name)) 221 return builds_logic.BuildsLogic.create_new(user, copr, package.source_type, package.source_json, chroot_names, **build_options)
222 223 224 @classmethod
225 - def batch_build(cls, user, copr, packages, chroot_names=None, **build_options):
226 new_builds = [] 227 228 batch = models.Batch() 229 db.session.add(batch) 230 231 for package in packages: 232 git_hashes = {} 233 skip_import = False 234 source_build = None 235 236 if (package.source_type == helpers.BuildSourceEnum('upload') or 237 package.source_type == helpers.BuildSourceEnum('link')): 238 source_build = package.last_build() 239 240 if not source_build or not source_build.build_chroots[0].git_hash: 241 raise exceptions.NoPackageSourceException( 242 "Could not get latest git hash for {}".format(package.name)) 243 244 for chroot_name in chroot_names: 245 git_hashes[chroot_name] = source_build.build_chroots[0].git_hash 246 skip_import = True 247 248 new_build = builds_logic.BuildsLogic.create_new( 249 user, 250 copr, 251 package.source_type, 252 package.source_json, 253 chroot_names, 254 git_hashes=git_hashes, 255 skip_import=skip_import, 256 batch=batch, 257 **build_options) 258 259 if source_build: 260 new_build.package_id = source_build.package_id 261 new_build.pkg_version = source_build.pkg_version 262 263 new_builds.append(new_build) 264 265 return new_builds
266