1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 from daklib.archive import ArchiveTransaction
20 from daklib.dbconn import *
21 import daklib.daklog
22 import daklib.utils
23
24 from sqlalchemy.orm.exc import NoResultFound
25 import sqlalchemy.sql as sql
26 import sys
27
28 """
29 Idea:
30
31 dak update-suite testing testing-kfreebsd
32 -> grab all source & binary packages from testing with a higher version
33 than in testing-kfreebsd (or not in -kfreebsd) and copy them
34 -> limited to architectures in testing-kfreebsd
35 -> obeys policy queues
36 -> copies to build queues
37
38 dak update-suite --create-in=ftp-master stable testing
39 -> create suite "testing" based on "stable" in archive "ftp-master"
40
41 Additional switches:
42 --skip-policy-queue: skip target suite's policy queue
43 --skip-build-queues: do not copy to build queue
44 --no-new-packages: do not copy new packages
45 -> source-based, new binaries from existing sources will be added
46 --only-new-packages: do not update existing packages
47 -> source-based, do not copy new binaries w/o source!
48 --also-policy-queue: also copy pending packages from policy queue
49 --update-overrides: update overrides as well (if different overrides are used)
50 --no-act
51 """
52
53
55 print("dak update-suite [-n|--no-act] <origin> <target>")
56 sys.exit(0)
57
58
60 - def __init__(self, transaction, origin, target,
61 new_packages=True, also_from_policy_queue=False,
62 obey_policy_queue=True, obey_build_queues=True,
63 update_overrides=False, dry_run=False):
64 self.transaction = transaction
65 self.origin = origin
66 self.target = target
67 self.new_packages = new_packages
68 self.also_from_policy_queue = also_from_policy_queue
69 self.obey_policy_queue = obey_policy_queue
70 self.obey_build_queues = obey_build_queues
71 self.update_overrides = update_overrides
72 self.dry_run = dry_run
73
74 if obey_policy_queue and target.policy_queue_id is not None:
75 raise Exception('Not implemented...')
76 self.logger = None if dry_run else daklib.daklog.Logger("update-suite")
77
79
80 query = """
81 SELECT b.*
82 FROM binaries b
83 JOIN bin_associations ba ON b.id = ba.bin AND ba.suite = :origin
84 """
85 if self.also_from_policy_queue:
86 query += """
87 UNION
88 SELECT b.*
89 FROM binaries b
90 JOIN policy_queue_upload_binaries_map pqubm ON pqubm.binary_id = b.id
91 JOIN policy_queue_upload pqu ON pqu.id = pqubm.policy_queue_upload_id
92 WHERE pqu.target_suite_id = :origin
93 AND pqu.policy_queue_id = (SELECT policy_queue_id FROM suite WHERE id = :origin)
94 """
95
96
97
98
99
100
101 if self.obey_policy_queue:
102 cond_source_in_policy_queue = """
103 EXISTS (SELECT 1
104 FROM policy_queue_upload pqu
105 WHERE tmp.source = pqu.source_id
106 AND pqu.target_suite_id = :target
107 AND pqu.policy_queue_id = (SELECT policy_queue_id FROM suite WHERE id = :target))
108 """
109 else:
110 cond_source_in_policy_queue = "FALSE"
111 query = """
112 WITH tmp AS ({0})
113 SELECT DISTINCT *
114 FROM tmp
115 WHERE tmp.architecture IN (SELECT architecture FROM suite_architectures WHERE suite = :target)
116 AND (tmp.source IN :additional_sources
117 OR EXISTS (SELECT 1
118 FROM src_associations sa
119 WHERE tmp.source = sa.source AND sa.suite = :target)
120 OR {1})
121 AND NOT EXISTS (SELECT 1
122 FROM binaries b2
123 JOIN bin_associations ba2 ON b2.id = ba2.bin AND ba2.suite = :target
124 WHERE tmp.package = b2.package AND tmp.architecture = b2.architecture AND b2.version >= tmp.version)
125 ORDER BY package, version, architecture
126 """.format(query, cond_source_in_policy_queue)
127
128
129
130
131 if len(additional_sources) == 0:
132 additional_sources = tuple([None])
133
134 params = {
135 'origin': self.origin.suite_id,
136 'target': self.target.suite_id,
137 'additional_sources': additional_sources,
138 }
139
140 return self.transaction.session.query(DBBinary).from_statement(sql.text(query)).params(params)
141
143
144 query = """
145 SELECT s.*
146 FROM source s
147 JOIN src_associations sa ON s.id = sa.source AND sa.suite = :origin
148 """
149 if self.also_from_policy_queue:
150 query += """
151 UNION
152 SELECT s.*
153 FROM source s
154 JOIN policy_queue_upload pqu ON pqu.source_id = s.id
155 WHERE pqu.target_suite_id = :origin
156 AND pqu.policy_queue_id = (SELECT policy_queue_id FROM suite WHERE id = :origin)
157 """
158
159
160 query = """
161 WITH tmp AS ({0})
162 SELECT DISTINCT *
163 FROM tmp
164 WHERE NOT EXISTS (SELECT 1
165 FROM source s2
166 JOIN src_associations sa2 ON s2.id = sa2.source AND sa2.suite = :target
167 WHERE s2.source = tmp.source AND s2.version >= tmp.version)
168 """.format(query)
169
170
171 if not self.new_packages:
172 query += """
173 AND EXISTS (SELECT 1
174 FROM source s2
175 JOIN src_associations sa2 ON s2.id = sa2.source AND sa2.suite = :target
176 WHERE s2.source = tmp.source)
177 """
178
179 query += "ORDER BY source, version"
180
181 params = {'origin': self.origin.suite_id, 'target': self.target.suite_id}
182
183 return self.transaction.session.query(DBSource).from_statement(sql.text(query)).params(params)
184
186 session = self.transaction.session
187 return session.query(Component) \
188 .join(ArchiveFile, Component.component_id == ArchiveFile.component_id) \
189 .join(ArchiveFile.file).filter(PoolFile.file_id == binary.poolfile_id) \
190 .filter(ArchiveFile.archive_id == suite.archive_id)
191
193 if len(binaries) == 0:
194 return
195
196
197 if self.origin.archive_id == suite.archive_id:
198 query = "INSERT INTO bin_associations (bin, suite) VALUES (:bin, :suite)"
199 target_id = suite.suite_id
200 params = [{'bin': b.binary_id, 'suite': target_id} for b in binaries]
201 self.transaction.session.execute(query, params)
202 else:
203 for b in binaries:
204 for c in self._components_for_binary(b, suite):
205 self.transaction.copy_binary(b, suite, c)
206
208 session = self.transaction.session
209 return session.query(Component) \
210 .join(ArchiveFile, Component.component_id == ArchiveFile.component_id) \
211 .join(ArchiveFile.file).filter(PoolFile.file_id == source.poolfile_id) \
212 .filter(ArchiveFile.archive_id == suite.archive_id)
213
215 if len(sources) == 0:
216 return
217
218
219 if self.origin.archive_id == suite.archive_id:
220 query = "INSERT INTO src_associations (source, suite) VALUES (:source, :suite)"
221 target_id = suite.suite_id
222 params = [{'source': s.source_id, 'suite': target_id} for s in sources]
223 self.transaction.session.execute(query, params)
224 else:
225 for s in sources:
226 for c in self._components_for_source(s, suite):
227 self.transaction.copy_source(s, suite, c)
228
230 targets = set([self.target])
231 if self.obey_build_queues:
232 targets.update([bq.suite for bq in self.target.copy_queues])
233 target_names = sorted(s.suite_name for s in targets)
234 target_name = ",".join(target_names)
235
236 new_sources = self.query_new_sources().all()
237 additional_sources = tuple(s.source_id for s in new_sources)
238 for s in new_sources:
239 self.log(["add-source", target_name, s.source, s.version])
240 if not self.dry_run:
241 for target in targets:
242 self.install_sources(new_sources, target)
243
244 new_binaries = self.query_new_binaries(additional_sources).all()
245 for b in new_binaries:
246 self.log(["add-binary", target_name, b.package, b.version, b.architecture.arch_string])
247 if not self.dry_run:
248 for target in targets:
249 self.install_binaries(new_binaries, target)
250
251 - def log(self, args):
252 if self.logger:
253 self.logger.log(args)
254 else:
255 print(args)
256
257
259 from daklib.config import Config
260 config = Config()
261
262 import apt_pkg
263 arguments = [
264 ('h', 'help', 'Update-Suite::Options::Help'),
265 ('n', 'no-act', 'Update-Suite::options::NoAct'),
266 ]
267 argv = apt_pkg.parse_commandline(config.Cnf, arguments, sys.argv)
268 try:
269 options = config.subtree("Update-Suite::Options")
270 except KeyError:
271 options = {}
272
273 if 'Help' in options or len(argv) != 2:
274 usage()
275
276 origin_name = argv[0]
277 target_name = argv[1]
278 dry_run = True if 'NoAct' in options else False
279
280 with ArchiveTransaction() as transaction:
281 session = transaction.session
282
283 try:
284 origin = session.query(Suite).filter_by(suite_name=origin_name).one()
285 except NoResultFound:
286 daklib.utils.fubar("Origin suite '{0}' is unknown.".format(origin_name))
287 try:
288 target = session.query(Suite).filter_by(suite_name=target_name).one()
289 except NoResultFound:
290 daklib.utils.fubar("Target suite '{0}' is unknown.".format(target_name))
291
292 su = SuiteUpdater(transaction, origin, target, dry_run=dry_run)
293 su.update_suite()
294
295 if dry_run:
296 transaction.rollback()
297 else:
298 transaction.commit()
299
300
301 if __name__ == '__main__':
302 pass
303