1
0
mirror of https://github.com/openSUSE/osc.git synced 2024-11-12 23:56:13 +01:00

core: Add functions for glob matching of multibuild flavors

This commit is contained in:
Daniel Mach 2022-05-10 09:41:08 +02:00
parent cc393758df
commit 082986daf9

View File

@ -8155,4 +8155,114 @@ def vc_export_env(apiurl, quiet=False):
os.environ[env] = val
class MultibuildFlavorResolver:
def __init__(self, apiurl, project, package, use_local=False):
self.apiurl = apiurl
self.project = project
self.package = package
# whether to use local _multibuild file or download it from server
self.use_local = use_local
def get_multibuild_data(self):
"""
Retrieve contents of _multibuild file from given project/package.
Return None if the file doesn't exist.
"""
# use local _multibuild file
if self.use_local:
try:
with open("_multibuild", "r") as f:
return f.read()
except IOError as e:
if e.errno != errno.EEXIST:
raise
return None
# use _multibuild file from server
query = {}
query['expand'] = 1
u = makeurl(self.apiurl, ['source', self.project, self.package, '_multibuild'], query=query)
try:
f = http_GET(u)
except HTTPError as e:
if e.code == 404:
return None
raise
return f.read()
@staticmethod
def parse_multibuild_data(s):
"""
Return set of flavors from a string with multibuild xml.
"""
result = set()
# handle empty string and None
if not s:
return result
root = ET.fromstring(s)
for node in root.findall("flavor"):
result.add(node.text)
return result
def resolve(self, patterns):
"""
Return list of flavors based on given flavor `patterns`.
If `patterns` contain a glob, it's resolved according to _multibuild file,
values without globs are passed through.
"""
# determine if we're using globs
# yes: contact server and do glob matching
# no: use the specified values directly
use_globs = False
for pattern in patterns:
if '*' in pattern:
use_globs = True
break
if use_globs:
import fnmatch
multibuild_xml = self.get_multibuild_data()
all_flavors = self.parse_multibuild_data(multibuild_xml)
flavors = set()
for pattern in patterns:
# not a glob, use it as it is
if '*' not in pattern:
flavors.add(pattern)
continue
# match the globs with flavors from server
for flavor in all_flavors:
if fnmatch.fnmatch(flavor, pattern):
flavors.add(flavor)
else:
flavors = patterns
return sorted(flavors)
def resolve_as_packages(self, patterns):
"""
Return list of package:flavor based on given flavor `patterns`.
If a value from `patterns` contains a glob, it is resolved according to the _multibuild
file. Values without globs are passed through. If a value is empty string, package
without flavor is returned.
"""
flavors = self.resolve(patterns)
packages = []
for flavor in flavors:
if flavor:
packages.append(self.package + ':' + flavor)
else:
# special case: no flavor
packages.append(self.package)
return packages
# vim: sw=4 et