Makes staging pluging Factory agnostic.
This commit is contained in:
parent
9abec06101
commit
29b8bcca6b
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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')
|
||||
|
@ -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)
|
||||
|
@ -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']
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user