Package dak :: Module control_overrides
[hide private]
[frames] | no frames]

Source Code for Module dak.control_overrides

  1  #! /usr/bin/env python3 
  2   
  3  """Bulk manipulation of the overrides""" 
  4  # Copyright (C) 2000, 2001, 2002, 2003, 2006  James Troup <james@nocrew.org> 
  5   
  6  # This program is free software; you can redistribute it and/or modify 
  7  # it under the terms of the GNU General Public License as published by 
  8  # the Free Software Foundation; either version 2 of the License, or 
  9  # (at your option) any later version. 
 10   
 11  # This program is distributed in the hope that it will be useful, 
 12  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 13  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 14  # GNU General Public License for more details. 
 15   
 16  # You should have received a copy of the GNU General Public License 
 17  # along with this program; if not, write to the Free Software 
 18  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 19   
 20  ################################################################################ 
 21   
 22  # On 30 Nov 1998, James Troup wrote: 
 23  # 
 24  # > James Troup<2> <troup2@debian.org> 
 25  # > 
 26  # >    James is a clone of James; he's going to take over the world. 
 27  # >    After he gets some sleep. 
 28  # 
 29  # Could you clone other things too? Sheep? Llamas? Giant mutant turnips? 
 30  # 
 31  # Your clone will need some help to take over the world, maybe clone up an 
 32  # army of penguins and threaten to unleash them on the world, forcing 
 33  # governments to sway to the new James' will! 
 34  # 
 35  # Yes, I can envision a day when James' duplicate decides to take a horrific 
 36  # vengance on the James that spawned him and unleashes his fury in the form 
 37  # of thousands upon thousands of chickens that look just like Captin Blue 
 38  # Eye! Oh the horror. 
 39  # 
 40  # Now you'll have to were name tags to people can tell you apart, unless of 
 41  # course the new clone is truely evil in which case he should be easy to 
 42  # identify! 
 43  # 
 44  # Jason 
 45  # Chicken. Black. Helicopters. 
 46  # Be afraid. 
 47   
 48  # <Pine.LNX.3.96.981130011300.30365Z-100000@wakko> 
 49   
 50  ################################################################################ 
 51   
 52  import sys 
 53  import time 
 54   
 55  import apt_pkg 
 56   
 57  from daklib import daklog, utils 
 58  from daklib.config import Config 
 59  from daklib.dbconn import ( 
 60      DBConn, 
 61      get_component, 
 62      get_override_type, 
 63      get_priorities, 
 64      get_sections, 
 65      get_suite, 
 66  ) 
 67  from daklib.regexes import re_comments 
 68   
 69  ################################################################################ 
 70   
 71  Logger = None 
 72   
 73  ################################################################################ 
 74   
 75   
