-
Notifications
You must be signed in to change notification settings - Fork 0
/
auto-transitioner.py
executable file
·162 lines (126 loc) · 5.55 KB
/
auto-transitioner.py
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#!/usr/bin/python
import apt_pkg
import copy
import itertools
import os
import sys
from debian.rt.package import (SourcePackage, BinaryPackage)
from debian.rt.mirror import PackageMirrorDist
from debian.rt.util import (binary_has_external_rdeps,
as_ben_file, compute_reverse_dependencies,
read_sources, read_binaries
)
def find_nearly_finished_transitions(src_test, bin_test, stage):
src2bin = {}
for bin_pkg in bin_test.itervalues():
if bin_pkg.architecture == 'all':
continue
source_pkg = src_test.get(bin_pkg.source, None)
if source_pkg is None:
src2bin.setdefault(bin_pkg.source, set())
src2bin[bin_pkg.source].add(bin_pkg.package)
continue
if apt_pkg.version_compare(source_pkg.version, bin_pkg.source_version) > 0:
src2bin.setdefault(bin_pkg.source, set())
src2bin[bin_pkg.source].add(bin_pkg.package)
for source in sorted(src2bin):
extra_info = {}
source_pkg = src_test[source]
new_bin = sorted(x for x in source_pkg.binaries - src2bin[source])
old_bin = sorted(x for x in src2bin[source] - source_pkg.binaries)
yield (source, source, new_bin, old_bin, stage, extra_info)
def transitions(src_test, bin_test, src_new, stage):
for source in sorted(src_test):
transition_name = source
test_bin = src_test[source].binaries
if source in src_new:
new_suite_bin = src_new[source].binaries
else:
transition_name = source + "-rm"
new_suite_bin = set()
if not any(y for x in test_bin if x in bin_test
for y in bin_test[x].reverse_depends
if y.package not in test_bin):
continue
if test_bin <= new_suite_bin:
continue
new_bin = sorted(x for x in new_suite_bin - test_bin)
old_bin = sorted(x for x in test_bin - new_suite_bin)
extra_info = {}
extra_info['can-smooth-update'] = 'maybe'
for old_pkg in old_bin:
if old_pkg not in bin_test:
# happens with udebs
continue
old_pkg_data = bin_test[old_pkg]
if old_pkg_data.section not in ('libs', 'oldlibs'):
if old_pkg_data.reverse_depends - test_bin:
extra_info['can-smooth-update'] = 'no - %s is not in libs or oldlibs' % old_pkg
elif extra_info['can-smooth-update'] == 'maybe':
extra_info['can-smooth-update'] = 'maybe (ignoring rdep-less binaries or/and intra-source-rdeps)'
yield (transition_name, source, new_bin, old_bin, stage, extra_info)
def find_existing_transitions(destdir):
transitions = {}
for stage in ("ongoing", "finished"):
stagedir = os.path.join(destdir, stage)
transitions[stage] = set()
for basename in os.listdir(stagedir):
if basename.endswith(".ben"):
transitions[stage].add(basename[:-4])
if basename.endswith("-rm.ben"):
transitions[stage].add(basename[:-7])
return transitions
if __name__ == "__main__":
apt_pkg.init()
seen = set()
mirror_test = PackageMirrorDist(sys.argv[1])
mirror_sid = PackageMirrorDist(sys.argv[2])
destdir = sys.argv[3]
src_test = read_sources(mirror_test)
src_sid = read_sources(mirror_sid)
bin_test = read_binaries(mirror_test)
compute_reverse_dependencies(bin_test)
possible_transitions = list(transitions(src_test, bin_test, src_sid, 'ongoing'))
possible_transitions.extend(find_nearly_finished_transitions(
src_test, bin_test, 'finished'))
existing_tranistions = find_existing_transitions(destdir)
possible_transitions = [x for x in possible_transitions
if x[0] not in existing_tranistions[x[4]] ]
if not possible_transitions:
exit(0)
bin_sid = read_binaries(mirror_sid)
compute_reverse_dependencies(bin_sid)
transition_data = {}
for transition_name, source, new_binaries, old_binaries, stage, extra_info in possible_transitions:
if not new_binaries and stage != 'finished' and transition_name == source:
continue
bin_suite = bin_sid
if stage == 'finished':
bin_suite = bin_test
if old_binaries and new_binaries:
old_has_rdeps = False
new_has_rdeps = False
for binary in old_binaries:
if binary_has_external_rdeps(source, binary, bin_suite):
old_has_rdeps = True
break
if not old_has_rdeps:
for binary in new_binaries:
if binary_has_external_rdeps(source, binary, bin_suite):
new_has_rdeps = True
break
if not old_has_rdeps and not new_has_rdeps:
# No rdeps seem affected, skip...
continue
if transition_name in seen:
# If there is a planned and an ongoing, focus on the
# ongoing transition. NB: We rely here on the order of
# possible_transition
continue
seen.add(transition_name)
if destdir:
output = as_ben_file(transition_name, new_binaries, old_binaries, extra_info)
filename = "auto-%s.ben" % transition_name
path = os.path.join(destdir, stage, filename)
with open(path, "w") as fd:
fd.write(output)