port-compare/port_stats/deps_cmp.py
Ivan A. Melnikov b674458df2 First steps towards python3 compatibility
Reports still use bytes/strs interchangeably,
but at least we can load things.
2023-03-10 14:42:01 +04:00

126 lines
3.6 KiB
Python

from __future__ import print_function
import json
import logging
import os
import re
import sys
from collections import defaultdict
import rpm
from port_stats import colorize
from port_stats import lists
from port_stats import utils
LOG = logging.getLogger('deps_cmp')
IGNORE_PATTERNS = tuple(
re.compile(p) for p in (
r'^rtld\(',
r'^rpmlib\(',
# glibc and gcc parts:
r'^ld.*so',
r'^/lib/ld.*so',
r'^/lib64/ld.*so',
r'^libc\.so',
r'^libm\.so',
# r'^libgcc_s\.so',
r'^libatomic\.so',
r'^libpthread\.so',
# r'^libstdc...so\.6',
))
def _gen_requires(header):
for dep in header[rpm.RPMTAG_REQUIRENAME]:
if dep.startswith('.'):
# strict interdeps -- we want to extract the name part
dep = '-'.join(dep.split('-')[1:-2])
if any(p.search(dep) for p in IGNORE_PATTERNS):
continue
yield dep
def source_name(header):
return header[rpm.RPMTAG_SOURCERPM].rsplit('-', 2)[0]
def read_pkg_lists(repo_dict):
result = []
prefix = repo_dict['path']
for arch in repo_dict['arch']:
path = os.path.join(prefix, arch, 'base', 'pkglist.classic.xz')
result.extend(lists.read_pkglist_headers_rpm(path))
return result
def main(config_path, colorize_name, result_prefix='bin_'):
logging.basicConfig(
format='%(asctime)s %(levelname)-5s %(name)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
stream=sys.stderr, level=logging.INFO)
LOG.info('Coparing deps for %s, config=%s', colorize_name, config_path)
with open(config_path) as f:
config = json.load(f)
names = None
for clrz in config['colorize']:
if clrz['name'] == colorize_name:
names = clrz
break
if not names:
LOG.error('Unknown colorize name: %s', colorize_name)
return 1
base_by_name = {}
for header in read_pkg_lists(config['repos'][names['base']]):
base_by_name[header[rpm.RPMTAG_NAME]] = header
new_bin_headers = sorted(
read_pkg_lists(config['repos'][names['new']]),
key=lambda h: h[rpm.RPMTAG_NAME])
LOG.info('Loaded %s base binary packages, %s new binary packages',
len(base_by_name), len(new_bin_headers))
for_deps = []
with open(result_prefix + 'colors.tsv', 'w') as out:
for nh in new_bin_headers:
n_nevr = lists.NEVR.from_header(nh)
bh = base_by_name.get(n_nevr.name)
b_nevr = lists.NEVR.from_header(bh) if bh else None
color = colorize.colorize_pair(b_nevr, n_nevr)
if color in ('SLATE', 'GREEN'):
for_deps.append((bh, nh, color))
print(color, n_nevr.name,
lists.format_evr(b_nevr), lists.format_evr(n_nevr),
sep='\t', file=out)
LOG.info("Found %s pairs to compare", len(for_deps))
diffs = defaultdict(list)
for bh, nh, color in for_deps:
b_reqs = sorted(_gen_requires(bh))
n_reqs = sorted(_gen_requires(nh))
if b_reqs != n_reqs:
name = nh[rpm.RPMTAG_NAME]
common = set(n_reqs) & set(b_reqs)
b_left = [r for r in b_reqs if r not in common]
n_left = [r for r in n_reqs if r not in common]
for x in b_left:
diffs[x + '\t--'].append(name)
for x in n_left:
diffs[x + '\t++'].append(name)
for k, v in sorted(utils.items(diffs)):
print(k, ' '.join(v), sep='\t')
if __name__ == '__main__':
sys.exit(main(*sys.argv[1:]))