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