2022-02-18 10:16:17 +01:00
|
|
|
from lxml import etree as ET
|
2014-03-05 15:12:45 +01:00
|
|
|
|
2014-03-04 15:30:49 +01:00
|
|
|
from osc import oscerr
|
2014-03-05 15:12:45 +01:00
|
|
|
from osc.core import http_GET
|
|
|
|
|
2014-03-04 09:39:14 +01:00
|
|
|
from osclib.request_finder import RequestFinder
|
2019-04-12 13:43:38 +02:00
|
|
|
from osclib.freeze_command import MAX_FROZEN_AGE
|
2014-03-04 15:30:49 +01:00
|
|
|
|
2014-05-20 17:05:00 +02:00
|
|
|
SELECT = 'select'
|
|
|
|
# SUPERSEDE = 'supersede'
|
|
|
|
MOVE = 'move'
|
|
|
|
|
|
|
|
|
2014-03-04 15:30:49 +01:00
|
|
|
class SelectCommand(object):
|
|
|
|
|
2015-07-16 15:09:26 +02:00
|
|
|
def __init__(self, api, target_project):
|
2014-03-04 09:39:14 +01:00
|
|
|
self.api = api
|
2014-06-04 16:54:21 +02:00
|
|
|
self.affected_projects = set()
|
2015-07-16 15:09:26 +02:00
|
|
|
self.target_project = target_project
|
2014-03-04 09:39:14 +01:00
|
|
|
|
2014-03-05 15:12:45 +01:00
|
|
|
def _package(self, request):
|
2014-03-06 18:23:07 +01:00
|
|
|
"""
|
|
|
|
Get the package name from the submit request XML.
|
|
|
|
:param request: request we check for
|
|
|
|
"""
|
2014-03-05 15:12:45 +01:00
|
|
|
f = http_GET(self.api.makeurl(['request', str(request)]))
|
|
|
|
root = ET.parse(f).getroot()
|
|
|
|
package = str(root.find('action').find('target').attrib['package'])
|
|
|
|
return package
|
|
|
|
|
2014-03-10 16:27:29 +01:00
|
|
|
def _supersede(self, request):
|
2014-03-05 15:12:45 +01:00
|
|
|
"""
|
|
|
|
Check if the request supersede a different request from a
|
|
|
|
staging project.
|
2014-03-10 16:27:29 +01:00
|
|
|
|
|
|
|
SRA supersede SRB when (1) SRA ID > SRB ID and (2) the changes
|
|
|
|
in SRB are in SRA. The second condition is difficult to
|
|
|
|
assure, but the way that we implement RequestFinder can
|
|
|
|
address some corner cases that make the first condition
|
|
|
|
enough.
|
|
|
|
|
2014-03-06 18:23:07 +01:00
|
|
|
:param request: request we check for
|
2014-03-05 15:12:45 +01:00
|
|
|
"""
|
|
|
|
package = self._package(request)
|
|
|
|
|
2014-03-10 16:27:29 +01:00
|
|
|
candidates = [] # Store candidates to be supersede by 'request'
|
2022-02-18 17:23:02 +01:00
|
|
|
url = self.api.makeurl(['staging', self.api.project, 'staging_projects'], {'requests': 1})
|
2019-11-06 14:29:02 +01:00
|
|
|
status = ET.parse(self.api.retried_GET(url)).getroot()
|
|
|
|
for prj in status.findall('staging_project'):
|
|
|
|
for req in prj.findall('./staged_requests/request'):
|
|
|
|
if int(req.get('id')) < int(request) and req.get('package') == package:
|
|
|
|
candidates.append((req.get('id'), package, prj.get('name')))
|
|
|
|
|
2022-02-18 17:44:32 +01:00
|
|
|
assert len(candidates) <= 1, 'There are more than one candidate to supersede {} ({}): {}'.format(
|
|
|
|
request, package, candidates)
|
2014-03-10 16:27:29 +01:00
|
|
|
|
|
|
|
return candidates[0] if candidates else None
|
2014-03-05 15:12:45 +01:00
|
|
|
|
2022-02-14 13:45:26 +01:00
|
|
|
def select_request(self, request, move, filter_from, remove_exclusion=False):
|
2019-11-19 21:24:58 +01:00
|
|
|
supersede = False
|
2014-03-05 15:12:45 +01:00
|
|
|
|
2014-08-14 17:28:35 +02:00
|
|
|
staged_requests = {
|
2019-11-25 17:09:39 +01:00
|
|
|
int(self.api.packages_staged[package]['rq_id']): package for package in self.api.packages_staged
|
2014-08-14 17:28:35 +02:00
|
|
|
}
|
2019-11-25 17:09:39 +01:00
|
|
|
if request in staged_requests:
|
2019-11-27 11:08:06 +01:00
|
|
|
supersede = self._supersede(request)
|
2014-08-14 17:28:35 +02:00
|
|
|
|
|
|
|
if request not in staged_requests and not supersede:
|
2014-03-04 09:39:14 +01:00
|
|
|
# Normal 'select' command
|
2014-05-20 15:08:21 +02:00
|
|
|
print('Adding request "{}" to project "{}"'.format(request, self.target_project))
|
2014-05-20 12:26:29 +02:00
|
|
|
|
2022-02-14 13:45:26 +01:00
|
|
|
return self.api.rq_to_prj(request, self.target_project, remove_exclusion)
|
2014-08-14 17:28:35 +02:00
|
|
|
elif request in staged_requests and (move or supersede):
|
2014-03-04 09:39:14 +01:00
|
|
|
# 'select' command becomes a 'move'
|
2018-10-18 17:14:17 -05:00
|
|
|
# supersede = (new_rq, package, project)
|
|
|
|
fprj = self.api.packages_staged[staged_requests[request]]['prj'] if not supersede else supersede[2]
|
2018-10-29 16:00:09 -05:00
|
|
|
if filter_from and filter_from != fprj:
|
2018-10-18 17:14:17 -05:00
|
|
|
print('Ignoring "{}" in "{}" since not in "{}"'.format(request, fprj, filter_from))
|
|
|
|
return True
|
2014-03-06 15:59:34 +01:00
|
|
|
|
2014-03-05 15:12:45 +01:00
|
|
|
if supersede:
|
2014-05-20 17:05:00 +02:00
|
|
|
print('"{} ({}) is superseded by {}'.format(request, supersede[1], supersede[0]))
|
2014-03-06 15:59:34 +01:00
|
|
|
|
2014-03-06 18:23:07 +01:00
|
|
|
if fprj == self.target_project:
|
|
|
|
print('"{}" is currently in "{}"'.format(request, self.target_project))
|
2014-03-06 15:59:34 +01:00
|
|
|
return False
|
|
|
|
|
2014-05-20 17:05:00 +02:00
|
|
|
print('Moving "{}" from "{}" to "{}"'.format(request, fprj, self.target_project))
|
2014-05-20 12:26:29 +02:00
|
|
|
|
2014-06-04 16:54:21 +02:00
|
|
|
# Store the source project, we also need to write a comment there
|
|
|
|
self.affected_projects.add(fprj)
|
2014-05-20 12:26:29 +02:00
|
|
|
|
2014-03-06 18:23:07 +01:00
|
|
|
return self.api.move_between_project(fprj, request, self.target_project)
|
2014-08-14 17:28:35 +02:00
|
|
|
elif request in staged_requests and not move:
|
2014-03-04 09:39:14 +01:00
|
|
|
# Previously selected, but not explicit move
|
2014-09-09 13:48:27 +02:00
|
|
|
fprj = self.api.packages_staged[staged_requests[request]]['prj']
|
2014-03-05 17:20:29 +01:00
|
|
|
msg = 'Request {} is already tracked in "{}".'
|
2014-09-09 13:48:27 +02:00
|
|
|
msg = msg.format(request, fprj)
|
2014-09-10 17:32:00 +02:00
|
|
|
if fprj != self.target_project:
|
2014-03-05 17:20:29 +01:00
|
|
|
msg += '\nUse --move modifier to move the request from "{}" to "{}"'
|
2014-09-09 13:48:27 +02:00
|
|
|
msg = msg.format(fprj, self.target_project)
|
2014-03-04 09:39:14 +01:00
|
|
|
print(msg)
|
2014-03-05 17:20:29 +01:00
|
|
|
return True
|
2016-05-11 14:32:42 +02:00
|
|
|
elif supersede:
|
|
|
|
print('"{} ({}) supersedes {}'.format(request, supersede[1], supersede[0]))
|
2014-03-04 09:39:14 +01:00
|
|
|
else:
|
|
|
|
raise oscerr.WrongArgs('Arguments for select are not correct.')
|
|
|
|
|
2015-07-16 19:35:22 +02:00
|
|
|
def perform(self, requests, move=False,
|
2022-02-14 13:45:26 +01:00
|
|
|
filter_from=None, no_freeze=False, remove_exclusion=False):
|
2014-03-06 18:23:07 +01:00
|
|
|
"""
|
|
|
|
Select package and move it accordingly by arguments
|
|
|
|
:param target_project: project we want to target
|
|
|
|
:param requests: requests we are working with
|
|
|
|
:param move: wether to move the requests or not
|
2018-10-18 17:14:17 -05:00
|
|
|
:param filter_from: filter request list to only those from a specific staging
|
2014-03-06 18:23:07 +01:00
|
|
|
"""
|
2014-03-07 14:49:33 +01:00
|
|
|
|
2015-07-18 14:12:58 +02:00
|
|
|
if self.api.is_adi_project(self.target_project):
|
|
|
|
no_freeze = True
|
|
|
|
|
2014-03-06 18:23:07 +01:00
|
|
|
# If the project is not frozen enough yet freeze it
|
2015-07-16 19:35:22 +02:00
|
|
|
if not (no_freeze or self.api.prj_frozen_enough(self.target_project)):
|
2019-04-12 13:43:38 +02:00
|
|
|
print('Project needs to be frozen or there was no change for last %d days.' % MAX_FROZEN_AGE)
|
|
|
|
print('Please freeze the project or use an option to ignore the time from the last freee.')
|
2014-06-17 13:57:19 +02:00
|
|
|
return False
|
2014-03-04 09:39:14 +01:00
|
|
|
|
2016-07-18 17:43:02 +08:00
|
|
|
# picks new candidate requests only if it's not to move requests
|
|
|
|
# ie. the review state of staging-project must be new if newcand is True
|
|
|
|
newcand = not move
|
|
|
|
|
2022-02-15 14:34:47 +01:00
|
|
|
requests = RequestFinder.find_sr(requests, self.api, newcand, consider_stagings=move)
|
2016-12-06 16:40:05 -06:00
|
|
|
requests_count = len(requests)
|
|
|
|
for index, request in enumerate(requests, start=1):
|
|
|
|
print('({}/{}) '.format(index, requests_count), end='')
|
2022-02-14 13:45:26 +01:00
|
|
|
if not self.select_request(request, move, filter_from, remove_exclusion=remove_exclusion):
|
2014-03-04 15:00:25 +01:00
|
|
|
return False
|
|
|
|
|
2014-06-04 16:54:21 +02:00
|
|
|
# Notify everybody about the changes
|
2017-03-28 22:33:35 -05:00
|
|
|
self.api.update_status_or_deactivate(self.target_project, 'select')
|
2014-06-04 16:54:21 +02:00
|
|
|
for fprj in self.affected_projects:
|
2017-03-28 22:33:35 -05:00
|
|
|
self.api.update_status_or_deactivate(fprj, 'select')
|
2014-03-07 14:49:33 +01:00
|
|
|
|
2014-03-10 11:22:36 +01:00
|
|
|
return True
|