Source code for dak.control_overrides

#! /usr/bin/env python3

""" Bulk manipulation of the overrides """
# Copyright (C) 2000, 2001, 2002, 2003, 2006  James Troup <james@nocrew.org>

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

################################################################################

# On 30 Nov 1998, James Troup wrote:
#
# > James Troup<2> <troup2@debian.org>
# >
# >    James is a clone of James; he's going to take over the world.
# >    After he gets some sleep.
#
# Could you clone other things too? Sheep? Llamas? Giant mutant turnips?
#
# Your clone will need some help to take over the world, maybe clone up an
# army of penguins and threaten to unleash them on the world, forcing
# governments to sway to the new James' will!
#
# Yes, I can envision a day when James' duplicate decides to take a horrific
# vengance on the James that spawned him and unleashes his fury in the form
# of thousands upon thousands of chickens that look just like Captin Blue
# Eye! Oh the horror.
#
# Now you'll have to were name tags to people can tell you apart, unless of
# course the new clone is truely evil in which case he should be easy to
# identify!
#
# Jason
# Chicken. Black. Helicopters.
# Be afraid.

# <Pine.LNX.3.96.981130011300.30365Z-100000@wakko>

################################################################################

import sys
import time
import apt_pkg

from daklib.dbconn import *
from daklib.config import Config
from daklib import utils
from daklib import daklog
from daklib.regexes import re_comments

################################################################################

Logger = None

################################################################################


