Inapt: SRPM dependencies report
For now, we just load src/pkglists and build a simple report on what packages you have to have in order to satisfy SRPM's build requires. Everything is very approxymate, of course.
This commit is contained in:
parent
58c796d15c
commit
8edb64675c
74
port_stats/inapt.py
Normal file
74
port_stats/inapt.py
Normal file
@ -0,0 +1,74 @@
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import collections
|
||||
import logging
|
||||
|
||||
import rpm
|
||||
|
||||
import lists
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Dependency(collections.namedtuple(
|
||||
'Dependency', ['name', 'flags', 'version'])):
|
||||
|
||||
HEADER_TRIPLETS = {
|
||||
'require': (rpm.RPMTAG_REQUIRENAME,
|
||||
rpm.RPMTAG_REQUIREFLAGS,
|
||||
rpm.RPMTAG_REQUIREVERSION),
|
||||
'provide': (rpm.RPMTAG_PROVIDENAME,
|
||||
rpm.RPMTAG_PROVIDEFLAGS,
|
||||
rpm.RPMTAG_PROVIDEVERSION)
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_header(cls, header, kind):
|
||||
tags = cls.HEADER_TRIPLETS[kind]
|
||||
triplets = zip(header[tags[0]], header[tags[1]], header[tags[2]])
|
||||
for name, flags, version in triplets:
|
||||
if not name.startswith('rpmlib('):
|
||||
yield cls(name, flags, version or None)
|
||||
if kind == 'provide':
|
||||
for name in header[rpm.RPMTAG_FILENAMES]:
|
||||
yield cls(name, 0, None)
|
||||
|
||||
|
||||
class DependencyInfo(collections.namedtuple(
|
||||
'DependencyInfo', ['src_req', 'srcrpms',
|
||||
'bin_req', 'reverse_prov'])):
|
||||
|
||||
@classmethod
|
||||
def load(cls, repo):
|
||||
src_list, bin_list = lists.read_pkglist_heders_for_repo(
|
||||
repo['path'], repo['arch'], components=['classic'])
|
||||
|
||||
def deps(*args):
|
||||
return frozenset(Dependency.from_header(*args))
|
||||
|
||||
src_req = dict((h.name, deps(h, 'require')) for h in src_list)
|
||||
srcrpms = dict((h.name, h[rpm.RPMTAG_SOURCERPM].rsplit('-', 2)[0])
|
||||
for h in bin_list)
|
||||
bin_req = dict((h.name, deps(h, 'require')) for h in bin_list)
|
||||
bin_prov = dict((h.name, deps(h, 'provide')) for h in bin_list)
|
||||
reverse_prov = {}
|
||||
for name, provs in bin_prov.iteritems():
|
||||
for p in provs:
|
||||
reverse_prov.setdefault(p.name, []).append((name, p))
|
||||
return cls(src_req, srcrpms, bin_req, reverse_prov)
|
||||
|
||||
def simple_srpm_report(self, srpm):
|
||||
result = collections.defaultdict(lambda: collections.defaultdict(set))
|
||||
for dep in self.src_req[srpm]:
|
||||
for p in self.reverse_prov[dep.name]:
|
||||
bin_name = p[0]
|
||||
src_name = self.srcrpms[bin_name]
|
||||
result[src_name][p[0]].add(dep.name)
|
||||
|
||||
for srpm in sorted(result):
|
||||
line = ['%-30s' % srpm]
|
||||
for k, v in result[srpm].iteritems():
|
||||
line.append('%s [%s]' % (k, ' '.join(sorted(v))))
|
||||
print(' '.join(line))
|
@ -80,6 +80,22 @@ def read_pkglist_headers_rpm(path):
|
||||
input_file.close()
|
||||
|
||||
|
||||
def read_pkglist_heders_for_repo(repo_path, arches, components=None):
|
||||
bin_headers = []
|
||||
src_headers = []
|
||||
for arch in arches:
|
||||
basedir = os.path.join(repo_path, arch, 'base')
|
||||
for pkglist in os.listdir(basedir):
|
||||
parts = pkglist.split('.', 3)
|
||||
if parts[0] not in ('pkglist', 'srclist'):
|
||||
continue
|
||||
if components is not None and parts[1] not in components:
|
||||
continue
|
||||
(src_headers if parts[0] == 'srclist' else bin_headers).extend(
|
||||
read_pkglist_headers_rpm(os.path.join(basedir, pkglist)))
|
||||
return src_headers, bin_headers
|
||||
|
||||
|
||||
def _read_pkglist_rpm(path):
|
||||
return (NEVR.from_header(h) for h in read_pkglist_headers_rpm(path))
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user