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_dir_id):
35 36 @classmethod
37 - def get_all_in_copr(cls, copr_id):
38 return (models.Package.query 39 .filter(models.Package.copr_id == copr_id))
40 41 @classmethod
42 - def get_copr_packages_list(cls, copr_dir):
43 query_select = """ 44 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 45 FROM package 46 LEFT OUTER JOIN (select MAX(build.id) as max_build_id_for_a_package, package_id 47 FROM build 48 WHERE build.copr_dir_id = :copr_dir_id 49 GROUP BY package_id) as subquery1 ON subquery1.package_id = package.id 50 LEFT OUTER JOIN build ON build.id = subquery1.max_build_id_for_a_package 51 LEFT OUTER JOIN (select build_id, min(status_to_order(status)) as min_order_for_a_build 52 FROM build_chroot 53 GROUP BY build_id) as subquery2 ON subquery2.build_id = subquery1.max_build_id_for_a_package 54 WHERE package.copr_dir_id = :copr_dir_id; 55 """ 56 57 if db.engine.url.drivername == "sqlite": 58 def sqlite_status_to_order(x): 59 if x == 3: 60 return 1 61 elif x == 6: 62 return 2 63 elif x == 7: 64 return 3 65 elif x == 4: 66 return 4 67 elif x == 0: 68 return 5 69 elif x == 1: 70 return 6 71 elif x == 5: 72 return 7 73 elif x == 2: 74 return 8 75 elif x == 8: 76 return 9 77 elif x == 9: 78 return 10 79 return 1000
80 81 def sqlite_order_to_status(x): 82 if x == 1: 83 return 3 84 elif x == 2: 85 return 6 86 elif x == 3: 87 return 7 88 elif x == 4: 89 return 4 90 elif x == 5: 91 return 0 92 elif x == 6: 93 return 1 94 elif x == 7: 95 return 5 96 elif x == 8: 97 return 2 98 elif x == 9: 99 return 8 100 elif x == 10: 101 return 9 102 return 1000
103 104 conn = db.engine.connect() 105 conn.connection.create_function("status_to_order", 1, sqlite_status_to_order) 106 conn.connection.create_function("order_to_status", 1, sqlite_order_to_status) 107 statement = text(query_select) 108 statement.bindparams(bindparam("copr_dir_id", Integer)) 109 result = conn.execute(statement, {"copr_dir_id": copr_dir.id}) 110 else: 111 statement = text(query_select) 112 statement.bindparams(bindparam("copr_dir_id", Integer)) 113 result = db.engine.execute(statement, {"copr_dir_id": copr_dir.id}) 114 115 return result 116 117 @classmethod
118 - def get_list_by_copr(cls, copr_id, package_name):
119 return models.Package.query.filter(models.Package.copr_id == copr_id, 120 models.Package.name == package_name)
121 122 @classmethod
123 - def get(cls, copr_dir_id, package_name):
124 return models.Package.query.filter(models.Package.copr_dir_id == copr_dir_id, 125 models.Package.name == package_name)
126 127 @classmethod
128 - def get_by_dir_name(cls, copr_dir_name, package_name):
129 return models.Package.query.join(models.CoprDir).filter( 130 models.CoprDir.name == copr_dir_name, models.Package.name == package_name)
131 132 @classmethod
133 - def get_or_create(cls, copr_dir, package_name, src_pkg):
134 package = cls.get_by_dir_name(copr_dir.name, package_name).first() 135 136 if package: 137 return package 138 139 package = models.Package( 140 name=src_pkg.name, 141 copr=src_pkg.copr, 142 source_type=src_pkg.source_type, 143 source_json=src_pkg.source_json, 144 copr_dir=copr_dir) 145 146 db.session.add(package) 147 return package
148 149 @classmethod
150 - def get_for_webhook_rebuild(cls, copr_id, webhook_secret, clone_url, commits, ref_type, ref):
151 clone_url_stripped = re.sub(r'(\.git)?/*$', '', clone_url) 152 153 packages = (models.Package.query.join(models.Copr) 154 .filter(models.Copr.webhook_secret == webhook_secret) 155 .filter(models.Package.source_type == helpers.BuildSourceEnum("scm")) 156 .filter(models.Package.copr_id == copr_id) 157 .filter(models.Package.webhook_rebuild == true()) 158 .filter(models.Package.source_json.contains(clone_url_stripped))) 159 160 result = [] 161 for package in packages: 162 package_clone_url = package.source_json_dict.get('clone_url', '') 163 package_clone_url_stripped = re.sub(r'(\.git)?/*$', '', package_clone_url) 164 165 if package_clone_url_stripped != clone_url_stripped: 166 continue 167 168 if cls.commits_belong_to_package(package, commits, ref_type, ref): 169 result += [package] 170 171 return result
172 173 @classmethod
174 - def commits_belong_to_package(cls, package, commits, ref_type, ref):
175 if ref_type == "tag": 176 matches = re.search(r'(.*)-[^-]+-[^-]+$', ref) 177 if matches and package.name != matches.group(1): 178 return False 179 else: 180 return True 181 182 committish = package.source_json_dict.get("committish") or '' 183 if committish and not ref.endswith(committish): 184 return False 185 186 path_match = True 187 for commit in commits: 188 for file_path in commit['added'] + commit['removed'] + commit['modified']: 189 path_match = False 190 if cls.path_belong_to_package(package, file_path): 191 path_match = True 192 break 193 if not path_match: 194 return False 195 196 return True
197 198 @classmethod
199 - def path_belong_to_package(cls, package, file_path):
200 data = package.source_json_dict 201 norm_file_path = file_path.strip('./') 202 package_subdir = data.get('subdirectory') or '' 203 return norm_file_path.startswith(package_subdir.strip('./'))
204 205 @classmethod
206 - def add(cls, user, copr_dir, package_name, source_type=helpers.BuildSourceEnum("unset"), source_json=json.dumps({})):
207 users_logic.UsersLogic.raise_if_cant_build_in_copr( 208 user, copr_dir.copr, 209 "You don't have permissions to build in this copr.") 210 211 if cls.exists(copr_dir.id, package_name).all(): 212 raise exceptions.DuplicateException( 213 "Project dir {} already has a package '{}'" 214 .format(copr_dir.full_name, package_name)) 215 216 package = models.Package( 217 name=package_name, 218 copr=copr_dir.copr, 219 copr_dir=copr_dir, 220 source_type=source_type, 221 source_json=source_json, 222 ) 223 224 db.session.add(package) 225 return package
226 227 @classmethod
228 - def exists(cls, copr_dir_id, package_name):
229 return (models.Package.query 230 .filter(models.Package.copr_dir_id == copr_dir_id) 231 .filter(models.Package.name == package_name))
232 233 234 @classmethod
235 - def delete_package(cls, user, package):
236 if not user.can_edit(package.copr): 237 raise exceptions.InsufficientRightsException( 238 "You are not allowed to delete package `{}`.".format(package.id)) 239 240 for build in package.builds: 241 builds_logic.BuildsLogic.delete_build(user, build) 242 243 db.session.delete(package)
244 245 246 @classmethod
247 - def reset_package(cls, user, package):
248 if not user.can_edit(package.copr): 249 raise exceptions.InsufficientRightsException( 250 "You are not allowed to reset package `{}`.".format(package.id)) 251 252 package.source_json = json.dumps({}) 253 package.source_type = helpers.BuildSourceEnum("unset") 254 255 db.session.add(package)
256 257 258 @classmethod
259 - def build_package(cls, user, copr, package, chroot_names=None, **build_options):
260 if not package.has_source_type_set or not package.source_json: 261 raise exceptions.NoPackageSourceException('Unset default source for package {0}'.format(package.name)) 262 return builds_logic.BuildsLogic.create_new(user, copr, package.source_type, package.source_json, chroot_names, **build_options)
263 264 265 @classmethod
266 - def batch_build(cls, user, copr, packages, chroot_names=None, **build_options):
267 new_builds = [] 268 269 batch = models.Batch() 270 db.session.add(batch) 271 272 for package in packages: 273 git_hashes = {} 274 skip_import = False 275 source_build = None 276 277 if (package.source_type == helpers.BuildSourceEnum('upload') or 278 package.source_type == helpers.BuildSourceEnum('link')): 279 source_build = package.last_build() 280 281 if not source_build or not source_build.build_chroots[0].git_hash: 282 raise exceptions.NoPackageSourceException( 283 "Could not get latest git hash for {}".format(package.name)) 284 285 for chroot_name in chroot_names: 286 git_hashes[chroot_name] = source_build.build_chroots[0].git_hash 287 skip_import = True 288 289 new_build = builds_logic.BuildsLogic.create_new( 290 user, 291 copr, 292 package.source_type, 293 package.source_json, 294 chroot_names, 295 git_hashes=git_hashes, 296 skip_import=skip_import, 297 batch=batch, 298 **build_options) 299 300 if source_build: 301 new_build.package_id = source_build.package_id 302 new_build.pkg_version = source_build.pkg_version 303 304 new_builds.append(new_build) 305 306 return new_builds
307