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 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 == 0: 55 return 0 56 elif x == 3: 57 return 1 58 elif x == 6: 59 return 2 60 elif x == 7: 61 return 3 62 elif x == 4: 63 return 4 64 elif x == 1: 65 return 5 66 elif x == 5: 67 return 6 68 return 1000
69 70 def sqlite_order_to_status(x): 71 if x == 0: 72 return 0 73 elif x == 1: 74 return 3 75 elif x == 2: 76 return 6 77 elif x == 3: 78 return 7 79 elif x == 4: 80 return 4 81 elif x == 5: 82 return 1 83 elif x == 6: 84 return 5 85 return 1000
86 87 conn = db.engine.connect() 88 conn.connection.create_function("status_to_order", 1, sqlite_status_to_order) 89 conn.connection.create_function("order_to_status", 1, sqlite_order_to_status) 90 statement = text(query_select) 91 statement.bindparams(bindparam("copr_id", Integer)) 92 result = conn.execute(statement, {"copr_id": copr.id}) 93 else: 94 statement = text(query_select) 95 statement.bindparams(bindparam("copr_id", Integer)) 96 result = db.engine.execute(statement, {"copr_id": copr.id}) 97 98 return result 99 100 @classmethod
101 - def get(cls, copr_id, package_name):
102 return models.Package.query.filter(models.Package.copr_id == copr_id, 103 models.Package.name == package_name)
104 105 @classmethod
106 - def get_for_webhook_rebuild(cls, copr_id, webhook_secret, clone_url, commits, ref_type, ref):
107 packages = (models.Package.query.join(models.Copr) 108 .filter(models.Copr.webhook_secret == webhook_secret) 109 .filter(models.Package.copr_id == copr_id) 110 .filter(models.Package.webhook_rebuild == true()) 111 .filter(models.Package.source_json.contains(clone_url.strip(".git")))) 112 113 result = [] 114 for package in packages: 115 if cls.commits_belong_to_package(package, commits, ref_type, ref): 116 result += [package] 117 return result
118 119 @classmethod
120 - def commits_belong_to_package(cls, package, commits, ref_type, ref):
121 if ref_type == "tag": 122 # way to exclude some packages from building for Tito method 123 if package.source_type_text == "git_and_tito": 124 matches = re.search(r'(.*)-[^-]+-[^-]+$', ref) 125 if matches and package.name != matches.group(1): 126 return False 127 return True 128 129 if package.source_type_text == "git_and_tito": 130 branch = package.source_json_dict["git_branch"] 131 if branch and not ref.endswith("/"+branch): 132 return False 133 elif package.source_type_text == "mock_scm": 134 branch = package.source_json_dict["scm_branch"] 135 if branch and not ref.endswith("/"+branch): 136 return False 137 138 if package.source_type_text == "git_and_tito": 139 path_match = False 140 for commit in commits: 141 for file_path in commit['added'] + commit['removed'] + commit['modified']: 142 if cls.path_belong_to_package(package, file_path): 143 path_match = True 144 break 145 if not path_match: 146 return False 147 148 return True
149 150 @classmethod
151 - def path_belong_to_package(cls, package, file_path):
152 if package.source_type_text == "git_and_tito": 153 data = package.source_json_dict 154 return file_path.startswith(data["git_dir"] or '') 155 else: 156 return True
157 158 @classmethod
159 - def add(cls, user, copr, package_name, source_type=helpers.BuildSourceEnum("unset"), source_json=json.dumps({})):
160 users_logic.UsersLogic.raise_if_cant_build_in_copr( 161 user, copr, 162 "You don't have permissions to build in this copr.") 163 164 if cls.exists(copr.id, package_name).all(): 165 raise exceptions.DuplicateException( 166 "Project {}/{} already has a package '{}'" 167 .format(copr.owner_name, copr.name, package_name)) 168 169 package = models.Package( 170 name=package_name, 171 copr_id=copr.id, 172 source_type=source_type, 173 source_json=source_json 174 ) 175 176 db.session.add(package) 177 178 return package
179 180 @classmethod
181 - def exists(cls, copr_id, package_name):
182 return (models.Package.query 183 .filter(models.Package.copr_id == copr_id) 184 .filter(models.Package.name == package_name))
185 186 187 @classmethod
188 - def delete_package(cls, user, package):
189 if not user.can_edit(package.copr): 190 raise exceptions.InsufficientRightsException( 191 "You are not allowed to delete package `{}`.".format(package.id)) 192 193 for build in package.builds: 194 builds_logic.BuildsLogic.delete_build(user, build) 195 196 db.session.delete(package)
197 198 199 @classmethod
200 - def reset_package(cls, user, package):
201 if not user.can_edit(package.copr): 202 raise exceptions.InsufficientRightsException( 203 "You are not allowed to reset package `{}`.".format(package.id)) 204 205 package.source_json = json.dumps({}) 206 package.source_type = helpers.BuildSourceEnum("unset") 207 208 db.session.add(package)
209 210 211 @classmethod
212 - def build_package(cls, user, copr, package, chroot_names=None, **build_options):
213 if not package.has_source_type_set or not package.source_json: 214 raise NoPackageSourceException('Unset default source for package {package}'.format(package.name)) 215 return builds_logic.BuildsLogic.create_new(user, copr, package.source_type, package.source_json, chroot_names, **build_options)
216 217 218 @classmethod
219 - def batch_build(cls, user, copr, packages, chroot_names=None, **build_options):
220 new_builds = [] 221 222 for package in packages: 223 git_hashes = {} 224 skip_import = False 225 source_build = None 226 227 if package.source_type == helpers.BuildSourceEnum('upload'): 228 source_build = package.last_build() 229 230 if not source_build or not source_build.build_chroots[0].git_hash: 231 raise exceptions.NoPackageSourceException( 232 "Could not get latest git hash for {}".format(package.name)) 233 234 for chroot_name in chroot_names: 235 git_hashes[chroot_name] = source_build.build_chroots[0].git_hash 236 skip_import = True 237 238 new_build = builds_logic.BuildsLogic.create_new( 239 user, 240 copr, 241 package.source_type, 242 package.source_json, 243 chroot_names, 244 git_hashes=git_hashes, 245 skip_import=skip_import, 246 **build_options) 247 248 if source_build: 249 new_build.package_id = source_build.package_id 250 new_build.pkg_version = source_build.pkg_version 251 252 new_builds.append(new_build) 253 254 return new_builds
255