Trees | Indices | Help |
---|
|
1 import json 2 import re 3 4 from sqlalchemy import bindparam, Integer, func 5 from sqlalchemy.sql import true, text 6 from sqlalchemy.orm import selectinload 7 8 from coprs import app 9 from coprs import db 10 from coprs import exceptions 11 from coprs import models 12 from coprs import helpers 13 14 from coprs.logic import users_logic 15 from coprs.logic import builds_logic 16 from copr_common.enums import StatusEnum 17 18 log = app.logger22 23 @classmethod 26 27 @classmethod 31 32 @classmethod 36 37 @classmethod72 73 @classmethod39 packages = (models.Package.query.filter_by(copr_dir_id=copr_dir_id) 40 .order_by(models.Package.name).all()) 41 pkg_ids = [package.id for package in packages] 42 builds_ids = models.Build.query \ 43 .filter(models.Build.package_id.in_(pkg_ids)) \ 44 .with_entities(func.max(models.Build.id)) \ 45 .group_by(models.Build.package_id) 46 47 # map package.id => package object in packages array 48 packages_map = {package.id: package for package in packages} 49 50 builds = (models.Build.query.filter(models.Build.id.in_(builds_ids)) 51 .options(selectinload('build_chroots')) 52 .yield_per(1000)) 53 54 for build in builds: 55 class SmallBuild(): 56 pass57 58 if not build.package_id: 59 continue 60 61 small_build_object = SmallBuild() 62 for param in ['state', 'status', 'pkg_version', 63 'submitted_on']: 64 # we don't want to keep all the attributes here in memory, and 65 # also we don't need any further info about assigned 66 # build_chroot(s). So we only pick the info we need, and throw 67 # the expensive objects away. 68 setattr(small_build_object, param, getattr(build, param)) 69 packages_map[build.package_id].latest_build = small_build_object 70 71 return packages75 return models.Package.query.filter(models.Package.copr_id == copr_id, 76 models.Package.name == package_name)77 78 @classmethod80 return models.Package.query.filter(models.Package.copr_dir_id == copr_dir_id, 81 models.Package.name == package_name)82 83 @classmethod85 return models.Package.query.join(models.CoprDir).filter( 86 models.CoprDir.id==copr_dir.id, 87 models.Package.name==package_name 88 )89 90 @classmethod92 package = cls.get_by_dir(copr_dir, package_name).first() 93 94 if package: 95 return package 96 97 package = models.Package( 98 name=src_pkg.name, 99 copr=src_pkg.copr, 100 source_type=src_pkg.source_type, 101 source_json=src_pkg.source_json, 102 copr_dir=copr_dir) 103 104 db.session.add(package) 105 return package106 107 @classmethod109 clone_url_stripped = re.sub(r'(\.git)?/*$', '', clone_url) 110 111 packages = (models.Package.query.join(models.Copr) 112 .filter(models.Copr.webhook_secret == webhook_secret) 113 .filter(models.Package.source_type == helpers.BuildSourceEnum("scm")) 114 .filter(models.Package.copr_id == copr_id) 115 .filter(models.Package.webhook_rebuild == true()) 116 .filter(models.Package.source_json.contains(clone_url_stripped))) 117 118 result = [] 119 for package in packages: 120 package_clone_url = package.source_json_dict.get('clone_url', '') 121 package_clone_url_stripped = re.sub(r'(\.git)?/*$', '', package_clone_url) 122 123 if package_clone_url_stripped != clone_url_stripped: 124 continue 125 126 if cls.commits_belong_to_package(package, commits, ref_type, ref): 127 result += [package] 128 129 return result130 131 @classmethod133 if ref_type == "tag": 134 matches = re.search(r'(.*)-[^-]+-[^-]+$', ref) 135 if matches and package.name != matches.group(1): 136 return False 137 else: 138 return True 139 140 committish = package.source_json_dict.get("committish") or '' 141 if committish and not ref.endswith(committish): 142 return False 143 144 for commit in commits: 145 subdir = package.source_json_dict.get('subdirectory') 146 sm = helpers.SubdirMatch(subdir) 147 changed = set() 148 for ch in ['added', 'removed', 'modified']: 149 changed |= set(commit.get(ch, [])) 150 151 for file_path in changed: 152 if sm.match(file_path): 153 return True 154 155 return False156 157 @classmethod158 - def add(cls, user, copr_dir, package_name, source_type=helpers.BuildSourceEnum("unset"), source_json=json.dumps({})):159 users_logic.UsersLogic.raise_if_cant_build_in_copr( 160 user, copr_dir.copr, 161 "You don't have permissions to build in this copr.") 162 163 if cls.exists(copr_dir.id, package_name).all(): 164 raise exceptions.DuplicateException( 165 "Project dir {} already has a package '{}'" 166 .format(copr_dir.full_name, package_name)) 167 168 package = models.Package( 169 name=package_name, 170 copr=copr_dir.copr, 171 copr_dir=copr_dir, 172 source_type=source_type, 173 source_json=source_json, 174 ) 175 176 db.session.add(package) 177 return package178 179 @classmethod181 return (models.Package.query 182 .filter(models.Package.copr_dir_id == copr_dir_id) 183 .filter(models.Package.name == package_name))184 185 186 @classmethod188 if not user.can_edit(package.copr): 189 raise exceptions.InsufficientRightsException( 190 "You are not allowed to delete package `{}`.".format(package.id)) 191 192 to_delete = [] 193 for build in package.builds: 194 to_delete.append(build) 195 196 builds_logic.BuildsLogic.delete_multiple_builds(user, to_delete) 197 db.session.delete(package)198 199 200 @classmethod202 if not user.can_edit(package.copr): 203 raise exceptions.InsufficientRightsException( 204 "You are not allowed to reset package `{}`.".format(package.id)) 205 206 package.source_json = json.dumps({}) 207 package.source_type = helpers.BuildSourceEnum("unset") 208 209 db.session.add(package)210 211 212 @classmethod213 - def build_package(cls, user, copr, package, chroot_names=None, copr_dirname=None, **build_options):214 if not package.has_source_type_set or not package.source_json: 215 raise exceptions.NoPackageSourceException('Unset default source for package {0}'.format(package.name)) 216 return builds_logic.BuildsLogic.create_new(user, copr, package.source_type, package.source_json, 217 chroot_names, copr_dirname=copr_dirname, **build_options)218 219 220 @classmethod222 new_builds = [] 223 224 batch = models.Batch() 225 db.session.add(batch) 226 227 for package in packages: 228 git_hashes = {} 229 skip_import = False 230 source_build = None 231 232 if (package.source_type == helpers.BuildSourceEnum('upload') or 233 package.source_type == helpers.BuildSourceEnum('link')): 234 source_build = package.last_build() 235 236 if not source_build or not source_build.build_chroots[0].git_hash: 237 raise exceptions.NoPackageSourceException( 238 "Could not get latest git hash for {}".format(package.name)) 239 240 for chroot_name in chroot_names: 241 git_hashes[chroot_name] = source_build.build_chroots[0].git_hash 242 skip_import = True 243 244 new_build = builds_logic.BuildsLogic.create_new( 245 user, 246 copr, 247 package.source_type, 248 package.source_json, 249 chroot_names, 250 git_hashes=git_hashes, 251 skip_import=skip_import, 252 batch=batch, 253 **build_options) 254 255 if source_build: 256 new_build.package_id = source_build.package_id 257 new_build.pkg_version = source_build.pkg_version 258 259 new_builds.append(new_build) 260 261 return new_builds262 263 @classmethod265 pkgs_to_delete = models.Package.query\ 266 .join(models.Copr, models.Package.copr_id == models.Copr.id)\ 267 .filter(models.Copr.deleted == True) 268 269 counter = 0 270 for pkg in pkgs_to_delete: 271 cls.delete_package(pkg.copr.user, pkg) 272 counter += 1 273 if counter >= 100: 274 db.session.commit() 275 counter = 0 276 277 if counter > 0: 278 db.session.commit()279 280 @classmethod282 builds = {} 283 for chroot in package.chroots: 284 for build in reversed(package.builds): 285 try: 286 build_chroot = build.chroots_dict_by_name[chroot.name] 287 except KeyError: 288 continue 289 if build_chroot.status not in [StatusEnum("succeeded"), StatusEnum("forked")]: 290 continue 291 if build not in builds: 292 builds[build] = [build_chroot] 293 else: 294 builds[build].append(build_chroot) 295 break 296 return builds297
Trees | Indices | Help |
---|
Generated by Epydoc 3.0.1 | http://epydoc.sourceforge.net |