-
Notifications
You must be signed in to change notification settings - Fork 97
/
repo2fileprovides.py
executable file
·61 lines (52 loc) · 2.28 KB
/
repo2fileprovides.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#!/usr/bin/python3
import gzip
import pyzstd
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|.zst)", file=sys.stderr)
sys.exit(1)
repofilename = sys.argv[1]
if repofilename.endswith('.gz'):
xmlfile = gzip.GzipFile(repofilename)
elif repofilename.endswith('.zst'):
xmlfile = pyzstd.ZstdFile(repofilename)
else:
xmlfile = open(repofilename, 'rb')
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]))}")