openSUSE-release-tools/repo2fileprovides.py

58 lines
2.2 KiB
Python
Executable File

#!/usr/bin/python3
import gzip
import sys
from collections import defaultdict
from lxml import etree
if len(sys.argv) != 2:
print("Script to generate necessary FileProvides lines needed by OBS from repo data.", file=sys.stderr)
print("Usage: repo2fileprovides.py primary.xml(.gz)", file=sys.stderr)
sys.exit(1)
repofilename = sys.argv[1]
xmlfile = open(repofilename, 'rb')
if repofilename.endswith('.gz'):
xmlfile = gzip.GzipFile(fileobj=xmlfile)
NS = {'md': 'http://linux.duke.edu/metadata/common',
'rpm': 'http://linux.duke.edu/metadata/rpm'}
repodata = etree.parse(xmlfile)
# Step 1: Collect all provided files
# Set of all provided files
providedfiles = set()
# Map of filename -> set of packages providing it
fileprovides = defaultdict(set)
for pkg in repodata.iterfind('/md:package', namespaces=NS):
pkgname = pkg.xpath('./md:name/text()', namespaces=NS)[0]
# Implicit file provides
for f in pkg.iterfind('./md:format/md:file', namespaces=NS):
filename = f.text
fileprovides[filename].add(pkgname)
providedfiles.add(filename)
# Explicit file provides
for filename in pkg.xpath("./md:format/rpm:provides/rpm:entry[starts-with(@name, '/')]/@name",
namespaces=NS):
fileprovides[filename].add(pkgname)
providedfiles.add(filename)
# Step 2: Collect all required files
requiredfiles = set(repodata.xpath("/md:metadata/md:package/md:format/rpm:requires/rpm:entry[starts-with(@name, '/')]/@name",
namespaces=NS))
# Split up boolean deps
booleandeps = set(repodata.xpath("/md:metadata/md:package/md:format/rpm:requires/rpm:entry"
"[starts-with(@name, '(') and contains(@name, '/')]/@name",
namespaces=NS))
for dep in booleandeps:
for capability in dep.replace('(', ' ').replace(')', ' ').split():
if capability[0] == '/':
requiredfiles.add(capability)
# Step 3: For all provided files which are also required, print "FileProvides"
# lines
for filename in sorted(providedfiles.intersection(requiredfiles)):
print(f"FileProvides: {filename} {' '.join(sorted(fileprovides[filename]))}")