2410682af6
A simple tool that compares dependencies of binary packages in two repositories. For packages with matching NEVR, it shows where their dependencies differ, possibly hinting at the need to rebuild one package or another.
125 lines
3.5 KiB
Python
125 lines
3.5 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
|
|
|
|
|
|
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(diffs.iteritems()):
|
|
print(k, ' '.join(v), sep='\t')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main(*sys.argv[1:]))
|