3 """ Cruft checker and hole filler for overrides """
4 # Copyright (C) 2000, 2001, 2002, 2004, 2006 James Troup <james@nocrew.org>
5 # Copyright (C) 2005 Jeroen van Wolffelaar <jeroen@wolffelaar.nl>
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 ################################################################################
23 ######################################################################
24 # NB: dak check-overrides is not a good idea with New Incoming as it #
25 # doesn't take into account accepted. You can minimize the impact #
26 # of this by running it immediately after dak process-accepted but #
27 # that's still racy because 'dak process-new' doesn't lock with 'dak #
28 # process-accepted'. A better long term fix is the evil plan for #
29 # accepted to be in the DB. #
30 ######################################################################
32 # dak check-overrides should now work fine being done during
33 # cron.daily, for example just before 'dak make-overrides' (after 'dak
34 # process-accepted' and 'dak make-suite-file-list'). At that point,
35 # queue/accepted should be empty and installed, so... dak
36 # check-overrides does now take into account suites sharing overrides
39 # * Only update out-of-sync overrides when corresponding versions are equal to
41 # * consistency checks like:
42 # - section=debian-installer only for udeb and # dsc
43 # - priority=source iff dsc
44 # - (suite, package, 'dsc') is unique,
45 # - just as (suite, package, (u)deb) (yes, across components!)
46 # - sections match their component (each component has an own set of sections,
47 # could probably be reduced...)
49 ################################################################################
54 from daklib.config import Config
55 from daklib.dbconn import *
56 from daklib import daklog
57 from daklib import utils
59 ################################################################################
67 ################################################################################
69 def usage (exit_code=0):
70 print """Usage: dak check-overrides
71 Check for cruft in overrides.
73 -n, --no-action don't do anything
74 -h, --help show this help and exit"""
78 ################################################################################
80 def gen_blacklist(dir):
81 for entry in os.listdir(dir):
82 entry = entry.split('_')[0]
85 def process(osuite, affected_suites, originosuite, component, otype, session):
86 global Logger, Options, sections, priorities
88 o = get_suite(osuite, session)
90 utils.fubar("Suite '%s' not recognised." % (osuite))
91 osuite_id = o.suite_id
93 originosuite_id = None
95 oo = get_suite(originosuite, session)
97 utils.fubar("Suite '%s' not recognised." % (originosuite))
98 originosuite_id = oo.suite_id
100 c = get_component(component, session)
102 utils.fubar("Component '%s' not recognised." % (component))
103 component_id = c.component_id
105 ot = get_override_type(otype, session)
107 utils.fubar("Type '%s' not recognised. (Valid types are deb, udeb and dsc)" % (otype))
108 type_id = ot.overridetype_id
109 dsc_type_id = get_override_type("dsc", session).overridetype_id
111 source_priority_id = get_priority("source", session).priority_id
113 if otype == "deb" or otype == "udeb":
115 # TODO: Fix to use placeholders (check how to with arrays)
116 q = session.execute("""
117 SELECT b.package FROM binaries b, bin_associations ba, files f,
118 location l, component c
119 WHERE b.type = :otype AND b.id = ba.bin AND f.id = b.file AND l.id = f.location
120 AND c.id = l.component AND ba.suite IN (%s) AND c.id = :component_id
121 """ % (",".join([ str(i) for i in affected_suites ])), {'otype': otype, 'component_id': component_id})
122 for i in q.fetchall():
126 q = session.execute("""
127 SELECT s.source FROM source s, src_associations sa, files f, location l,
129 WHERE s.id = sa.source AND f.id = s.file AND l.id = f.location
130 AND c.id = l.component AND sa.suite IN (%s) AND c.id = :component_id
131 """ % (",".join([ str(i) for i in affected_suites])), {'component_id': component_id})
132 for i in q.fetchall():
133 src_packages[i[0]] = 0
136 # Drop unused overrides
138 q = session.execute("""SELECT package, priority, section, maintainer
139 FROM override WHERE suite = :suite_id
140 AND component = :component_id AND type = :type_id""",
141 {'suite_id': osuite_id, 'component_id': component_id,
143 # We're already within a transaction
145 for i in q.fetchall():
147 if src_packages.has_key(package):
148 src_packages[package] = 1
150 if blacklist.has_key(package):
151 utils.warn("%s in incoming, not touching" % package)
153 Logger.log(["removing unused override", osuite, component,
154 otype, package, priorities[i[1]], sections[i[2]], i[3]])
155 if not Options["No-Action"]:
156 session.execute("""DELETE FROM override WHERE package = :package
157 AND suite = :suite_id AND component = :component_id
158 AND type = :type_id""",
159 {'package': package, 'suite_id': osuite_id,
160 'component_id': component_id, 'type_id': type_id})
161 # create source overrides based on binary overrides, as source
162 # overrides not always get created
163 q = session.execute("""SELECT package, priority, section, maintainer
164 FROM override WHERE suite = :suite_id AND component = :component_id""",
165 {'suite_id': osuite_id, 'component_id': component_id})
166 for i in q.fetchall():
168 if not src_packages.has_key(package) or src_packages[package]:
170 src_packages[package] = 1
172 Logger.log(["add missing override", osuite, component,
173 otype, package, "source", sections[i[2]], i[3]])
174 if not Options["No-Action"]:
175 session.execute("""INSERT INTO override (package, suite, component,
176 priority, section, type, maintainer)
177 VALUES (:package, :suite_id, :component_id,
178 :priority_id, :section_id, :type_id, :maintainer)""",
179 {'package': package, 'suite_id': osuite_id,
180 'component_id': component_id, 'priority_id': source_priority_id,
181 'section_id': i[2], 'type_id': dsc_type_id, 'maintainer': i[3]})
182 # Check whether originosuite has an override for us we can
185 q = session.execute("""SELECT origin.package, origin.priority, origin.section,
186 origin.maintainer, target.priority, target.section,
189 LEFT JOIN override target ON (origin.package = target.package
190 AND target.suite = :suite_id
191 AND origin.component = target.component
192 AND origin.type = target.type)
193 WHERE origin.suite = :originsuite_id
194 AND origin.component = :component_id
195 AND origin.type = :type_id""",
196 {'suite_id': osuite_id, 'originsuite_id': originosuite_id,
197 'component_id': component_id, 'type_id': type_id})
198 for i in q.fetchall():
200 if not src_packages.has_key(package) or src_packages[package]:
201 if i[4] and (i[1] != i[4] or i[2] != i[5] or i[3] != i[6]):
202 Logger.log(["syncing override", osuite, component,
203 otype, package, "source", sections[i[5]], i[6], "source", sections[i[2]], i[3]])
204 if not Options["No-Action"]:
205 session.execute("""UPDATE override
206 SET section = :section,
207 maintainer = :maintainer
208 WHERE package = :package AND suite = :suite_id
209 AND component = :component_id AND type = :type_id""",
210 {'section': i[2], 'maintainer': i[3],
211 'package': package, 'suite_id': osuite_id,
212 'component_id': component_id, 'type_id': dsc_type_id})
216 src_packages[package] = 1
217 Logger.log(["copying missing override", osuite, component,
218 otype, package, "source", sections[i[2]], i[3]])
219 if not Options["No-Action"]:
220 session.execute("""INSERT INTO override (package, suite, component,
221 priority, section, type, maintainer)
222 VALUES (:package, :suite_id, :component_id,
223 :priority_id, :section_id, :type_id,
225 {'package': package, 'suite_id': osuite_id,
226 'component_id': component_id, 'priority_id': source_priority_id,
227 'section_id': i[2], 'type_id': dsc_type_id, 'maintainer': i[3]})
229 for package, hasoverride in src_packages.items():
231 utils.warn("%s has no override!" % package)
233 else: # binary override
234 for i in q.fetchall():
236 if packages.has_key(package):
237 packages[package] = 1
239 if blacklist.has_key(package):
240 utils.warn("%s in incoming, not touching" % package)
242 Logger.log(["removing unused override", osuite, component,
243 otype, package, priorities[i[1]], sections[i[2]], i[3]])
244 if not Options["No-Action"]:
245 session.execute("""DELETE FROM override
246 WHERE package = :package AND suite = :suite_id
247 AND component = :component_id AND type = :type_id""",
248 {'package': package, 'suite_id': osuite_id,
249 'component_id': component_id, 'type_id': type_id})
251 # Check whether originosuite has an override for us we can
254 q = session.execute("""SELECT origin.package, origin.priority, origin.section,
255 origin.maintainer, target.priority, target.section,
257 FROM override origin LEFT JOIN override target
258 ON (origin.package = target.package
259 AND target.suite = :suite_id
260 AND origin.component = target.component
261 AND origin.type = target.type)
262 WHERE origin.suite = :originsuite_id
263 AND origin.component = :component_id
264 AND origin.type = :type_id""",
265 {'suite_id': osuite_id, 'originsuite_id': originosuite_id,
266 'component_id': component_id, 'type_id': type_id})
267 for i in q.fetchall():
269 if not packages.has_key(package) or packages[package]:
270 if i[4] and (i[1] != i[4] or i[2] != i[5] or i[3] != i[6]):
271 Logger.log(["syncing override", osuite, component,
272 otype, package, priorities[i[4]], sections[i[5]],
273 i[6], priorities[i[1]], sections[i[2]], i[3]])
274 if not Options["No-Action"]:
275 session.execute("""UPDATE override
276 SET priority = :priority_id,
277 section = :section_id,
278 maintainer = :maintainer
279 WHERE package = :package
280 AND suite = :suite_id
281 AND component = :component_id
282 AND type = :type_id""",
283 {'priority_id': i[1], 'section_id': i[2],
284 'maintainer': i[3], 'package': package,
285 'suite_id': osuite_id, 'component_id': component_id,
289 packages[package] = 1
290 Logger.log(["copying missing override", osuite, component,
291 type, package, priorities[i[1]], sections[i[2]], i[3]])
292 if not Options["No-Action"]:
293 session.execute("""INSERT INTO override (package, suite, component,
294 priority, section, type, maintainer)
295 VALUES (:package, :suite_id, :component_id,
296 :priority_id, :section_id, :type_id, :maintainer)""",
297 {'package': package, 'suite_id': osuite_id,
298 'component_id': component_id, 'priority_id': i[1],
299 'section_id': i[2], 'type_id': type_id, 'maintainer': i[3]})
301 for package, hasoverride in packages.items():
303 utils.warn("%s has no override!" % package)
309 ################################################################################
312 global Logger, Options, sections, priorities
316 Arguments = [('h',"help","Check-Overrides::Options::Help"),
317 ('n',"no-action", "Check-Overrides::Options::No-Action")]
318 for i in [ "help", "no-action" ]:
319 if not cnf.has_key("Check-Overrides::Options::%s" % (i)):
320 cnf["Check-Overrides::Options::%s" % (i)] = ""
321 apt_pkg.ParseCommandLine(cnf.Cnf, Arguments, sys.argv)
322 Options = cnf.SubTree("Check-Overrides::Options")
327 session = DBConn().session()
329 # init sections, priorities:
331 # We need forward and reverse
332 sections = get_sections(session)
333 for name, entry in sections.items():
334 sections[entry] = name
336 priorities = get_priorities(session)
337 for name, entry in priorities.items():
338 priorities[entry] = name
340 if not Options["No-Action"]:
341 Logger = daklog.Logger(cnf, "check-overrides")
343 Logger = daklog.Logger(cnf, "check-overrides", 1)
345 gen_blacklist(cnf["Dir::Queue::Accepted"])
347 for osuite in cnf.SubTree("Check-Overrides::OverrideSuites").List():
348 if "1" != cnf["Check-Overrides::OverrideSuites::%s::Process" % osuite]:
351 osuite = osuite.lower()
356 originosuite = cnf["Check-Overrides::OverrideSuites::%s::OriginSuite" % osuite]
357 originosuite = originosuite.lower()
358 originremark = " taking missing from %s" % originosuite
362 print "Processing %s%s..." % (osuite, originremark)
363 # Get a list of all suites that use the override file of 'osuite'
364 ocodename = cnf["Suite::%s::codename" % osuite].lower()
367 for suite in cnf.SubTree("Suite").List():
368 if ocodename == cnf["Suite::%s::OverrideCodeName" % suite].lower():
370 s = get_suite(suite.lower(), session)
372 suiteids.append(s.suite_id)
374 if len(suiteids) != len(suites) or len(suiteids) < 1:
375 utils.fubar("Couldn't find id's of all suites: %s" % suites)
377 for component in cnf.SubTree("Component").List():
378 # It is crucial for the dsc override creation based on binary
379 # overrides that 'dsc' goes first
380 otypes = cnf.ValueList("OverrideType")
382 otypes = ["dsc"] + otypes
384 print "Processing %s [%s - %s] using %s..." \
385 % (osuite, component, otype, suites)
387 process(osuite, suiteids, originosuite, component, otype, session)
391 ################################################################################
393 if __name__ == '__main__':