From 29b8bcca6be5658c7f90942d88e632b9d3ecaead Mon Sep 17 00:00:00 2001 From: Alberto Planas Date: Thu, 7 Aug 2014 12:39:41 +0200 Subject: [PATCH] Makes staging pluging Factory agnostic. --- osc-check_repo.py | 4 +- osc-staging.py | 18 +++++---- osclib/accept_command.py | 7 ++-- osclib/cleanup_rings.py | 76 +++++++++++++++++++------------------- osclib/cycle.py | 17 +++++---- osclib/freeze_command.py | 69 +++++++++++++++++----------------- osclib/list_command.py | 5 +-- osclib/request_finder.py | 59 ++++++++++++++--------------- osclib/select_command.py | 3 +- osclib/stagingapi.py | 18 +++++---- osclib/unselect_command.py | 4 -- tests/freeze_tests.py | 12 +++++- 12 files changed, 151 insertions(+), 141 deletions(-) diff --git a/osc-check_repo.py b/osc-check_repo.py index acb6e584..86d3c3b6 100644 --- a/osc-check_repo.py +++ b/osc-check_repo.py @@ -35,6 +35,7 @@ sys.path.append(_plugin_dir) from osclib.checkrepo import CheckRepo from osclib.cycle import CycleDetector from osclib.memoize import CACHEDIR +from osclib.stagingapi import StagingAPI def _check_repo_download(self, request, opts): @@ -148,7 +149,8 @@ def _check_repo_group(self, id_, requests, opts): # Detect cycles into the current Factory graph after we update the # links with the current list of request. - cycle_detector = CycleDetector(opts.apiurl) + api = StagingAPI(opts.apiurl) + cycle_detector = CycleDetector(api) for (cycle, new_edges) in cycle_detector.cycles(requests=packs): print print ' - New cycle detected:', sorted(cycle) diff --git a/osc-staging.py b/osc-staging.py index 39cefbd2..deec7197 100644 --- a/osc-staging.py +++ b/osc-staging.py @@ -17,14 +17,14 @@ from osc import cmdln, oscerr _plugin_dir = os.path.expanduser('~/.osc-plugins') sys.path.append(_plugin_dir) -from osclib.stagingapi import StagingAPI -from osclib.select_command import SelectCommand -from osclib.unselect_command import UnselectCommand from osclib.accept_command import AcceptCommand -from osclib.cleanup_rings import CleanupRings -from osclib.list_command import ListCommand -from osclib.freeze_command import FreezeCommand from osclib.check_command import CheckCommand +from osclib.cleanup_rings import CleanupRings +from osclib.freeze_command import FreezeCommand +from osclib.list_command import ListCommand +from osclib.select_command import SelectCommand +from osclib.stagingapi import StagingAPI +from osclib.unselect_command import UnselectCommand OSC_STAGING_VERSION = '0.0.1' @@ -39,6 +39,8 @@ def _print_version(self): help='force the selection to become a move') @cmdln.option('-f', '--from', dest='from_', metavar='FROMPROJECT', help='manually specify different source project during request moving') +@cmdln.option('-p', '--project', dest='project', metavar='PROJECT', default='Factory', + help='select a different project instead of openSUSE:Factory') @cmdln.option('--add', dest='add', metavar='PACKAGE', help='mark additional packages to be checked by repo checker') @cmdln.option('-o', '--old', action='store_true', @@ -103,7 +105,7 @@ def do_staging(self, subcmd, opts, *args): # init the obs access opts.apiurl = self.get_api_url() opts.verbose = False - api = StagingAPI(opts.apiurl) + api = StagingAPI(opts.apiurl, opts.project) # call the respective command and parse args by need if cmd == 'check': @@ -128,6 +130,6 @@ def do_staging(self, subcmd, opts, *args): else: SelectCommand(api).perform(tprj, args[2:], opts.move, opts.from_) elif cmd == 'cleanup_rings': - CleanupRings(opts.apiurl).perform() + CleanupRings(opts.api).perform() elif cmd == 'list': ListCommand(api).perform() diff --git a/osclib/accept_command.py b/osclib/accept_command.py index f812c57e..e6a46a72 100644 --- a/osclib/accept_command.py +++ b/osclib/accept_command.py @@ -67,15 +67,16 @@ class AcceptCommand(object): def accept_other_new(self): changed = False - for req in self.find_new_requests('openSUSE:Factory'): + for req in self.find_new_requests('openSUSE:{}'.format(self.api.opensuse)): change_request_state(self.api.apiurl, str(req), 'accepted', message='Accept to factory') changed = True return changed def update_factory_version(self): - """Update Factory version if is necessary.""" - url = self.api.makeurl(['source', 'openSUSE:Factory', '_product', 'openSUSE.product']) + """Update openSUSE (Factory, 13.2, ...) version if is necessary.""" + project = 'openSUSE:{}'.format(self.api.opensuse) + url = self.api.makeurl(['source', project, '_product', 'openSUSE.product']) product = http_GET(url).read() curr_version = date.today().strftime('%Y%m%d') diff --git a/osclib/cleanup_rings.py b/osclib/cleanup_rings.py index 75ec5b01..f97e8a95 100644 --- a/osclib/cleanup_rings.py +++ b/osclib/cleanup_rings.py @@ -5,31 +5,37 @@ from osc.core import http_GET class CleanupRings(object): - def __init__(self, apiurl): - self.bin2src = dict() - self.pkgdeps = dict() - self.sources = list() - self.apiurl = apiurl - self.links = dict() + def __init__(self, api): + self.bin2src = {} + self.pkgdeps = {} + self.sources = [] + self.api = api + self.links = {} def perform(self): - self.check_depinfo_ring('openSUSE:Factory:Rings:0-Bootstrap', 'openSUSE:Factory:Rings:1-MinimalX') - self.check_depinfo_ring('openSUSE:Factory:Rings:1-MinimalX', 'openSUSE:Factory:Rings:2-TestDVD') - self.check_depinfo_ring('openSUSE:Factory:Rings:2-TestDVD', None) + self.check_depinfo_ring('openSUSE:{}:Rings:0-Bootstrap'.format(self.api.opensuse), + 'openSUSE:{}:Rings:1-MinimalX'.format(self.api.opensuse)) + self.check_depinfo_ring('openSUSE:{}:Rings:1-MinimalX'.format(self.api.opensuse), + 'openSUSE:{}:Rings:2-TestDVD'.format(self.api.opensuse)) + self.check_depinfo_ring('openSUSE:{}:Rings:2-TestDVD'.format(self.api.opensuse), None) def find_inner_ring_links(self, prj): - url = makeurl(self.apiurl, ['source', prj], { 'view': 'info', 'nofilename': '1' }) + query = { + 'view': 'info', + 'nofilename': '1' + } + url = makeurl(self.api.apiurl, ['source', prj], query=query) f = http_GET(url) root = ET.parse(f).getroot() for si in root.findall('sourceinfo'): linked = si.find('linked') - if not linked is None and linked.get('project') != 'openSUSE:Factory': - if not linked.get('project').startswith('openSUSE:Factory:Rings:'): + if linked is not None and linked.get('project') != 'openSUSE:{}'.format(self.api.opensuse): + if not linked.get('project').startswith('openSUSE:{}:Rings:'.format(self.api.opensuse)): print(ET.tostring(si)) self.links[linked.get('package')] = si.get('package') def fill_pkgdeps(self, prj, repo, arch): - url = makeurl(self.apiurl, ['build', prj, repo, arch, '_builddepinfo']) + url = makeurl(self.api.apiurl, ['build', prj, repo, arch, '_builddepinfo']) f = http_GET(url) root = ET.parse(f).getroot() @@ -41,14 +47,14 @@ class CleanupRings(object): for subpkg in package.findall('subpkg'): subpkg = subpkg.text - if self.bin2src.has_key(subpkg): + if subpkg in self.bin2src: print('Binary {} is defined twice: {}/{}'.format(subpkg, prj, source)) self.bin2src[subpkg] = source for package in root.findall('package'): source = package.find('source').text for pkg in package.findall('pkgdep'): - if not self.bin2src.has_key(pkg.text): + if pkg.text not in self.bin2src: if pkg.text.startswith('texlive-'): for letter in range(ord('a'), ord('z') + 1): self.pkgdeps['texlive-specs-' + chr(letter)] = 'texlive-specs-' + chr(letter) @@ -59,64 +65,58 @@ class CleanupRings(object): self.pkgdeps[b] = source def check_depinfo_ring(self, prj, nextprj): - url = makeurl(self.apiurl, ['build', prj, '_result'] ) + url = makeurl(self.api.apiurl, ['build', prj, '_result']) root = ET.parse(http_GET(url)).getroot() for repo in root.findall('result'): repostate = repo.get('state', 'missing') - if not repostate in ['unpublished', 'published']: + if repostate not in ['unpublished', 'published']: print('Repo {}/{} is in state {}'.format(repo.get('project'), repo.get('repository'), repostate)) return False for package in repo.findall('status'): code = package.get('code') - if not code in ['succeeded', 'excluded', 'disabled']: + if code not in ['succeeded', 'excluded', 'disabled']: print('Package {}/{}/{} is {}'.format(repo.get('project'), repo.get('repository'), package.get('package'), code)) return False self.find_inner_ring_links(prj) self.fill_pkgdeps(prj, 'standard', 'x86_64') - if prj == 'openSUSE:Factory:Rings:1-MinimalX': - url = makeurl(self.apiurl, ['build', prj, 'images', 'x86_64', 'Test-DVD-x86_64', '_buildinfo'] ) + if prj == 'openSUSE:{}:Rings:1-MinimalX': + url = makeurl(self.api.apiurl, ['build', prj, 'images', 'x86_64', 'Test-DVD-x86_64', '_buildinfo']) root = ET.parse(http_GET(url)).getroot() for bdep in root.findall('bdep'): - if not bdep.attrib.has_key('name'): + if 'name' not in bdep.attrib: continue b = bdep.attrib['name'] - if not self.bin2src.has_key(b): + if b not in self.bin2src: continue b = self.bin2src[b] self.pkgdeps[b] = 'MYdvd' - if prj == 'openSUSE:Factory:Rings:2-TestDVD': - url = makeurl(self.apiurl, ['build', prj, 'images', 'x86_64', 'Test-DVD-x86_64', '_buildinfo'] ) + if prj == 'openSUSE:{}:Rings:2-TestDVD'.format(self.api.opensuse): + url = makeurl(self.api.apiurl, ['build', prj, 'images', 'x86_64', 'Test-DVD-x86_64', '_buildinfo']) root = ET.parse(http_GET(url)).getroot() for bdep in root.findall('bdep'): - if not bdep.attrib.has_key('name'): + if 'name' not in bdep.attrib: continue b = bdep.attrib['name'] - if not self.bin2src.has_key(b): + if b not in self.bin2src: continue b = self.bin2src[b] self.pkgdeps[b] = 'MYdvd2' - # if ($prj eq 'openSUSE:Factory:MainDesktops') { - # $dinfo->{MYcds} = {}; - # $dinfo->{MYcds}->{pkgdep} = (); - # $dinfo->{MYcds}->{source} = 'MYcds'; - # push(@{$dinfo->{MYcds}->{pkgdep}}, 'kiwi-image-livecd-gnome'); - # push(@{$dinfo->{MYcds}->{pkgdep}}, 'kiwi-image-livecd-kde'); - - if prj == 'openSUSE:Factory:Rings:0-Bootstrap': - url = makeurl(self.apiurl, ['build', prj, 'standard', '_buildconfig'] ) + if prj == 'openSUSE:{}:Rings:0-Bootstrap'.format(self.api.opensuse): + url = makeurl(self.api.apiurl, ['build', prj, 'standard', '_buildconfig']) for line in http_GET(url).read().split('\n'): if line.startswith('Preinstall:') or line.startswith('Support:'): for prein in line.split(':')[1].split(): - if not self.bin2src.has_key(prein): continue + if prein not in self.bin2src: + continue b = self.bin2src[prein] self.pkgdeps[b] = 'MYinstall' for source in self.sources: - if not self.pkgdeps.has_key(source) and not self.links.has_key(source): + if source not in self.pkgdeps and source not in self.links: print('osc rdelete -m cleanup {} {}'.format(prj, source)) if nextprj: - print('osc linkpac openSUSE:Factory {} {}').format(source, nextprj) + print('osc linkpac openSUSE:{} {} {}').format(self.api.opensuse, source, nextprj) diff --git a/osclib/cycle.py b/osclib/cycle.py index 40c90b66..10ab29ca 100644 --- a/osclib/cycle.py +++ b/osclib/cycle.py @@ -144,10 +144,10 @@ class Package(object): class CycleDetector(object): - """Class to detect cycles in Factory.""" + """Class to detect cycles in Factory / 13.2.""" - def __init__(self, apiurl): - self.apiurl = apiurl + def __init__(self, api): + self.api = api # Store packages prevoiusly ignored. Don't pollute the screen. self._ignore_packages = set() @@ -156,7 +156,7 @@ class CycleDetector(object): root = None try: # print('Generating _builddepinfo for (%s, %s, %s)' % (project, repository, arch)) - url = makeurl(self.apiurl, ['/build/%s/%s/%s/_builddepinfo' % (project, repository, arch)]) + url = makeurl(self.api.apiurl, ['/build/%s/%s/%s/_builddepinfo' % (project, repository, arch)]) root = http_GET(url).read() except urllib2.HTTPError, e: print('ERROR in URL %s [%s]' % (url, e)) @@ -174,8 +174,8 @@ class CycleDetector(object): _IGNORE_PREFIX = ('texlive-', 'master-boot-code') - # Note, by default generate the graph for all Factory. If you only - # need the base packages you can use: + # Note, by default generate the graph for all Factory / + # 13/2. If you only need the base packages you can use: # project = 'Base:System' # repository = 'openSUSE_Factory' @@ -228,9 +228,12 @@ class CycleDetector(object): return frozenset(frozenset(e.text for e in cycle.findall('package')) for cycle in root.findall('cycle')) - def cycles(self, requests, project='openSUSE:Factory', repository='standard', arch='x86_64'): + def cycles(self, requests, project=None, repository='standard', arch='x86_64'): """Detect cycles in a specific repository.""" + if not project: + project = 'openSUSE:{}'.format(self.api.opensuse) + # filter submit requests requests = [rq for rq in requests if rq.action_type == 'submit'] diff --git a/osclib/freeze_command.py b/osclib/freeze_command.py index ccb855ca..0c1ac652 100644 --- a/osclib/freeze_command.py +++ b/osclib/freeze_command.py @@ -1,6 +1,7 @@ import time from xml.etree import cElementTree as ET + class FreezeCommand(object): def __init__(self, api): @@ -32,13 +33,14 @@ class FreezeCommand(object): self.create_bootstrap_aggregate_file() def bootstrap_packages(self): - url = self.api.makeurl(['source', 'openSUSE:Factory:Rings:0-Bootstrap']) + url = self.api.makeurl(['source', 'openSUSE:{}:Rings:0-Bootstrap'.format(self.api.opensuse)]) f = self.api.retried_GET(url) root = ET.parse(f).getroot() l = list() for e in root.findall('entry'): name = e.get('name') - if name in ['rpmlint-mini-AGGR']: continue + if name in ['rpmlint-mini-AGGR']: + continue l.append(name) l.sort() return l @@ -47,27 +49,28 @@ class FreezeCommand(object): url = self.api.makeurl(['source', self.prj, 'bootstrap-copy', '_aggregate']) root = ET.Element('aggregatelist') - a = ET.SubElement(root, 'aggregate', { 'project': "openSUSE:Factory:Rings:0-Bootstrap" } ) + a = ET.SubElement(root, 'aggregate', + {'project': 'openSUSE:{}:Rings:0-Bootstrap'.format(self.api.opensuse)}) for package in self.bootstrap_packages(): p = ET.SubElement(a, 'package') p.text = package - ET.SubElement(a, 'repository', { 'target': 'bootstrap_copy', 'source': 'standard' } ) - ET.SubElement(a, 'repository', { 'target': 'standard', 'source': 'nothing' } ) - ET.SubElement(a, 'repository', { 'target': 'images', 'source': 'nothing' } ) + ET.SubElement(a, 'repository', {'target': 'bootstrap_copy', 'source': 'standard'}) + ET.SubElement(a, 'repository', {'target': 'standard', 'source': 'nothing'}) + ET.SubElement(a, 'repository', {'target': 'images', 'source': 'nothing'}) self.api.retried_PUT(url, ET.tostring(root)) def create_bootstrap_aggregate_meta(self): url = self.api.makeurl(['source', self.prj, 'bootstrap-copy', '_meta']) - root = ET.Element('package', { 'project': self.prj, 'name': 'bootstrap-copy' }) + root = ET.Element('package', {'project': self.prj, 'name': 'bootstrap-copy'}) ET.SubElement(root, 'title') ET.SubElement(root, 'description') f = ET.SubElement(root, 'build') # this one is to toggle - ET.SubElement(f, 'disable', { 'repository': 'bootstrap_copy' }) + ET.SubElement(f, 'disable', {'repository': 'bootstrap_copy'}) # this one is the global toggle ET.SubElement(f, 'disable') @@ -84,7 +87,7 @@ class FreezeCommand(object): self.api.retried_PUT(url, ET.tostring(pkgmeta)) def verify_bootstrap_copy_codes(self, codes): - url = self.api.makeurl(['build', self.prj, '_result'], { 'package': 'bootstrap-copy' }) + url = self.api.makeurl(['build', self.prj, '_result'], {'package': 'bootstrap-copy'}) root = ET.parse(self.api.retried_GET(url)).getroot() for result in root.findall('result'): @@ -111,21 +114,21 @@ class FreezeCommand(object): self.build_switch_bootstrap_copy('disable') # now try to freeze sub project - much easier - if self.api.project_exists(prj + ":DVD"): - self.prj = prj + ":DVD" - self.set_links() - self.freeze_prjlinks() + if self.api.project_exists(prj + ':DVD'): + self.prj = prj + ':DVD' + self.set_links() + self.freeze_prjlinks() def prj_meta_for_bootstrap_copy(self, prj): - root = ET.Element('project', { 'name': prj }) + root = ET.Element('project', {'name': prj}) ET.SubElement(root, 'title') ET.SubElement(root, 'description') - links = self.projectlinks or ['openSUSE:Factory:Rings:1-MinimalX'] + links = self.projectlinks or ['openSUSE:{}:Rings:1-MinimalX'.format(self.api.opensuse)] for lprj in links: - ET.SubElement(root, 'link', { 'project': lprj }) + ET.SubElement(root, 'link', {'project': lprj}) f = ET.SubElement(root, 'build') # this one stays - ET.SubElement(f, 'disable', { 'repository': 'bootstrap_copy' }) + ET.SubElement(f, 'disable', {'repository': 'bootstrap_copy'}) # this one is the global toggle ET.SubElement(f, 'disable') f = ET.SubElement(root, 'publish') @@ -133,22 +136,22 @@ class FreezeCommand(object): f = ET.SubElement(root, 'debuginfo') ET.SubElement(f, 'enable') - r = ET.SubElement(root, 'repository', { 'name': 'bootstrap_copy' }) - ET.SubElement(r, 'path', { 'project': 'openSUSE:Factory', 'repository': 'ports' }) + r = ET.SubElement(root, 'repository', {'name': 'bootstrap_copy'}) + ET.SubElement(r, 'path', {'project': 'openSUSE:{}'.format(self.api.opensuse), 'repository': 'ports'}) a = ET.SubElement(r, 'arch') a.text = 'i586' a = ET.SubElement(r, 'arch') a.text = 'x86_64' - r = ET.SubElement(root, 'repository', { 'name': 'standard', 'linkedbuild': 'all', 'rebuild': 'direct' }) - ET.SubElement(r, 'path', { 'project': prj, 'repository': 'bootstrap_copy' }) + r = ET.SubElement(root, 'repository', {'name': 'standard', 'linkedbuild': 'all', 'rebuild': 'direct'}) + ET.SubElement(r, 'path', {'project': prj, 'repository': 'bootstrap_copy'}) a = ET.SubElement(r, 'arch') a.text = 'i586' a = ET.SubElement(r, 'arch') a.text = 'x86_64' - r = ET.SubElement(root, 'repository', { 'name': 'images', 'linkedbuild': 'all', 'rebuild': 'direct' }) - ET.SubElement(r, 'path', { 'project': prj, 'repository': 'standard' }) + r = ET.SubElement(root, 'repository', {'name': 'images', 'linkedbuild': 'all', 'rebuild': 'direct'}) + ET.SubElement(r, 'path', {'project': prj, 'repository': 'standard'}) a = ET.SubElement(r, 'arch') a.text = 'x86_64' @@ -159,14 +162,14 @@ class FreezeCommand(object): flink = ET.Element('frozenlinks') for lprj in self.projectlinks: - fl = ET.SubElement(flink, 'frozenlink', { 'project': lprj } ) + fl = ET.SubElement(flink, 'frozenlink', {'project': lprj}) sources = self.receive_sources(lprj, sources, fl) - url = self.api.makeurl(['source', self.prj, '_project', '_frozenlinks'], { 'meta': '1' } ) + url = self.api.makeurl(['source', self.prj, '_project', '_frozenlinks'], {'meta': '1'}) self.api.retried_PUT(url, ET.tostring(flink)) def receive_sources(self, prj, sources, flink): - url = self.api.makeurl(['source', prj], { 'view': 'info', 'nofilename': '1' } ) + url = self.api.makeurl(['source', prj], {'view': 'info', 'nofilename': '1'}) f = self.api.retried_GET(url) root = ET.parse(f).getroot() @@ -183,15 +186,15 @@ class FreezeCommand(object): # won't get updated kernel-default (and many other cases) for linked in si.findall('linked'): if linked.get('project') in self.projectlinks: - # take the unexpanded md5 from Factory link - url = self.api.makeurl(['source', 'openSUSE:Factory', package], { 'view': 'info', 'nofilename': '1' }) - #print(package, linked.get('package'), linked.get('project')) + # take the unexpanded md5 from Factory / 13.2 link + url = self.api.makeurl(['source', 'openSUSE:{}'.format(self.api.opensuse), package], + {'view': 'info', 'nofilename': '1'}) + # print(package, linked.get('package'), linked.get('project')) f = self.api.retried_GET(url) proot = ET.parse(f).getroot() - ET.SubElement(flink, 'package', { 'name': package, 'srcmd5': proot.get('lsrcmd5'), 'vrev': si.get('vrev') }) + ET.SubElement(flink, 'package', {'name': package, 'srcmd5': proot.get('lsrcmd5'), 'vrev': si.get('vrev')}) return package if package in ['rpmlint-mini-AGGR']: - return package # we should not freeze aggregates - ET.SubElement(flink, 'package', { 'name': package, 'srcmd5': si.get('srcmd5'), 'vrev': si.get('vrev') }) + return package # we should not freeze aggregates + ET.SubElement(flink, 'package', {'name': package, 'srcmd5': si.get('srcmd5'), 'vrev': si.get('vrev')}) return package - diff --git a/osclib/list_command.py b/osclib/list_command.py index 3f1866f1..b384d8e4 100644 --- a/osclib/list_command.py +++ b/osclib/list_command.py @@ -1,7 +1,4 @@ -from xml.etree import cElementTree as ET - -from osc.core import makeurl -from osc.core import http_GET +from osc import oscerr class ListCommand: diff --git a/osclib/request_finder.py b/osclib/request_finder.py index 2fb82ba0..801ebc61 100644 --- a/osclib/request_finder.py +++ b/osclib/request_finder.py @@ -6,17 +6,13 @@ from osc.core import makeurl from osc.core import http_GET -FACTORY = 'openSUSE:Factory' -STG_PREFIX = 'openSUSE:Factory:Staging:' - - def _is_int(x): return isinstance(x, int) or x.isdigit() class RequestFinder(object): - def __init__(self, apiurl, stagingapi): + def __init__(self, api): """ Store the list of submit request together with the source project @@ -31,8 +27,7 @@ class RequestFinder(object): } } """ - self.apiurl = apiurl - self.stagingapi = stagingapi + self.api = api self.srs = {} def _filter_review_by_project(self, element, state): @@ -56,8 +51,8 @@ class RequestFinder(object): :param element: XML with list of reviews """ reviews = self._filter_review_by_project(element, 'new') - assert len(reviews) <= 1, 'Request "{}" have multiple review by project in new state "{}"'.format(request_id, - reviews) + msg = 'Request "{}" have multiple review by project in new state "{}"'.format(request_id, reviews) + assert len(reviews) <= 1, msg return reviews[0] if reviews else None def find_request_id(self, request_id): @@ -69,7 +64,7 @@ class RequestFinder(object): if not _is_int(request_id): return False - url = makeurl(self.apiurl, ['request', str(request_id)]) + url = makeurl(self.api.apiurl, ['request', str(request_id)]) try: f = http_GET(url) except urllib2.HTTPError: @@ -81,14 +76,14 @@ class RequestFinder(object): return None project = root.find('action').find('target').get('project') - if project != FACTORY and not project.startswith(STG_PREFIX): - msg = 'Request {} is not for openSUSE:Factory, but for {}' - msg = msg.format(request_id, project) + if (project != 'openSUSE:{}'.format(self.api.opensuse) and not project.startswith('openSUSE:{}:Staging:'.format(self.api.opensuse))): + msg = 'Request {} is not for openSUSE:{}, but for {}' + msg = msg.format(request_id, self.api.opensuse, project) raise oscerr.WrongArgs(msg) self.srs[int(request_id)] = {'project': project} review = self._new_review_by_project(request_id, root) - if review and review.startswith(STG_PREFIX): + if review and review.startswith('openSUSE:{}:Staging:'.format(self.api.opensuse)): self.srs[int(request_id)]['staging'] = review return True @@ -99,9 +94,9 @@ class RequestFinder(object): :param package: name of the package """ - query = 'states=new,review,declined&project=openSUSE:Factory&view=collection&package={}' - query = query.format(urllib2.quote(package)) - url = makeurl(self.apiurl, ['request'], query) + query = 'states=new,review,declined&project=openSUSE:{}&view=collection&package={}' + query = query.format(self.api.opensuse, urllib2.quote(package)) + url = makeurl(self.api.apiurl, ['request'], query) f = http_GET(url) root = ET.parse(f).getroot() @@ -116,10 +111,10 @@ class RequestFinder(object): request = int(sr.get('id')) state = sr.find('state').get('name') - self.srs[request] = {'project': 'openSUSE:Factory', 'state': state} + self.srs[request] = {'project': 'openSUSE:{}'.format(self.api.opensuse), 'state': state} review = self._new_review_by_project(request, sr) - if review and review.startswith(STG_PREFIX): + if review and review.startswith('openSUSE:{}:Staging:'.format(self.api.opensuse)): self.srs[int(request)]['staging'] = review if last_rq: @@ -145,8 +140,8 @@ class RequestFinder(object): :param source_project: name of the source project """ - query = 'states=new,review&project=openSUSE:Factory&view=collection' - url = makeurl(self.apiurl, ['request'], query) + query = 'states=new,review&project=openSUSE:{}&view=collection'.format(self.api.opensuse) + url = makeurl(self.api.apiurl, ['request'], query) f = http_GET(url) root = ET.parse(f).getroot() @@ -157,9 +152,9 @@ class RequestFinder(object): if src is not None and src.get('project') == source_project: request = int(sr.attrib['id']) state = sr.find('state').get('name') - self.srs[request] = {'project': 'openSUSE:Factory', 'state': state} + self.srs[request] = {'project': 'openSUSE:{}'.format(self.api.opensuse), 'state': state} review = self._new_review_by_project(request, sr) - if review and review.startswith(STG_PREFIX): + if review and review.startswith('openSUSE:{}:Staging:'.format(self.api.opensuse)): self.srs[int(request)]['staging'] = review ret = True @@ -193,13 +188,13 @@ class RequestFinder(object): for p in pkgs: found = False - for staging in self.stagingapi.get_staging_projects(): - if _is_int(p) and self.stagingapi.get_package_for_request_id(staging, p): + for staging in self.api.get_staging_projects(): + if _is_int(p) and self.api.get_package_for_request_id(staging, p): self.srs[int(p)] = {'staging': staging} found = True continue else: - rq = self.stagingapi.get_request_id_for_package(staging, p) + rq = self.api.get_request_id_for_package(staging, p) if rq: self.srs[rq] = {'staging': staging} found = True @@ -208,23 +203,23 @@ class RequestFinder(object): raise oscerr.WrongArgs('No SR# found for: {}'.format(p)) @classmethod - def find_sr(cls, pkgs, apiurl, stagingapi=None): + def find_sr(cls, pkgs, api): """ Search for all various mutations and return list of SR#s :param pkgs: mesh of argumets to search for - :param apiurl: OBS url + :param api: StagingAPI instance """ - finder = cls(apiurl, stagingapi) + finder = cls(api) finder.find(pkgs) return finder.srs @classmethod - def find_staged_sr(cls, pkgs, stagingapi): + def find_staged_sr(cls, pkgs, api): """ Search for all various mutations and return a single SR#s. :param pkgs: mesh of argumets to search for (SR#|package name) - :param stagingapi: StagingAPI instance + :param api: StagingAPI instance """ - finder = cls(stagingapi.apiurl, stagingapi) + finder = cls(api) finder.find_via_stagingapi(pkgs) return finder.srs diff --git a/osclib/select_command.py b/osclib/select_command.py index f99bee02..f3dbf9b9 100644 --- a/osclib/select_command.py +++ b/osclib/select_command.py @@ -1,4 +1,3 @@ -from collections import defaultdict from xml.etree import cElementTree as ET from osc import oscerr @@ -115,7 +114,7 @@ class SelectCommand(object): # FreezeCommand(self.api).perform(target_project) self.target_project = target_project - for request, request_project in RequestFinder.find_sr(requests, self.api.apiurl).items(): + for request, request_project in RequestFinder.find_sr(requests, self.api).items(): if not self.select_request(request, request_project, move, from_): return False diff --git a/osclib/stagingapi.py b/osclib/stagingapi.py index 72a155ee..f5f893f0 100644 --- a/osclib/stagingapi.py +++ b/osclib/stagingapi.py @@ -30,16 +30,17 @@ class StagingAPI(object): Class containing various api calls to work with staging projects. """ - def __init__(self, apiurl): + def __init__(self, apiurl, opensuse='Factory'): """ Initialize instance variables """ self.apiurl = apiurl + self.opensuse = opensuse self.rings = ( - 'openSUSE:Factory:Rings:0-Bootstrap', - 'openSUSE:Factory:Rings:1-MinimalX', - 'openSUSE:Factory:Rings:2-TestDVD' + 'openSUSE:{}:Rings:0-Bootstrap'.format(self.opensuse), + 'openSUSE:{}:Rings:1-MinimalX'.format(self.opensuse), + 'openSUSE:{}:Rings:2-TestDVD'.format(self.opensuse) ) self.ring_packages = self._generate_ring_packages() self.packages_staged = self._get_staged_requests() @@ -183,7 +184,7 @@ class StagingAPI(object): projects = [] - query = "id?match=starts-with(@name,'openSUSE:Factory:Staging:')" + query = "id?match=starts-with(@name,'openSUSE:{}:Staging:')".format(self.opensuse) url = self.makeurl(['search', 'project', query]) projxml = http_GET(url) root = ET.parse(projxml).getroot() @@ -522,7 +523,7 @@ class StagingAPI(object): informations) """ - _prefix = 'openSUSE:Factory:Staging:' + _prefix = 'openSUSE:{}:Staging:'.format(self.opensuse) if project.startswith(_prefix): project = project.replace(_prefix, '') url = self.makeurl(('factory', 'staging_projects', project + '.json')) @@ -621,7 +622,8 @@ class StagingAPI(object): if project.endswith(':DVD'): return project # not yet - if self.ring_packages.get(pkg) == 'openSUSE:Factory:Rings:2-TestDVD': + ring_dvd = 'openSUSE:{}:Rings:2-TestDVD'.format(self.opensuse) + if self.ring_packages.get(pkg) == ring_dvd: return project + ":DVD" return project @@ -735,7 +737,7 @@ class StagingAPI(object): def prj_from_letter(self, letter): if ':' in letter: # not a letter return letter - return 'openSUSE:Factory:Staging:%s' % letter + return 'openSUSE:{}:Staging:{}'.format(self.opensuse, letter) def list_requests_in_prj(self, project): where = "@by_project='%s'+and+@state='new'" % project diff --git a/osclib/unselect_command.py b/osclib/unselect_command.py index 5e8d9f1a..9497d6bd 100644 --- a/osclib/unselect_command.py +++ b/osclib/unselect_command.py @@ -1,7 +1,3 @@ -from osc import oscerr -from osc.core import get_request -from osc.core import http_GET - from osclib.request_finder import RequestFinder diff --git a/tests/freeze_tests.py b/tests/freeze_tests.py index 4d798a01..8fd41aa4 100644 --- a/tests/freeze_tests.py +++ b/tests/freeze_tests.py @@ -10,10 +10,20 @@ import difflib import subprocess import tempfile +from obs import APIURL +from obs import OBS from osclib.freeze_command import FreezeCommand +from osclib.stagingapi import StagingAPI class TestFreeze(unittest.TestCase): + def setUp(self): + """ + Initialize the configuration + """ + self.obs = OBS() + self.api = StagingAPI(APIURL) + def _get_fixture_path(self, filename): """ Return path for fixture @@ -28,7 +38,7 @@ class TestFreeze(unittest.TestCase): def test_bootstrap_copy(self): - fc = FreezeCommand('https://localhost') + fc = FreezeCommand(self.api) fp = self._get_fixture_path('staging-meta-for-bootstrap-copy.xml') fixture = subprocess.check_output('/usr/bin/xmllint --format %s' % fp, shell=True)