openSUSE-release-tools/osclib/check_duplicate_binaries_command.py

76 lines
2.8 KiB
Python

from __future__ import print_function
from osc.core import http_GET
from osclib.core import target_archs
from xml.etree import cElementTree as ET
import re
import urllib2
import yaml
class CheckDuplicateBinariesCommand(object):
def __init__(self, api):
self.api = api
# some packages create packages with the same name but
# different architecture than built for.
self.ignore_extra_archs = {
'i586': {
'glibc:i686': ('i686',)
},
'x86_64': {
'syslinux': ('s390x', 'ppc64le',)
}
}
def perform(self, save=False):
duplicates = {}
for arch in sorted(target_archs(self.api.apiurl, self.api.project), reverse=True):
url = self.api.makeurl(['build', self.api.project, 'standard', arch], { 'view': 'binaryversions' })
data = http_GET(url)
root = ET.parse(data).getroot()
binaries = {}
for packagenode in root.findall('.//binaryversionlist'):
package = packagenode.get('package')
for binarynode in packagenode.findall('binary'):
binary = binarynode.get('name')
# StagingAPI.fileinfo_ext(), but requires lots of calls.
match = re.match(r'(.*)-([^-]+)-([^-]+)\.([^-\.]+)\.rpm', binary)
if not match:
continue
parch = match.group(4)
if parch in ('src', 'nosrc'):
continue
name = match.group(1)
if arch in self.ignore_extra_archs \
and package in self.ignore_extra_archs[arch] \
and parch in self.ignore_extra_archs[arch][package]:
continue
binaries.setdefault(arch, {})
if name in binaries[arch]:
duplicates.setdefault(arch, {})
duplicates[arch].setdefault(name, set()).add(package)
duplicates[arch][name].add(binaries[arch][name])
continue
binaries[arch][name] = package
# convert sets to lists for readable yaml
for arch in duplicates.keys():
for name in duplicates[arch].keys():
duplicates[arch][name] = list(duplicates[arch][name])
current = yaml.dump(duplicates, default_flow_style=False)
if save:
args = ['{}:Staging'.format(self.api.project), 'dashboard', 'duplicate_binaries']
previous = self.api.load_file_content(*args)
if current != previous:
args.append(current)
self.api.save_file_content(*args)
else:
print(current)