def origin_update_pending(apiurl, origin_project, package, target_project, policy, supersede, frequency): apiurl_remote, project_remote = project_remote_apiurl( apiurl, origin_project) request_actions = request_action_list_source(apiurl_remote, project_remote, package, include_release=True) for request, action in sorted(request_actions, key=lambda i: i[0].reqid, reverse=True): reviews_not_allowed = reviews_filter_allowed( reviews_remaining(request, True), policy['pending_submission_allowed_reviews_update']) if len(reviews_not_allowed): continue identifier = request_remote_identifier(apiurl, apiurl_remote, request.reqid) message = 'Newer pending source available from package origin. See {}.'.format( identifier) src_project = project_remote_prefixed(apiurl, apiurl_remote, action.src_project) return request_create_submit(apiurl, src_project, action.src_package, target_project, package, message=message, revision=action.src_rev, supersede=supersede, frequency=frequency) return False
def origin_history(apiurl, target_project, package, user): history = [] request_actions = request_action_list_source(apiurl, target_project, package, states=['all']) for request, action in sorted(request_actions, key=lambda i: i[0].reqid, reverse=True): annotation = origin_annotation_load(request, action, user) history.append({ # Not completely accurate, but more useful to have non-annotated # entries than to exclude them. 'origin': annotation['origin'] if annotation else action.src_project, 'request': request.reqid, 'state': request.state.name, 'source_project': action.src_project, 'source_package': action.src_package, 'source_revision': action.src_rev, }) return history
def origin_find_fallback(apiurl, target_project, package, source_hash, user): # Search accepted requests (newest to oldest), find the last review made by # the specified user, load comment as annotation, and extract origin. request_actions = request_action_list_source(apiurl, target_project, package, states=['accepted']) for request, action in sorted(request_actions, key=lambda i: i[0].reqid, reverse=True): annotation = origin_annotation_load(request, action, user) if not annotation: continue return OriginInfo(annotation.get('origin'), False) # Fallback to searching workaround project. fallback_workaround = config_load( apiurl, target_project).get('fallback-workaround') if fallback_workaround: if project_source_contain(apiurl, fallback_workaround['project'], package, source_hash): return OriginInfo(fallback_workaround['origin'], False) # Attempt to find a revision of target package that matches an origin. first = True for source_hash_consider in package_source_hash_history( apiurl, target_project, package, include_project_link=True): if first: first = False continue origin_info = origin_find(apiurl, target_project, package, source_hash_consider, pending_allow=False, fallback=False) if origin_info: return origin_info return None
def project_source_pending(apiurl, project, package, source_hash): apiurl_remote, project_remote = project_remote_apiurl(apiurl, project) request_actions = request_action_list_source(apiurl_remote, project_remote, package, states=['new', 'review'], include_release=True) for request, action in request_actions: source_hash_consider = package_source_hash(apiurl_remote, action.src_project, action.src_package, action.src_rev) project_source_log('pending', project, source_hash_consider, source_hash) if source_hash_consider == source_hash: return PendingRequestInfo( request_remote_identifier(apiurl, apiurl_remote, request.reqid), reviews_remaining(request, True)) return False
def origin_update(apiurl, target_project, package): origin_info = origin_find(apiurl, target_project, package) if not origin_info: # Cases for a lack of origin: # - package does not exist in target_project # - initial package submission from devel (lacking devel meta on package) # - initial package submission overriden to allow from no origin # - origin project/package deleted # # Ideally, the second case should never be used and instead the first # case should be opted for instead. # Check for accepted source submission with devel annotation and create # change_devel request as automatic follow-up to approval. config = config_load(apiurl, target_project) request_actions = request_action_list_source(apiurl, target_project, package, states=['accepted']) for request, action in sorted(request_actions, key=lambda i: i[0].reqid, reverse=True): annotation = origin_annotation_load(request, action, config['review-user']) if not annotation: continue origin = annotation.get('origin') if origin_workaround_check(origin): continue if origin not in config_origin_list(config, apiurl, target_project): message = f'Set devel project based on initial submission in request#{request.reqid}.' return request_create_change_devel(apiurl, origin, package, target_project, message=message) # Either the first or one of the second two cases. exists = entity_exists(apiurl, target_project, package) origin, version = origin_potential(apiurl, target_project, package, not exists) if origin is None: if not exists: # Package does not exist to be deleted. return False # Package is not found in any origin so request deletion. message = 'Package not available from any potential origin.' return request_create_delete(apiurl, target_project, package, message) if not exists: if origin_update_initial_blacklisted(apiurl, target_project, package): return False message = 'Submitting new package from highest potential origin.' return request_create_submit(apiurl, origin, package, target_project, message=message, ignore_if_any_request=True) # No longer tracking previous origin (likely removed from origin) so # submit from the highest potential origin. message = 'Submitting package from highest potential origin.' return request_create_submit(apiurl, origin, package, target_project, message=message) if origin_workaround_check(origin_info.project): # Do not attempt to update workarounds as the expected flow is to either # to explicitely switched back to non-workaround or source to match at # some point and implicitily switch. return False if origin_info.pending: # Already accepted source ahead of origin so nothing to do. return False policy = policy_get(apiurl, target_project, package, origin_info.project) if not policy['automatic_updates']: return False mode = origin_update_mode(apiurl, target_project, package, policy, origin_info.project) if mode['skip']: return False age = package_source_age(apiurl, origin_info.project, package).total_seconds() if age < int(mode['delay']): return False supersede = str2bool(str(mode['supersede'])) frequency = int(mode['frequency']) if policy['pending_submission_allow']: request_id = origin_update_pending(apiurl, origin_info.project, package, target_project, policy, supersede, frequency) if request_id: return request_id message = 'Newer source available from package origin.' return request_create_submit(apiurl, origin_info.project, package, target_project, message=message, supersede=supersede, frequency=frequency)