summaryrefslogtreecommitdiff
path: root/multiarchanalyze.py
blob: 5cd5de7d10632416dc5a61b6bc9a16642584d5f7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#!/usr/bin/python

import argparse
import sqlite3

from dedup.utils import fetchiter

def bipartitions(edges):
    """
    @type edges: {T: set(T)}
    @rtype: [(set(T), set(T))]
    """
    todo = set(edges.keys())
    result = []
    colors = {}
    while todo:
        node = todo.pop()
        colors[node] = False
        partition = (set((node,)), set())
        todo2 = set((node,))
        while todo2:
            partnode = todo2.pop()
            for nextnode in edges[partnode]:
                try:
                    if colors[nextnode] == colors[partnode]:
                        raise ValueError("not bipartite")
                except KeyError:
                    colors[nextnode] = not colors[partnode]
                    partition[colors[nextnode]].add(nextnode)
                    todo2.add(nextnode)
                    todo.remove(nextnode)
        result.append(partition)
    return result

def show_archset(archs, limit=3):
    """
    @type archs: set(str)
    @rtype: str
    """
    archs = set(archs)
    if len(archs) > limit:
        return "%d archs" % len(archs)
    return ", ".join(sorted(archs))

def show_combinations(combinations):
    edges = {}
    for left, right in combinations:
        edges.setdefault(left, set()).add(right)
        edges.setdefault(right, set()).add(left) # safety
    if len(edges) == 2:
        return "%s <-> %s" % (min(left, right), max(left, right))
    try:
        partitions = bipartitions(edges)
    except ValueError:
        pass
    else:
        if len(partitions) == 1:
            return " <-> ".join(show_archset(archs, 4)
                                for archs in sorted(partitions[0], key=len))
        else:
            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 "%s with %d combinations" % (show_archset(edges.keys()),
                                        len(combinations))

def show_files(filenames):
    if len(filenames) == 1:
        return next(iter(filenames))
    return "%d files" % len(filenames)

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("-d", "--database", action="store",
                        default="test.sqlite3",
                        help="path to the sqlite3 database file")
    args = parser.parse_args()
    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):
        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)))

    cur.execute("SELECT name FROM maforeign_candidate ORDER BY name;")
    for name, in fetchiter(cur):
        print("%s could be Multi-Arch: foreign" % name)

    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)

    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)
    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))

if __name__ == "__main__":
    main()