Introduce --remove-exclusion for staging select

The API errors with that option if a request is ignored, so we have to
support it.

Fixes #2374
This commit is contained in:
Stephan Kulow 2022-02-14 13:45:26 +01:00
parent 00fbc99195
commit cf2c496116
4 changed files with 43 additions and 21 deletions

View File

@ -118,6 +118,7 @@ def clean_args(args):
@cmdln.option('--try-strategies', action='store_true', default=False, help='apply strategies and keep any with desireable outcome')
@cmdln.option('--strategy', help='apply a specific strategy')
@cmdln.option('--no-color', action='store_true', help='strip colors from output (or add staging.color = 0 to the .oscrc general section')
@cmdln.option('--remove-exclusion', action='store_true', help='unignore selected requests automatically', default=False)
@cmdln.option('--save', action='store_true', help='save the result to the pseudometa package')
def do_staging(self, subcmd, opts, *args):
"""${cmd_name}: Commands to work with staging projects
@ -266,6 +267,9 @@ def do_staging(self, subcmd, opts, *args):
select --move --filter-from A B $(< package.list)
select --remove-exclusion will unignore the requests selected (ignored requests
are called excluded in the OBS API)
"unselect" will remove from the project - pushing them back to the backlog
If a message is included the requests will be ignored first.
@ -304,7 +308,7 @@ def do_staging(self, subcmd, opts, *args):
osc staging unignore [--cleanup] [REQUEST...|all]
osc staging list [--supersede]
osc staging lock [-m MESSAGE]
osc staging select [--no-freeze] [--move [--filter-from STAGING]]
osc staging select [--no-freeze] [--remove-exclusion] [--move [--filter-from STAGING]]
STAGING REQUEST...
osc staging select [--no-freeze] [--interactive|--non-interactive]
[--filter-by...] [--group-by...]
@ -559,13 +563,13 @@ def do_staging(self, subcmd, opts, *args):
# api.set_splitter_info_in_prj_pseudometa(target_project, info['group'], info['strategy'])
SelectCommand(api, target_project) \
.perform(request_ids, no_freeze=opts.no_freeze)
.perform(request_ids, no_freeze=opts.no_freeze, remove_exclusion=opts.remove_exclusion)
else:
target_project = api.prj_from_short(stagings[0])
filter_from = api.prj_from_short(opts.filter_from) if opts.filter_from else None
SelectCommand(api, target_project) \
.perform(requests, opts.move,
filter_from, opts.no_freeze)
filter_from, no_freeze=opts.no_freeze, remove_exclusion=opts.remove_exclusion)
elif cmd == 'cleanup_rings':
CleanupRings(api).perform()
elif cmd == 'ignore':

View File

@ -55,7 +55,7 @@ class SelectCommand(object):
return candidates[0] if candidates else None
def select_request(self, request, move, filter_from):
def select_request(self, request, move, filter_from, remove_exclusion=False):
supersede = False
staged_requests = {
@ -68,7 +68,7 @@ class SelectCommand(object):
# Normal 'select' command
print('Adding request "{}" to project "{}"'.format(request, self.target_project))
return self.api.rq_to_prj(request, self.target_project)
return self.api.rq_to_prj(request, self.target_project, remove_exclusion)
elif request in staged_requests and (move or supersede):
# 'select' command becomes a 'move'
# supersede = (new_rq, package, project)
@ -106,7 +106,7 @@ class SelectCommand(object):
raise oscerr.WrongArgs('Arguments for select are not correct.')
def perform(self, requests, move=False,
filter_from=None, no_freeze=False):
filter_from=None, no_freeze=False, remove_exclusion=False):
"""
Select package and move it accordingly by arguments
:param target_project: project we want to target
@ -132,7 +132,7 @@ class SelectCommand(object):
requests_count = len(requests)
for index, request in enumerate(requests, start=1):
print('({}/{}) '.format(index, requests_count), end='')
if not self.select_request(request, move, filter_from):
if not self.select_request(request, move, filter_from, remove_exclusion=remove_exclusion):
return False
# Notify everybody about the changes

View File

@ -895,7 +895,7 @@ class StagingAPI(object):
return (time.time() - float(entry.get('mtime'))) / 3600 / 24
return 100000 # quite some!
def rq_to_prj(self, request_id, project):
def rq_to_prj(self, request_id, project, remove_exclusion=False):
"""
Links request to project - delete or submit
:param request_id: request to link
@ -923,7 +923,10 @@ class StagingAPI(object):
raise oscerr.WrongArgs(msg)
requestxml = f"<requests><request id='{request_id}'/></requests>"
u = makeurl(self.apiurl, ['staging', self.project, 'staging_projects', project, 'staged_requests'])
opts = {}
if remove_exclusion:
opts['remove_exclusion'] = 1
u = makeurl(self.apiurl, ['staging', self.project, 'staging_projects', project, 'staged_requests'], opts)
f = http_POST(u, data=requestxml)
if act_type == 'delete':

View File

@ -1,22 +1,13 @@
import unittest
import os.path
from osc import oscerr
import osc.conf
from osc.core import http_GET, http_POST, makeurl
from lxml import etree as ET
from osclib.cache import Cache
from osclib.cache_manager import CacheManager
from osclib.comments import CommentAPI
from osclib.conf import Config
from osclib.core import package_list
from osclib.select_command import SelectCommand
from osclib.unselect_command import UnselectCommand
from osclib.supersede_command import SupersedeCommand
from osclib.stagingapi import StagingAPI
from osclib.memoize import memoize_session_reset
from osclib.ignore_command import IgnoreCommand
from osclib.core import source_file_load
import logging
from urllib.error import HTTPError
from lxml import etree as ET
from mock import MagicMock
from . import OBSLocal
@ -136,3 +127,27 @@ class TestSelect(OBSLocal.TestCase):
# TODO: record which URLs were called so we can verify them
# but we wont' be able to test the actual wipe unless we really build something
# which is too expensive
def test_select_excluded_package(self):
self.wf.setup_rings()
staging = self.wf.create_staging('A', freeze=True, with_repo=True)
self.wf.create_submit_request('devel:wine', 'wine')
IgnoreCommand(self.wf.api).perform(['wine'])
with self.assertRaises(HTTPError) as context:
SelectCommand(self.wf.api, staging.name).perform(['wine'])
root = ET.fromstring(context.exception.fp.read())
self.assertRegex(root.find('summary').text, r'Use --remove-exclusion')
def test_excluded_package(self):
self.wf.setup_rings()
staging = self.wf.create_staging('A', freeze=True, with_repo=True)
self.wf.create_submit_request('devel:wine', 'wine')
IgnoreCommand(self.wf.api).perform(['wine'])
ret = SelectCommand(self.wf.api, staging.name).perform(['wine'], remove_exclusion=True)
self.assertEqual(True, ret)
self.assertEqual(0, len(self.wf.api.get_ignored_requests()))