[docs]def usage(exit_code=0): print("""Usage: dak control-overrides [OPTIONS] -h, --help print this help and exit -c, --component=CMPT list/set overrides by component (contrib,*main,non-free) -s, --suite=SUITE list/set overrides by suite (experimental,stable,testing,*unstable) -t, --type=TYPE list/set overrides by type (*deb,dsc,udeb) -a, --add add overrides (changes and deletions are ignored) -S, --set set overrides -C, --change change overrides (additions and deletions are ignored) -l, --list list overrides -q, --quiet be less verbose -n, --no-action only list the action that would have been done starred (*) values are default""") sys.exit(exit_code)
################################################################################
[docs]def process_file(file, suite, component, otype, mode, action, session): cnf = Config() s = get_suite(suite, session=session) if s is None: utils.fubar("Suite '%s' not recognised." % (suite)) suite_id = s.suite_id c = get_component(component, session=session) if c is None: utils.fubar("Component '%s' not recognised." % (component)) component_id = c.component_id o = get_override_type(otype) if o is None: utils.fubar("Type '%s' not recognised. (Valid types are deb, udeb and dsc.)" % (otype)) type_id = o.overridetype_id # --set is done mostly internal for performance reasons; most # invocations of --set will be updates and making people wait 2-3 # minutes while 6000 select+inserts are run needlessly isn't cool. original = {} new = {} c_skipped = 0 c_added = 0 c_updated = 0 c_removed = 0 c_error = 0 q = session.execute("""SELECT o.package, o.priority, o.section, o.maintainer, p.priority, s.section FROM override o, priority p, section s WHERE o.suite = :suiteid AND o.component = :componentid AND o.type = :typeid and o.priority = p.id and o.section = s.id""", {'suiteid': suite_id, 'componentid': component_id, 'typeid': type_id}) for i in q.fetchall(): original[i[0]] = i[1:] start_time = time.time() section_cache = get_sections(session) priority_cache = get_priorities(session) # Our session is already in a transaction for line in file.readlines(): line = re_comments.sub('', line).strip() if line == "": continue maintainer_override = None if otype == "dsc": split_line = line.split(None, 2) if len(split_line) == 2: (package, section) = split_line elif len(split_line) == 3: (package, section, maintainer_override) = split_line else: utils.warn("'%s' does not break into 'package section [maintainer-override]'." % (line)) c_error += 1 continue priority = "optional" else: # binary or udeb split_line = line.split(None, 3) if len(split_line) == 3: (package, priority, section) = split_line elif len(split_line) == 4: (package, priority, section, maintainer_override) = split_line else: utils.warn("'%s' does not break into 'package priority section [maintainer-override]'." % (line)) c_error += 1 continue if section not in section_cache: utils.warn("'%s' is not a valid section. ['%s' in suite %s, component %s]." % (section, package, suite, component)) c_error += 1 continue section_id = section_cache[section] if priority not in priority_cache: utils.warn("'%s' is not a valid priority. ['%s' in suite %s, component %s]." % (priority, package, suite, component)) c_error += 1 continue priority_id = priority_cache[priority] if package in new: utils.warn("Can't insert duplicate entry for '%s'; ignoring all but the first. [suite %s, component %s]" % (package, suite, component)) c_error += 1 continue new[package] = "" if package in original: (old_priority_id, old_section_id, old_maintainer_override, old_priority, old_section) = original[package] if mode == "add" or old_priority_id == priority_id and \ old_section_id == section_id and \ old_maintainer_override == maintainer_override: # If it's unchanged or we're in 'add only' mode, ignore it c_skipped += 1 continue else: # If it's changed, delete the old one so we can # reinsert it with the new information c_updated += 1 if action: session.execute("""DELETE FROM override WHERE suite = :suite AND component = :component AND package = :package AND type = :typeid""", {'suite': suite_id, 'component': component_id, 'package': package, 'typeid': type_id}) # Log changes if old_priority_id != priority_id: Logger.log(["changed priority", package, old_priority, priority]) if old_section_id != section_id: Logger.log(["changed section", package, old_section, section]) if old_maintainer_override != maintainer_override: Logger.log(["changed maintainer override", package, old_maintainer_override, maintainer_override]) update_p = 1 elif mode == "change": # Ignore additions in 'change only' mode c_skipped += 1 continue else: c_added += 1 update_p = 0 if action: if not maintainer_override: m_o = None else: m_o = maintainer_override session.execute("""INSERT INTO override (suite, component, type, package, priority, section, maintainer) VALUES (:suiteid, :componentid, :typeid, :package, :priorityid, :sectionid, :maintainer)""", {'suiteid': suite_id, 'componentid': component_id, 'typeid': type_id, 'package': package, 'priorityid': priority_id, 'sectionid': section_id, 'maintainer': m_o}) if not update_p: Logger.log(["new override", suite, component, otype, package, priority, section, maintainer_override]) if mode == "set": # Delete any packages which were removed for package in original.keys(): if package not in new: if action: session.execute("""DELETE FROM override WHERE suite = :suiteid AND component = :componentid AND package = :package AND type = :typeid""", {'suiteid': suite_id, 'componentid': component_id, 'package': package, 'typeid': type_id}) c_removed += 1 Logger.log(["removed override", suite, component, otype, package]) if action: session.commit() if not cnf["Control-Overrides::Options::Quiet"]: print("Done in %d seconds. [Updated = %d, Added = %d, Removed = %d, Skipped = %d, Errors = %d]" % (int(time.time() - start_time), c_updated, c_added, c_removed, c_skipped, c_error)) Logger.log(["set complete", c_updated, c_added, c_removed, c_skipped, c_error])
################################################################################
[docs]def list_overrides(suite, component, otype, session): dat = {} s = get_suite(suite, session) if s is None: utils.fubar("Suite '%s' not recognised." % (suite)) dat['suiteid'] = s.suite_id c = get_component(component, session) if c is None: utils.fubar("Component '%s' not recognised." % (component)) dat['componentid'] = c.component_id o = get_override_type(otype) if o is None: utils.fubar("Type '%s' not recognised. (Valid types are deb, udeb and dsc)" % (otype)) dat['typeid'] = o.overridetype_id if otype == "dsc": q = session.execute("""SELECT o.package, s.section, o.maintainer FROM override o, section s WHERE o.suite = :suiteid AND o.component = :componentid AND o.type = :typeid AND o.section = s.id ORDER BY s.section, o.package""", dat) for i in q.fetchall(): print(utils.result_join(i)) else: q = session.execute("""SELECT o.package, p.priority, s.section, o.maintainer, p.level FROM override o, priority p, section s WHERE o.suite = :suiteid AND o.component = :componentid AND o.type = :typeid AND o.priority = p.id AND o.section = s.id ORDER BY s.section, p.level, o.package""", dat) for i in q.fetchall(): print(utils.result_join(i[:-1]))
################################################################################
[docs]def main(): global Logger cnf = Config() Arguments = [('a', "add", "Control-Overrides::Options::Add"), ('c', "component", "Control-Overrides::Options::Component", "HasArg"), ('h', "help", "Control-Overrides::Options::Help"), ('l', "list", "Control-Overrides::Options::List"), ('q', "quiet", "Control-Overrides::Options::Quiet"), ('s', "suite", "Control-Overrides::Options::Suite", "HasArg"), ('S', "set", "Control-Overrides::Options::Set"), ('C', "change", "Control-Overrides::Options::Change"), ('n', "no-action", "Control-Overrides::Options::No-Action"), ('t', "type", "Control-Overrides::Options::Type", "HasArg")] # Default arguments for i in ["add", "help", "list", "quiet", "set", "change", "no-action"]: key = "Control-Overrides::Options::%s" % i if key not in cnf: cnf[key] = "" if "Control-Overrides::Options::Component" not in cnf: cnf["Control-Overrides::Options::Component"] = "main" if "Control-Overrides::Options::Suite" not in cnf: cnf["Control-Overrides::Options::Suite"] = "unstable" if "Control-Overrides::Options::Type" not in cnf: cnf["Control-Overrides::Options::Type"] = "deb" file_list = apt_pkg.parse_commandline(cnf.Cnf, Arguments, sys.argv) if cnf["Control-Overrides::Options::Help"]: usage() session = DBConn().session() mode = None for i in ["add", "list", "set", "change"]: if cnf["Control-Overrides::Options::%s" % (i)]: if mode: utils.fubar("Can not perform more than one action at once.") mode = i # Need an action... if mode is None: utils.fubar("No action specified.") (suite, component, otype) = (cnf["Control-Overrides::Options::Suite"], cnf["Control-Overrides::Options::Component"], cnf["Control-Overrides::Options::Type"]) if mode == "list": list_overrides(suite, component, otype, session) else: if get_suite(suite).untouchable: utils.fubar("%s: suite is untouchable" % suite) action = True if cnf["Control-Overrides::Options::No-Action"]: utils.warn("In No-Action Mode") action = False Logger = daklog.Logger("control-overrides", mode) if file_list: for f in file_list: process_file(open(f), suite, component, otype, mode, action, session) else: process_file(sys.stdin, suite, component, otype, mode, action, session) Logger.close()
####################################################################################### if __name__ == '__main__': main()