diff options
-rwxr-xr-x | multiarchanalyze.py | 80 |
1 files changed, 70 insertions, 10 deletions
diff --git a/multiarchanalyze.py b/multiarchanalyze.py index 5cd5de7..201ffc3 100755 --- a/multiarchanalyze.py +++ b/multiarchanalyze.py @@ -1,7 +1,11 @@ #!/usr/bin/python import argparse +import os.path import sqlite3 +import sys + +import yaml from dedup.utils import fetchiter @@ -61,13 +65,16 @@ def show_combinations(combinations): return "%d bipartitions of %s" % (len(partitions), show_archset(edges.keys())) if all(len(outedges) == len(edges) - 1 for outedges in edges.values()): - return "any two of " + show_archset(edges.keys(), limit=4) + return "any two of " + show_archset(edges.keys(), limit=5) return "%s with %d combinations" % (show_archset(edges.keys()), len(combinations)) def show_files(filenames): if len(filenames) == 1: return next(iter(filenames)) + prefix = os.path.commonprefix(filenames) + if prefix not in ('', '/'): + return "%d files starting with %s" % (len(filenames), prefix) return "%d files" % len(filenames) def main(): @@ -76,39 +83,92 @@ def main(): default="test.sqlite3", help="path to the sqlite3 database file") args = parser.parse_args() + hints = [] db = sqlite3.connect(args.database) cur = db.cursor() cur.execute("SELECT name1, architecture1, architecture2, filename FROM masame_conflict;") same_conflicts = {} for package, arch1, arch2, filename in fetchiter(cur): + if filename.startswith("./"): + filename = filename[1:] conflicts = same_conflicts.setdefault(package, {}) conflicts.setdefault(filename, set()).add((arch1, arch2)) for package, conflicts in sorted(same_conflicts.items()): all_combinations = set() for combinations in conflicts.values(): all_combinations.update(combinations) - print("%s conflicts on %s on %s" % - (package, show_files(conflicts.keys()), - show_combinations(all_combinations))) + desc = "%s conflicts on %s on %s" % \ + (package, show_files(conflicts.keys()), + show_combinations(all_combinations)) + hints.append(dict( + binary=package, + description=desc, + link="https://wiki.debian.org/MultiArch/Hints#file-conflict", + severity="high")) cur.execute("SELECT name FROM maforeign_candidate ORDER BY name;") for name, in fetchiter(cur): - print("%s could be Multi-Arch: foreign" % name) + hints.append(dict( + binary=name, + description="%s could be marked Multi-Arch: foreign" % name, + link="https://wiki.debian.org/MultiArch/Hints#ma-foreign", + severity="rdeps")) cur.execute("SELECT name FROM archall_candidate ORDER BY name;") archall_suggests = set() for name, in fetchiter(cur): archall_suggests.add(name) - print("%s could be converted to Architecture: all + Multi-Arch: foreign" % name) + desc = "%s could be converted to Architecture: all and marked Multi-Arch: foreign" % \ + name + hints.append(dict( + binary=name, + description=desc, + link="https://wiki.debian.org/MultiArch/Hints#arch-all", + severity="low")) cur.execute("SELECT name FROM masame_candidate ORDER BY name;") for name, in fetchiter(cur): - if name not in archall_suggests: - print("%s could be Multi-Arch: same" % name) + if name in archall_suggests: + continue + hints.append(dict( + binary=name, + description="%s could be marked Multi-Arch: same" % name, + link="https://wiki.debian.org/MultiArch/Hints#ma-same", + severity="normal")) + cur.execute("SELECT depender, dependee FROM colonany_candidate ORDER BY depender;") for depender, dependee in fetchiter(cur): - print("%s could have its %s dependency annotated with :any" % - (depender, dependee)) + desc = "%s could have its dependency on %s annotated with :any" % \ + (depender, dependee) + hints.append(dict( + binary=depender, + description=desc, + link="https://wiki.debian.org/MultiArch/Hints#dep-any", + severity="normal")) + + for hint in hints: + if "source" not in hint: + cur.execute("SELECT distinct(source) FROM package WHERE name = ?;", + (hint["binary"],)) + row = cur.fetchone() + if row and row[0] and not cur.fetchone(): + hint["source"] = row[0] + + if hint.get("severity") == "rdeps": + cur.execute("SELECT count(*) FROM depends WHERE dependee = ?;", + (hint["binary"],)) + rdeps = cur.fetchone()[0] + if rdeps >= 50: + hint["severity"] = "high" + elif rdeps: + hint["severity"] = "normal" + else: + hint["severity"] = "low" + + yaml.safe_dump(dict(format="multiarch-hints-1.0", hints=hints), + default_flow_style=False, + width=1000, + stream=sys.stdout) if __name__ == "__main__": main() |