#!/usr/bin/python3
# public domain

import apt_pkg
import apt.cache
import re
import time
import os

apt_pkg.init()

def flatten_once(lst):
    for sublst in lst:
        for elem in sublst:
            yield elem

def traverse(pc, c, interm_all_pkgs, seen=()):
    ret = False
    for dep in flatten_once(c.dependencies):
        if dep.name in seen:
            continue
        try:
            depc = pc[dep.name].candidate
        except KeyError:
            continue
        if depc is None:
            continue
        if depc.record.get("Multi-Arch") == "foreign":
            continue
        if depc.architecture == 'all':
            if dep.name in interm_all_pkgs:  # short cut
                ret = True
            elif traverse(pc, depc, interm_all_pkgs, seen + (dep.name,)):
                interm_all_pkgs.add(dep.name)
                ret = True
        else:
            ret = True
    return ret

def main():
    rootdir = os.path.expanduser("~/.chdist/sid")
    pc = apt.cache.Cache(rootdir=rootdir)
    interm_all_pkgs = set()
    for p in pc:
        c = p.candidate
        if not c:
            continue
        if c.architecture != 'amd64':
            continue
        for dep in flatten_once(c.dependencies):
            try:
                depc = pc[dep.name].candidate
            except KeyError:
                continue
            if depc is None:
                continue
            if depc.architecture != 'all':
                continue
            if depc.record.get("Multi-Arch") == "foreign":
                continue
            if traverse(pc, depc, interm_all_pkgs):
                interm_all_pkgs.add(dep.name)

    groups = [
        ("Java", re.compile("^java:lib.*-java$")),
        ("Mono", re.compile("^cli-mono:libmono-.*-cil$")),
        ("Perl", re.compile("^perl:lib.*-perl$")),
        ("Python", re.compile("^(python|zope):python3?-")),
        ("Ruby", re.compile("^ruby:ruby-")),
        ("Node", re.compile("^web:node-")),
        ("R", re.compile("^gnu-r:r-(cran|bioc)-")),
        ("Go", re.compile("^devel:golang-.*-dev$")),
        ("cross libs", re.compile("^(lib)?devel:lib.*-.*-cross$")),
        ("-common and -data", re.compile(".*-(common|data)$")),
    ]

    summary = {}
    pkgs = []

    for p in interm_all_pkgs:
        c = pc[p]
        found = "Others"
        for name, pattern in groups:
            if pattern.match("%s:%s" % (c.candidate.section, p)):
                found = name
                break
        summary[found] = summary.get(found, 0) + 1
        pkgs.append((c.candidate.section, p))

    summary = sorted(summary.items(), key=lambda pair: -pair[1])
    pkgs.sort()

    print("""<html><head><title>Multiarch interpreter issue size</title></head>
<body><h1>Multiarch interpreter issue size</h1>""")
    print("<p>Last updated: %s</p>" % time.asctime())
    print("<p>Total affected packages: %d</p>" % len(pkgs))
    print("<p>This page lists architecture independent packages from sid/amd64 that are on a dependency path from an architecture dependent package to another architecture dependent package.</p>")
    print("<h3>Summary</h3>")
    print("<table border='1'><tr><th>Group</th><th>affected packages</th></tr>")
    for item in summary:
        print("<tr><td>%s</td><td>%d</td></tr>" % item)
    print("</table>")
    print("<h3>Details</h3>")
    print("<table border='1'><tr><th>Section</th><th>Package</th></tr>")
    for item in pkgs:
        print("<tr><td>%s</td><td>%s</td></tr>" % item)
    print("</table>")
    print("<p> Source at people.d.o:/home/helmutg/multiarch_interpreter_workaround.py</p></body></html>")

if __name__ == "__main__":
    main()
