From 9e28dd5f8b9d6934ce48016bbd92f26090341624 Mon Sep 17 00:00:00 2001 From: alexanderlaw Date: Thu, 6 Nov 2014 20:49:46 +0300 Subject: [PATCH] Add analyze-repo-closure script --- analyze-repo-closure.py | 197 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100755 analyze-repo-closure.py diff --git a/analyze-repo-closure.py b/analyze-repo-closure.py new file mode 100755 index 0000000..73441ba --- /dev/null +++ b/analyze-repo-closure.py @@ -0,0 +1,197 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +import os +import sys +import argparse +import sqlite3 +import string +import rpm +import re +import gettext +prepare_repodb = __import__("prepare-repodb") + +gettext.install('urpm-tools') + +DB = 'repo.db' + +def parseargs(args): + parser = argparse.ArgumentParser(description=_('Find a closed subset of the repository\'s for a given list of packages.')) + parser.add_argument('packages_lst', metavar='packages.lst', + help=('path to packages.lst')) + parser.add_argument('--repo', action='append', nargs='+', required=True, + metavar='REPO', help=_('URL or name of a repository')) + opts = parser.parse_args() + return opts + +def main(args): + options = parseargs(args) + with open(options.packages_lst, 'r') as f: + ks_cfg = f.read() + section = None + in_packages = False + sel_packages = [] + for line in ks_cfg.split('\n'): + ls = line.strip() + if ls and not ls.startswith('#'): + sel_packages.append(ls) + + conn = sqlite3.connect(DB) + c = conn.cursor() + repodirs = [] + for repo in options.repo: + print repo + rid = c.execute(""" +SELECT id FROM repodirs WHERE name = ? OR url = ? +""", [repo[0], repo[0]]).fetchall() + if not rid: + print 'Repository "%s" not found.' % repo + exit(1) + repodirs.append(rid[0][0]) + if not repodirs: + print 'No repositories specified.' + exit(1) + if not sel_packages: + print 'No packages specified.' + exit(1) + in_repodirs = ','.join(str(id) for id in repodirs) + package_ids = [] + for spackage in sel_packages: + packages_found = c.execute(""" +SELECT id, nvra, version, release FROM packages WHERE repodir_id IN (%s) AND name = ? +""" % in_repodirs, [spackage]).fetchall() + if not packages_found: + print 'Package "%s" not found!' % spackage + continue + pid = None + if len(packages_found) > 1: + chosen_nvra = None + chosen_version = None + for vpid in packages_found: + better_found = pid is None + verrel = (vpid[2] if vpid[2] is not None else '') + '-' + \ + (vpid[3] if vpid[3] is not None else '') + if not better_found: + better_found = prepare_repodb.version_ok(chosen_version, + prepare_repodb.RPMSENSE_GREATER, + verrel) + if better_found: + pid = vpid[0] + chosen_nvra = vpid[1] + chosen_version = verrel + print ('Multiple versions of "%s" found (%s). Choosing latest: %s.' % + (spackage, ', '.join(cp[1] for cp in packages_found), chosen_nvra)) + else: + pid = packages_found[0][0] + package_ids.append(pid) + + pre_package_cnt = 0 + src_package_cnt = 0 + src_package_ids = [] + while True: + src_package_cnt = len(src_package_ids) + print >> sys.stderr, "packages processed:", pre_package_cnt, len(package_ids) + if pre_package_cnt == len(package_ids): + break + in_next_packages = ','.join(str(id) for id in package_ids[pre_package_cnt:]) + pre_package_cnt = len(package_ids) + + for lost_src in c.execute(""" +SELECT '"' || nvra || '" (' || sourcerpm || ')' FROM packages + WHERE id IN (%s) AND + sourcerpm IS NOT NULL AND sourcerpm_package IS NULL + ORDER BY nvra +""" % in_next_packages): + print 'Source rpm for package %s not found!' % lost_src + + + in_packages = ','.join(str(id) for id in package_ids) + in_src_packages = ','.join(str(id) for id in src_package_ids) \ + if len(src_package_ids) > 0 else '-1' + for src_package in c.execute(""" +SELECT sourcerpm_package FROM packages + WHERE id IN (%s) AND sourcerpm IS NOT NULL AND sourcerpm_package IS NOT NULL + AND sourcerpm_package NOT IN (%s) + """ % (in_packages, in_src_packages)): + src_package_ids.append(src_package[0]) + print >> sys.stderr, "src packages processed:", src_package_cnt, len(src_package_ids) + if src_package_cnt == len(src_package_ids): + break + + while True: + package_cnt = len(package_ids) + in_packages = ','.join(str(id) for id in package_ids + src_package_ids) + for required_package in c.execute(""" +SELECT packages.id, packages.name, nvra +FROM packages, package_requires_res +WHERE packages.id = package_requires_res.dep_package_id AND + packages.repodir_id IN (%s) AND + package_requires_res.package_id IN (%s) AND + packages.id NOT IN (%s) +ORDER BY packages.name + """ % (in_repodirs, in_packages, in_packages)): + package_ids.append(required_package[0]) + if package_cnt == len(package_ids): + break + + + in_src_packages = ','.join(str(id) for id in src_package_ids) \ + if len(src_package_ids) > 0 else '-1' + + repo_packages_cnt = 0 + pre_repodir_id = -1 + for reduntant_package in c.execute(""" +SELECT repodir_id, repodirs.name, packages.id, packages.nvra + FROM packages, repodirs + WHERE packages.repodir_id = repodirs.id AND + packages.id IN (%s) + ORDER BY repodir_id, nvra +""" % (in_src_packages)): + (repodir_id, repodir_name, package_nvra) = \ + (reduntant_package[0], reduntant_package[1], reduntant_package[3]) + if pre_repodir_id != repodir_id: + if pre_repodir_id == -1: + print 'Required source packages:' + else: + print 'Total: %d' % repo_packages_cnt + print '' + print '%d) %s' % (repodir_id, repodir_name) + pre_repodir_id = repodir_id + repo_packages_cnt = 0 + print '\t%s' % package_nvra + repo_packages_cnt += 1 + if pre_repodir_id != -1: + print 'Total: %d' % repo_packages_cnt + print '' + + repo_packages_cnt = 0 + pre_repodir_id = -1 + for reduntant_package in c.execute(""" +SELECT repodir_id, repodirs.name, packages.id, packages.nvra + FROM packages, repodirs + WHERE packages.repodir_id = repodirs.id AND + repodirs.name IN (SELECT sources FROM repodirs WHERE id IN (%s)) AND + packages.id NOT IN (%s) + ORDER BY repodir_id, nvra +""" % (in_repodirs, in_src_packages)): + (repodir_id, repodir_name, package_nvra) = \ + (reduntant_package[0], reduntant_package[1], reduntant_package[3]) + if pre_repodir_id != repodir_id: + if pre_repodir_id == -1: + print 'Redundant source packages:' + else: + print 'Total: %d' % repo_packages_cnt + print '' + print '%d) %s' % (repodir_id, repodir_name) + pre_repodir_id = repodir_id + repo_packages_cnt = 0 + print '\t%s' % package_nvra + repo_packages_cnt += 1 + if pre_repodir_id != -1: + print 'Total: %d' % repo_packages_cnt + print '' + + conn.rollback() + +if __name__ == "__main__": + main(sys.argv)