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