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