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