move the 'freeze' command in a file on its own and implement issue 1515
This commit is contained in:
parent
c82d7c03ad
commit
b2fff384b2
@ -267,7 +267,6 @@ def _staging_get_rings(self, opts):
|
||||
ret[entry.attrib['name']] = prj
|
||||
return ret
|
||||
|
||||
|
||||
def _staging_one_request(self, rq, opts):
|
||||
if (opts.verbose):
|
||||
ET.dump(rq)
|
||||
@ -309,59 +308,6 @@ def _staging_one_request(self, rq, opts):
|
||||
|
||||
self._staging_change_review_state(opts, id, 'accepted', by_group='factory-staging', message=msg)
|
||||
|
||||
|
||||
def _staging_check_one_source(self, flink, si, opts):
|
||||
package = si.get('package')
|
||||
# we have to check if its a link within the staging project
|
||||
# in this case we need to keep the link as is, and not freezing
|
||||
# the target. Otherwise putting kernel-source into staging prj
|
||||
# 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 = makeurl(opts.apiurl, ['source', 'openSUSE:Factory', package], { 'view': 'info', 'nofilename': '1' })
|
||||
#print package, linked.get('package'), linked.get('project')
|
||||
f = http_GET(url)
|
||||
proot = ET.parse(f).getroot()
|
||||
ET.SubElement(flink, 'package', { 'name': package, 'srcmd5': proot.get('lsrcmd5'), 'vrev': si.get('vrev') })
|
||||
return package
|
||||
ET.SubElement(flink, 'package', { 'name': package, 'srcmd5': si.get('srcmd5'), 'vrev': si.get('vrev') })
|
||||
return package
|
||||
|
||||
|
||||
def _staging_receive_sources(self, prj, sources, flink, opts):
|
||||
url = makeurl(opts.apiurl, ['source', prj], { 'view': 'info', 'nofilename': '1' } )
|
||||
f = http_GET(url)
|
||||
root = ET.parse(f).getroot()
|
||||
|
||||
for si in root.findall('sourceinfo'):
|
||||
package = self._staging_check_one_source(flink, si, opts)
|
||||
sources[package] = 1
|
||||
return sources
|
||||
|
||||
|
||||
def _staging_freeze_prjlink(self, prj, opts):
|
||||
url = makeurl(opts.apiurl, ['source', prj, '_meta'])
|
||||
f = http_GET(url)
|
||||
root = ET.parse(f).getroot()
|
||||
sources = dict()
|
||||
flink = ET.Element('frozenlinks')
|
||||
links = root.findall('link')
|
||||
links.reverse()
|
||||
self.projectlinks = []
|
||||
for link in links:
|
||||
self.projectlinks.append(link.get('project'))
|
||||
|
||||
for lprj in self.projectlinks:
|
||||
fl = ET.SubElement(flink, 'frozenlink', { 'project': lprj } )
|
||||
sources = self._staging_receive_sources(lprj, sources, fl, opts)
|
||||
|
||||
url = makeurl(opts.apiurl, ['source', prj, '_project', '_frozenlinks'], { 'meta': '1' } )
|
||||
f = http_PUT(url, data=ET.tostring(flink))
|
||||
root = ET.parse(f).getroot()
|
||||
print ET.tostring(root)
|
||||
|
||||
|
||||
@cmdln.option('-e', '--everything', action='store_true',
|
||||
help='during check do not stop on first first issue and show them all')
|
||||
@cmdln.option('-p', '--parent', metavar='TARGETPROJECT',
|
||||
@ -442,7 +388,8 @@ def do_staging(self, subcmd, opts, *args):
|
||||
project = args[1]
|
||||
self._staging_submit_devel(project, opts)
|
||||
elif cmd in ['freeze']:
|
||||
self._staging_freeze_prjlink(args[1], opts)
|
||||
import osclib.freeze_command
|
||||
osclib.freeze_command.FreezeCommand(opts.apiurl).perform(args[1])
|
||||
elif cmd in ['select']:
|
||||
# TODO: have an api call for that
|
||||
stprj = 'openSUSE:Factory:Staging:%s' % args[1]
|
||||
|
192
osclib/freeze_command.py
Normal file
192
osclib/freeze_command.py
Normal file
@ -0,0 +1,192 @@
|
||||
import osc
|
||||
from osc import cmdln
|
||||
from osc.core import *
|
||||
import time
|
||||
|
||||
class FreezeCommand:
|
||||
|
||||
def __init__(self, apiurl):
|
||||
self.apiurl = apiurl
|
||||
|
||||
def set_links(self):
|
||||
url = makeurl(self.apiurl, ['source', self.prj, '_meta'])
|
||||
f = http_GET(url)
|
||||
root = ET.parse(f).getroot()
|
||||
sources = dict()
|
||||
flink = ET.Element('frozenlinks')
|
||||
links = root.findall('link')
|
||||
links.reverse()
|
||||
self.projectlinks = []
|
||||
for link in links:
|
||||
self.projectlinks.append(link.get('project'))
|
||||
|
||||
def set_bootstrap_copy(self):
|
||||
url = makeurl(self.apiurl, ['source', self.prj, '_meta'])
|
||||
meta = self.prj_meta_for_bootstrap_copy(self.prj)
|
||||
http_PUT(url, data=meta)
|
||||
|
||||
def create_bootstrap_aggregate(self):
|
||||
self.create_bootstrap_aggregate_meta()
|
||||
self.create_bootstrap_aggregate_file()
|
||||
|
||||
def bootstrap_packages(self):
|
||||
url = makeurl(self.apiurl, ['source', 'openSUSE:Factory:Rings:0-Bootstrap'])
|
||||
f = http_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
|
||||
l.append(name)
|
||||
l.sort()
|
||||
return l
|
||||
|
||||
def create_bootstrap_aggregate_file(self):
|
||||
url = makeurl(self.apiurl, ['source', self.prj, 'bootstrap-copy', '_aggregate'])
|
||||
|
||||
root = ET.Element('aggregatelist')
|
||||
a = ET.SubElement(root, 'aggregate', { 'project': "openSUSE:Factory:Rings:0-Bootstrap" } )
|
||||
|
||||
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' } )
|
||||
|
||||
http_PUT(url, data=ET.tostring(root))
|
||||
|
||||
def create_bootstrap_aggregate_meta(self):
|
||||
url = makeurl(self.apiurl, ['source', self.prj, 'bootstrap-copy', '_meta'])
|
||||
|
||||
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' })
|
||||
# this one is the global toggle
|
||||
ET.SubElement(f, 'disable')
|
||||
|
||||
http_PUT(url, data=ET.tostring(root))
|
||||
|
||||
def build_switch_bootstrap_copy(self, state):
|
||||
url = makeurl(self.apiurl, ['source', self.prj, 'bootstrap-copy', '_meta'])
|
||||
pkgmeta = ET.parse(http_GET(url)).getroot()
|
||||
|
||||
for f in pkgmeta.find('build'):
|
||||
if f.get('repository', None) == 'bootstrap_copy':
|
||||
f.tag = state
|
||||
pass
|
||||
http_PUT(url, data=ET.tostring(pkgmeta))
|
||||
|
||||
def verify_bootstrap_copy_code(self, code):
|
||||
url = makeurl(self.apiurl, ['build', self.prj, '_result'], { 'package': 'bootstrap-copy' })
|
||||
|
||||
root = ET.parse(http_GET(url)).getroot()
|
||||
for result in root.findall('result'):
|
||||
if result.get('repository') == 'bootstrap_copy':
|
||||
if not result.get('code') in ['published', 'unpublished']:
|
||||
print ET.tostring(result)
|
||||
return False
|
||||
|
||||
if result.find('status').get('code') != code:
|
||||
print ET.tostring(result)
|
||||
return False
|
||||
return True
|
||||
|
||||
def perform(self, prj):
|
||||
self.prj = prj
|
||||
self.set_links()
|
||||
|
||||
self.freeze_prjlinks()
|
||||
|
||||
if 'openSUSE:Factory:Rings:1-MinimalX' in self.projectlinks \
|
||||
and not 'openSUSE:Factory:Rings:0-Bootstrap' in self.projectlinks:
|
||||
self.set_bootstrap_copy()
|
||||
self.create_bootstrap_aggregate()
|
||||
print "waiting for scheduler to disable..."
|
||||
while not self.verify_bootstrap_copy_code('disabled'):
|
||||
time.sleep(1)
|
||||
self.build_switch_bootstrap_copy('enable')
|
||||
print "waiting for scheduler to copy..."
|
||||
while not self.verify_bootstrap_copy_code('succeeded'):
|
||||
time.sleep(1)
|
||||
self.build_switch_bootstrap_copy('disable')
|
||||
|
||||
def prj_meta_for_bootstrap_copy(self, prj):
|
||||
root = ET.Element('project', { 'name': prj })
|
||||
ET.SubElement(root, 'title')
|
||||
ET.SubElement(root, 'description')
|
||||
ET.SubElement(root, 'link', { 'project': 'openSUSE:Factory:Rings:1-MinimalX' })
|
||||
f = ET.SubElement(root, 'build')
|
||||
# this one stays
|
||||
ET.SubElement(f, 'disable', { 'repository': 'bootstrap_copy' })
|
||||
# this one is the global toggle
|
||||
ET.SubElement(f, 'disable')
|
||||
f = ET.SubElement(root, 'publish')
|
||||
ET.SubElement(f, 'disable')
|
||||
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' })
|
||||
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' })
|
||||
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' })
|
||||
a = ET.SubElement(r, 'arch')
|
||||
a.text = 'x86_64'
|
||||
|
||||
return ET.tostring(root)
|
||||
|
||||
def freeze_prjlinks(self):
|
||||
sources = dict()
|
||||
flink = ET.Element('frozenlinks')
|
||||
|
||||
for lprj in self.projectlinks:
|
||||
fl = ET.SubElement(flink, 'frozenlink', { 'project': lprj } )
|
||||
sources = self.receive_sources(lprj, sources, fl)
|
||||
|
||||
url = makeurl(self.apiurl, ['source', self.prj, '_project', '_frozenlinks'], { 'meta': '1' } )
|
||||
http_PUT(url, data=ET.tostring(flink))
|
||||
|
||||
def receive_sources(self, prj, sources, flink):
|
||||
url = makeurl(self.apiurl, ['source', prj], { 'view': 'info', 'nofilename': '1' } )
|
||||
f = http_GET(url)
|
||||
root = ET.parse(f).getroot()
|
||||
|
||||
for si in root.findall('sourceinfo'):
|
||||
package = self.check_one_source(flink, si)
|
||||
sources[package] = 1
|
||||
return sources
|
||||
|
||||
def check_one_source(self, flink, si):
|
||||
package = si.get('package')
|
||||
# we have to check if its a link within the staging project
|
||||
# in this case we need to keep the link as is, and not freezing
|
||||
# the target. Otherwise putting kernel-source into staging prj
|
||||
# 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 = makeurl(self.apiurl, ['source', 'openSUSE:Factory', package], { 'view': 'info', 'nofilename': '1' })
|
||||
#print package, linked.get('package'), linked.get('project')
|
||||
f = http_GET(url)
|
||||
proot = ET.parse(f).getroot()
|
||||
ET.SubElement(flink, 'package', { 'name': package, 'srcmd5': proot.get('lsrcmd5'), 'vrev': si.get('vrev') })
|
||||
return package
|
||||
ET.SubElement(flink, 'package', { 'name': package, 'srcmd5': si.get('srcmd5'), 'vrev': si.get('vrev') })
|
||||
return package
|
||||
|
@ -9,6 +9,9 @@ import sys
|
||||
import contextlib
|
||||
import unittest
|
||||
import httpretty
|
||||
import difflib
|
||||
import subprocess
|
||||
import tempfile
|
||||
# mock is part of python3.3
|
||||
try:
|
||||
import unittest.mock
|
||||
@ -30,6 +33,15 @@ class TestApiCalls(unittest.TestCase):
|
||||
"""
|
||||
return os.path.join(os.getcwd(), 'tests/fixtures')
|
||||
|
||||
def _get_fixture_path(self, filename):
|
||||
return os.path.join(self._get_fixtures_dir(), filename)
|
||||
|
||||
def _get_fixture_content(self, filename):
|
||||
response = open(self._get_fixture_path(filename), 'r')
|
||||
content = response.read()
|
||||
response.close()
|
||||
return content
|
||||
|
||||
def _register_pretty_url_get(self, url, filename):
|
||||
"""
|
||||
Register specified get url with specific filename in fixtures
|
||||
@ -37,9 +49,7 @@ class TestApiCalls(unittest.TestCase):
|
||||
:param filename: name of the fixtures file
|
||||
"""
|
||||
|
||||
response = open(os.path.join(self._get_fixtures_dir(), filename), 'r')
|
||||
content = response.read()
|
||||
response.close()
|
||||
content = self._get_fixture_content(filename)
|
||||
|
||||
httpretty.register_uri(httpretty.GET,
|
||||
url,
|
||||
@ -274,6 +284,22 @@ class TestApiCalls(unittest.TestCase):
|
||||
data = f.read().strip()
|
||||
self.assertEqual(sys.stdout.getvalue().strip(), data)
|
||||
|
||||
def test_bootstrap_copy(self):
|
||||
import osclib.freeze_command
|
||||
fc = osclib.freeze_command.FreezeCommand('http://localhost')
|
||||
|
||||
fp = self._get_fixture_path('staging-meta-for-bootstrap-copy.xml')
|
||||
fixture = subprocess.check_output('/usr/bin/xmllint --format %s' % fp, shell=True)
|
||||
|
||||
f = tempfile.NamedTemporaryFile(delete=False)
|
||||
f.write(fc.prj_meta_for_bootstrap_copy('openSUSE:Factory:Staging:A'))
|
||||
f.close()
|
||||
|
||||
output = subprocess.check_output('/usr/bin/xmllint --format %s' % f.name, shell=True)
|
||||
|
||||
for line in difflib.unified_diff(fixture.split("\n"), output.split("\n")):
|
||||
print line
|
||||
self.assertEqual(output, fixture)
|
||||
|
||||
# Here place all mockable functions
|
||||
@contextlib.contextmanager
|
||||
|
29
tests/fixtures/staging-meta-for-bootstrap-copy.xml
vendored
Normal file
29
tests/fixtures/staging-meta-for-bootstrap-copy.xml
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
<project name="openSUSE:Factory:Staging:A">
|
||||
<title></title>
|
||||
<description></description>
|
||||
<link project="openSUSE:Factory:Rings:1-MinimalX"/>
|
||||
<build>
|
||||
<disable repository="bootstrap_copy"/>
|
||||
<disable/>
|
||||
</build>
|
||||
<publish>
|
||||
<disable/>
|
||||
</publish>
|
||||
<debuginfo>
|
||||
<enable/>
|
||||
</debuginfo>
|
||||
<repository name="bootstrap_copy">
|
||||
<path project="openSUSE:Factory" repository="ports"/>
|
||||
<arch>i586</arch>
|
||||
<arch>x86_64</arch>
|
||||
</repository>
|
||||
<repository linkedbuild="all" name="standard" rebuild="direct">
|
||||
<path project="openSUSE:Factory:Staging:A" repository="bootstrap_copy"/>
|
||||
<arch>i586</arch>
|
||||
<arch>x86_64</arch>
|
||||
</repository>
|
||||
<repository linkedbuild="all" name="images" rebuild="direct">
|
||||
<path project="openSUSE:Factory:Staging:A" repository="standard"/>
|
||||
<arch>x86_64</arch>
|
||||
</repository>
|
||||
</project>
|
Loading…
x
Reference in New Issue
Block a user