76 -def usage(exit_code=0):
77 print( 78 """Usage: dak control-overrides [OPTIONS] 79 -h, --help print this help and exit 80 81 -c, --component=CMPT list/set overrides by component 82 (contrib,*main,non-free) 83 -s, --suite=SUITE list/set overrides by suite 84 (experimental,stable,testing,*unstable) 85 -t, --type=TYPE list/set overrides by type 86 (*deb,dsc,udeb) 87 88 -a, --add add overrides (changes and deletions are ignored) 89 -S, --set set overrides 90 -C, --change change overrides (additions and deletions are ignored) 91 -l, --list list overrides 92 93 -q, --quiet be less verbose 94 -n, --no-action only list the action that would have been done 95 96 starred (*) values are default""" 97 ) 98 sys.exit(exit_code)
99 100 101 ################################################################################ 102 103
104 -def process_file(file, suite, component, otype, mode, action, session):
105 cnf = Config() 106 107 s = get_suite(suite, session=session) 108 if s is None: 109 utils.fubar("Suite '%s' not recognised." % (suite)) 110 suite_id = s.suite_id 111 112 c = get_component(component, session=session) 113 if c is None: 114 utils.fubar("Component '%s' not recognised." % (component)) 115 component_id = c.component_id 116 117 o = get_override_type(otype) 118 if o is None: 119 utils.fubar( 120 "Type '%s' not recognised. (Valid types are deb, udeb and dsc.)" % (otype) 121 ) 122 type_id = o.overridetype_id 123 124 # --set is done mostly internal for performance reasons; most 125 # invocations of --set will be updates and making people wait 2-3 126 # minutes while 6000 select+inserts are run needlessly isn't cool. 127 128 original = {} 129 new = {} 130 c_skipped = 0 131 c_added = 0 132 c_updated = 0 133 c_removed = 0 134 c_error = 0 135 136 q = session.execute( 137 """SELECT o.package, o.priority, o.section, o.maintainer, p.priority, s.section 138 FROM override o, priority p, section s 139 WHERE o.suite = :suiteid AND o.component = :componentid AND o.type = :typeid 140 and o.priority = p.id and o.section = s.id""", 141 {"suiteid": suite_id, "componentid": component_id, "typeid": type_id}, 142 ) 143 for i in q.fetchall(): 144 original[i[0]] = i[1:] 145 146 start_time = time.time() 147 148 section_cache = get_sections(session) 149 priority_cache = get_priorities(session) 150 151 # Our session is already in a transaction 152 153 for line in file.readlines(): 154 line = re_comments.sub("", line).strip() 155 if line == "": 156 continue 157 158 maintainer_override = None 159 if otype == "dsc": 160 split_line = line.split(None, 2) 161 if len(split_line) == 2: 162 (package, section) = split_line 163 elif len(split_line) == 3: 164 (package, section, maintainer_override) = split_line 165 else: 166 utils.warn( 167 "'%s' does not break into 'package section [maintainer-override]'." 168 % (line) 169 ) 170 c_error += 1 171 continue 172 priority = "optional" 173 else: # binary or udeb 174 split_line = line.split(None, 3) 175 if len(split_line) == 3: 176 (package, priority, section) = split_line 177 elif len(split_line) == 4: 178 (package, priority, section, maintainer_override) = split_line 179 else: 180 utils.warn( 181 "'%s' does not break into 'package priority section [maintainer-override]'." 182 % (line) 183 ) 184 c_error += 1 185 continue 186 187 if section not in section_cache: 188 utils.warn( 189 "'%s' is not a valid section. ['%s' in suite %s, component %s]." 190 % (section, package, suite, component) 191 ) 192 c_error += 1 193 continue 194 195 section_id = section_cache[section] 196 197 if priority not in priority_cache: 198 utils.warn( 199 "'%s' is not a valid priority. ['%s' in suite %s, component %s]." 200 % (priority, package, suite, component) 201 ) 202 c_error += 1 203 continue 204 205 priority_id = priority_cache[priority] 206 207 if package in new: 208 utils.warn( 209 "Can't insert duplicate entry for '%s'; ignoring all but the first. [suite %s, component %s]" 210 % (package, suite, component) 211 ) 212 c_error += 1 213 continue 214 new[package] = "" 215 216 if package in original: 217 ( 218 old_priority_id, 219 old_section_id, 220 old_maintainer_override, 221 old_priority, 222 old_section, 223 ) = original[package] 224 if ( 225 mode == "add" 226 or old_priority_id == priority_id 227 and old_section_id == section_id 228 and old_maintainer_override == maintainer_override 229 ): 230 # If it's unchanged or we're in 'add only' mode, ignore it 231 c_skipped += 1 232 continue 233 else: 234 # If it's changed, delete the old one so we can 235 # reinsert it with the new information 236 c_updated += 1 237 if action: 238 session.execute( 239 """DELETE FROM override WHERE suite = :suite AND component = :component 240 AND package = :package AND type = :typeid""", 241 { 242 "suite": suite_id, 243 "component": component_id, 244 "package": package, 245 "typeid": type_id, 246 }, 247 ) 248 249 # Log changes 250 if old_priority_id != priority_id: 251 Logger.log(["changed priority", package, old_priority, priority]) 252 if old_section_id != section_id: 253 Logger.log(["changed section", package, old_section, section]) 254 if old_maintainer_override != maintainer_override: 255 Logger.log( 256 [ 257 "changed maintainer override", 258 package, 259 old_maintainer_override, 260 maintainer_override, 261 ] 262 ) 263 update_p = 1 264 elif mode == "change": 265 # Ignore additions in 'change only' mode 266 c_skipped += 1 267 continue 268 else: 269 c_added += 1 270 update_p = 0 271 272 if action: 273 if not maintainer_override: 274 m_o = None 275 else: 276 m_o = maintainer_override 277 session.execute( 278 """INSERT INTO override (suite, component, type, package, 279 priority, section, maintainer) 280 VALUES (:suiteid, :componentid, :typeid, 281 :package, :priorityid, :sectionid, 282 :maintainer)""", 283 { 284 "suiteid": suite_id, 285 "componentid": component_id, 286 "typeid": type_id, 287 "package": package, 288 "priorityid": priority_id, 289 "sectionid": section_id, 290 "maintainer": m_o, 291 }, 292 ) 293 294 if not update_p: 295 Logger.log( 296 [ 297 "new override", 298 suite, 299 component, 300 otype, 301 package, 302 priority, 303 section, 304 maintainer_override, 305 ] 306 ) 307 308 if mode == "set": 309 # Delete any packages which were removed 310 for package in original.keys(): 311 if package not in new: 312 if action: 313 session.execute( 314 """DELETE FROM override 315 WHERE suite = :suiteid AND component = :componentid 316 AND package = :package AND type = :typeid""", 317 { 318 "suiteid": suite_id, 319 "componentid": component_id, 320 "package": package, 321 "typeid": type_id, 322 }, 323 ) 324 c_removed += 1 325 Logger.log(["removed override", suite, component, otype, package]) 326 327 if action: 328 session.commit() 329 330 if not cnf["Control-Overrides::Options::Quiet"]: 331 print( 332 "Done in %d seconds. [Updated = %d, Added = %d, Removed = %d, Skipped = %d, Errors = %d]" 333 % ( 334 int(time.time() - start_time), 335 c_updated, 336 c_added, 337 c_removed, 338 c_skipped, 339 c_error, 340 ) 341 ) 342 343 Logger.log(["set complete", c_updated, c_added, c_removed, c_skipped, c_error])
344 345 346 ################################################################################ 347 348
349 -def list_overrides(suite, component, otype, session):
350 dat = {} 351 s = get_suite(suite, session) 352 if s is None: 353 utils.fubar("Suite '%s' not recognised." % (suite)) 354 355 dat["suiteid"] = s.suite_id 356 357 c = get_component(component, session) 358 if c is None: 359 utils.fubar("Component '%s' not recognised." % (component)) 360 361 dat["componentid"] = c.component_id 362 363 o = get_override_type(otype) 364 if o is None: 365 utils.fubar( 366 "Type '%s' not recognised. (Valid types are deb, udeb and dsc)" % (otype) 367 ) 368 369 dat["typeid"] = o.overridetype_id 370 371 if otype == "dsc": 372 q = session.execute( 373 """SELECT o.package, s.section, o.maintainer FROM override o, section s 374 WHERE o.suite = :suiteid AND o.component = :componentid 375 AND o.type = :typeid AND o.section = s.id 376 ORDER BY s.section, o.package""", 377 dat, 378 ) 379 for i in q.fetchall(): 380 print(utils.result_join(i)) 381 else: 382 q = session.execute( 383 """SELECT o.package, p.priority, s.section, o.maintainer, p.level 384 FROM override o, priority p, section s 385 WHERE o.suite = :suiteid AND o.component = :componentid 386 AND o.type = :typeid AND o.priority = p.id AND o.section = s.id 387 ORDER BY s.section, p.level, o.package""", 388 dat, 389 ) 390 for i in q.fetchall(): 391 print(utils.result_join(i[:-1]))
392 393 394 ################################################################################ 395 396
397 -def main():
398 global Logger 399 400 cnf = Config() 401 Arguments = [ 402 ("a", "add", "Control-Overrides::Options::Add"), 403 ("c", "component", "Control-Overrides::Options::Component", "HasArg"), 404 ("h", "help", "Control-Overrides::Options::Help"), 405 ("l", "list", "Control-Overrides::Options::List"), 406 ("q", "quiet", "Control-Overrides::Options::Quiet"), 407 ("s", "suite", "Control-Overrides::Options::Suite", "HasArg"), 408 ("S", "set", "Control-Overrides::Options::Set"), 409 ("C", "change", "Control-Overrides::Options::Change"), 410 ("n", "no-action", "Control-Overrides::Options::No-Action"), 411 ("t", "type", "Control-Overrides::Options::Type", "HasArg"), 412 ] 413 414 # Default arguments 415 for i in ["add", "help", "list", "quiet", "set", "change", "no-action"]: 416 key = "Control-Overrides::Options::%s" % i 417 if key not in cnf: 418 cnf[key] = "" 419 if "Control-Overrides::Options::Component" not in cnf: 420 cnf["Control-Overrides::Options::Component"] = "main" 421 if "Control-Overrides::Options::Suite" not in cnf: 422 cnf["Control-Overrides::Options::Suite"] = "unstable" 423 if "Control-Overrides::Options::Type" not in cnf: 424 cnf["Control-Overrides::Options::Type"] = "deb" 425 426 file_list = apt_pkg.parse_commandline(cnf.Cnf, Arguments, sys.argv) 427 428 if cnf["Control-Overrides::Options::Help"]: 429 usage() 430 431 session = DBConn().session() 432 433 mode = None 434 for i in ["add", "list", "set", "change"]: 435 if cnf["Control-Overrides::Options::%s" % (i)]: 436 if mode: 437 utils.fubar("Can not perform more than one action at once.") 438 mode = i 439 440 # Need an action... 441 if mode is None: 442 utils.fubar("No action specified.") 443 444 (suite, component, otype) = ( 445 cnf["Control-Overrides::Options::Suite"], 446 cnf["Control-Overrides::Options::Component"], 447 cnf["Control-Overrides::Options::Type"], 448 ) 449 450 if mode == "list": 451 list_overrides(suite, component, otype, session) 452 else: 453 if get_suite(suite).untouchable: 454 utils.fubar("%s: suite is untouchable" % suite) 455 456 action = True 457 if cnf["Control-Overrides::Options::No-Action"]: 458 utils.warn("In No-Action Mode") 459 action = False 460 461 Logger = daklog.Logger("control-overrides", mode) 462 if file_list: 463 for f in file_list: 464 process_file(open(f), suite, component, otype, mode, action, session) 465 else: 466 process_file(sys.stdin, suite, component, otype, mode, action, session) 467 Logger.close()
468 469 470 ####################################################################################### 471 472 473 if __name__ == "__main__": 474 main() 475