Makes staging pluging Factory agnostic.

This commit is contained in:
Alberto Planas 2014-08-07 12:39:41 +02:00
parent 9abec06101
commit 29b8bcca6b
12 changed files with 151 additions and 141 deletions

View File

@ -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)

View File

@ -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()

View File

@ -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')

View File

@ -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)

View File

@ -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']

View File

@ -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"
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') })
ET.SubElement(flink, 'package', {'name': package, 'srcmd5': si.get('srcmd5'), 'vrev': si.get('vrev')})
return package

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)