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 clone_url_stripped = re.sub(r'(\.git)?/*$', '', clone_url) 120 121 packages = (models.Package.query.join(models.Copr) 122 .filter(models.Copr.webhook_secret == webhook_secret) 123 .filter(models.Package.source_type == helpers.BuildSourceEnum("scm")) 124 .filter(models.Package.copr_id == copr_id) 125 .filter(models.Package.webhook_rebuild == true()) 126 .filter(models.Package.source_json.contains(clone_url_stripped))) 127 128 result = [] 129 for package in packages: 130 package_clone_url = package.source_json_dict.get('clone_url', '') 131 package_clone_url_stripped = re.sub(r'(\.git)?/*$', '', package_clone_url) 132 133 if package_clone_url_stripped != clone_url_stripped: 134 continue 135 136 if cls.commits_belong_to_package(package, commits, ref_type, ref): 137 result += [package] 138 139 return result
140 141 @classmethod
142 - def commits_belong_to_package(cls, package, commits, ref_type, ref):
143 if ref_type == "tag": 144 matches = re.search(r'(.*)-[^-]+-[^-]+$', ref) 145 if matches and package.name != matches.group(1): 146 return False 147 else: 148 return True 149 150 committish = package.source_json_dict.get("committish") or '' 151 if committish and not ref.endswith(committish): 152 return False 153 154 path_match = True 155 for commit in commits: 156 for file_path in commit['added'] + commit['removed'] + commit['modified']: 157 path_match = False 158 if cls.path_belong_to_package(package, file_path): 159 path_match = True 160 break 161 if not path_match: 162 return False 163 164 return True
165 166 @classmethod
167 - def path_belong_to_package(cls, package, file_path):
168 data = package.source_json_dict 169 norm_file_path = file_path.strip('./') 170 package_subdir = data.get('subdirectory') or '' 171 return norm_file_path.startswith(package_subdir.strip('./'))
172 173 @classmethod
174 - def add(cls, user, copr, package_name, source_type=helpers.BuildSourceEnum("unset"), source_json=json.dumps({})):
175 users_logic.UsersLogic.raise_if_cant_build_in_copr( 176 user, copr, 177 "You don't have permissions to build in this copr.") 178 179 if cls.exists(copr.id, package_name).all(): 180 raise exceptions.DuplicateException( 181 "Project {}/{} already has a package '{}'" 182 .format(copr.owner_name, copr.name, package_name)) 183 184 package = models.Package( 185 name=package_name, 186 copr_id=copr.id, 187 source_type=source_type, 188 source_json=source_json 189 ) 190 191 db.session.add(package) 192 193 return package
194 195 @classmethod
196 - def exists(cls, copr_id, package_name):
197 return (models.Package.query 198 .filter(models.Package.copr_id == copr_id) 199 .filter(models.Package.name == package_name))
200 201 202 @classmethod
203 - def delete_package(cls, user, package):
204 if not user.can_edit(package.copr): 205 raise exceptions.InsufficientRightsException( 206 "You are not allowed to delete package `{}`.".format(package.id)) 207 208 for build in package.builds: 209 builds_logic.BuildsLogic.delete_build(user, build) 210 211 db.session.delete(package)
212 213 214 @classmethod
215 - def reset_package(cls, user, package):
216 if not user.can_edit(package.copr): 217 raise exceptions.InsufficientRightsException( 218 "You are not allowed to reset package `{}`.".format(package.id)) 219 220 package.source_json = json.dumps({}) 221 package.source_type = helpers.BuildSourceEnum("unset") 222 223 db.session.add(package)
224 225 226 @classmethod
227 - def build_package(cls, user, copr, package, chroot_names=None, **build_options):
228 if not package.has_source_type_set or not package.source_json: 229 raise exceptions.NoPackageSourceException('Unset default source for package {0}'.format(package.name)) 230 return builds_logic.BuildsLogic.create_new(user, copr, package.source_type, package.source_json, chroot_names, **build_options)
231 232 233 @classmethod
234 - def batch_build(cls, user, copr, packages, chroot_names=None, **build_options):
235 new_builds = [] 236 237 batch = models.Batch() 238 db.session.add(batch) 239 240 for package in packages: 241 git_hashes = {} 242 skip_import = False 243 source_build = None 244 245 if (package.source_type == helpers.BuildSourceEnum('upload') or 246 package.source_type == helpers.BuildSourceEnum('link')): 247 source_build = package.last_build() 248 249 if not source_build or not source_build.build_chroots[0].git_hash: 250 raise exceptions.NoPackageSourceException( 251 "Could not get latest git hash for {}".format(package.name)) 252 253 for chroot_name in chroot_names: 254 git_hashes[chroot_name] = source_build.build_chroots[0].git_hash 255 skip_import = True 256 257 new_build = builds_logic.BuildsLogic.create_new( 258 user, 259 copr, 260 package.source_type, 261 package.source_json, 262 chroot_names, 263 git_hashes=git_hashes, 264 skip_import=skip_import, 265 batch=batch, 266 **build_options) 267 268 if source_build: 269 new_build.package_id = source_build.package_id 270 new_build.pkg_version = source_build.pkg_version 271 272 new_builds.append(new_build) 273 274 return new_builds
275