#! /usr/bin/env python3
""" Microscopic modification and query tool for overrides in projectb """
# Copyright (C) 2004, 2006 Daniel Silverstone <dsilvers@digital-scurf.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
################################################################################
## So line up your soldiers and she'll shoot them all down
## Coz Alisha Rules The World
## You think you found a dream, then it shatters and it seems,
## That Alisha Rules The World
################################################################################
import os
import sys
import apt_pkg
from daklib.config import Config
from daklib.dbconn import *
from daklib import daklog
from daklib import utils
################################################################################
# Shamelessly stolen from 'dak rm'. Should probably end up in utils.py
[docs]def game_over():
answer = utils.input_or_exit("Continue (y/N)? ").lower()
if answer != "y":
print("Aborted.")
sys.exit(1)
[docs]def usage(exit_code=0):
print("""Usage: dak override [OPTIONS] package [section] [priority]
Make microchanges or microqueries of the binary overrides
-h, --help show this help and exit
-c, --check check override compliance (deprecated)
-d, --done=BUG# send priority/section change as closure to bug#
-n, --no-action don't do anything
-s, --suite specify the suite to use
""")
sys.exit(exit_code)
[docs]def main():
cnf = Config()
Arguments = [('h', "help", "Override::Options::Help"),
('c', "check", "Override::Options::Check"),
('d', "done", "Override::Options::Done", "HasArg"),
('n', "no-action", "Override::Options::No-Action"),
('s', "suite", "Override::Options::Suite", "HasArg"),
]
for i in ["help", "check", "no-action"]:
key = "Override::Options::%s" % i
if key not in cnf:
cnf[key] = ""
if "Override::Options::Suite" not in cnf:
cnf["Override::Options::Suite"] = "unstable"
arguments = apt_pkg.parse_commandline(cnf.Cnf, Arguments, sys.argv)
Options = cnf.subtree("Override::Options")
if Options["Help"]:
usage()
session = DBConn().session()
if not arguments:
utils.fubar("package name is a required argument.")
package = arguments.pop(0)
suite_name = Options["Suite"]
if arguments and len(arguments) > 2:
utils.fubar("Too many arguments")
suite = get_suite(suite_name, session)
if suite is None:
utils.fubar("Unknown suite '{0}'".format(suite_name))
if arguments and len(arguments) == 1:
# Determine if the argument is a priority or a section...
arg = arguments.pop()
q = session.execute("""
SELECT ( SELECT COUNT(*) FROM section WHERE section = :arg ) AS secs,
( SELECT COUNT(*) FROM priority WHERE priority = :arg ) AS prios
""", {'arg': arg})
r = q.fetchall()
if r[0][0] == 1:
arguments = (arg, ".")
elif r[0][1] == 1:
arguments = (".", arg)
else:
utils.fubar("%s is not a valid section or priority" % (arg))
# Retrieve current section/priority...
oldsection, oldsourcesection, oldpriority = None, None, None
for packagetype in ['source', 'binary']:
eqdsc = '!='
if packagetype == 'source':
eqdsc = '='
q = session.execute("""
SELECT priority.priority AS prio, section.section AS sect, override_type.type AS type
FROM override, priority, section, suite, override_type
WHERE override.priority = priority.id
AND override.type = override_type.id
AND override_type.type %s 'dsc'
AND override.section = section.id
AND override.package = :package
AND override.suite = suite.id
AND suite.suite_name = :suite_name
""" % (eqdsc), {'package': package, 'suite_name': suite_name})
if q.rowcount == 0:
continue
if q.rowcount > 1:
utils.fubar("%s is ambiguous. Matches %d packages" % (package, q.rowcount))
r = q.fetchone()
if packagetype == 'binary':
oldsection = r[1]
oldpriority = r[0]
else:
oldsourcesection = r[1]
oldpriority = 'optional'
if not oldpriority and not oldsourcesection:
utils.fubar("Unable to find package %s" % (package))
if oldsection and oldsourcesection and oldsection != oldsourcesection:
# When setting overrides, both source & binary will become the same section
utils.warn("Source is in section '%s' instead of '%s'" % (oldsourcesection, oldsection))
if not oldsection:
oldsection = oldsourcesection
if not arguments:
print("%s is in section '%s' at priority '%s'" % (
package, oldsection, oldpriority))
sys.exit(0)
# At this point, we have a new section and priority... check they're valid...
newsection, newpriority = arguments
if newsection == ".":
newsection = oldsection
if newpriority == ".":
newpriority = oldpriority
s = get_section(newsection, session)
if s is None:
utils.fubar("Supplied section %s is invalid" % (newsection))
newsecid = s.section_id
p = get_priority(newpriority, session)
if p is None:
utils.fubar("Supplied priority %s is invalid" % (newpriority))
newprioid = p.priority_id
if newpriority == oldpriority and newsection == oldsection:
print("I: Doing nothing")
sys.exit(0)
if Options["Check"]:
print("WARNING: Check option is deprecated by Debian Policy 4.0.1")
# If we're in no-action mode
if Options["No-Action"]:
if newpriority != oldpriority:
print("I: Would change priority from %s to %s" % (oldpriority, newpriority))
if newsection != oldsection:
print("I: Would change section from %s to %s" % (oldsection, newsection))
if "Done" in Options:
print("I: Would also close bug(s): %s" % (Options["Done"]))
sys.exit(0)
if newpriority != oldpriority:
print("I: Will change priority from %s to %s" % (oldpriority, newpriority))
if newsection != oldsection:
print("I: Will change section from %s to %s" % (oldsection, newsection))
if "Done" not in Options:
pass
# utils.warn("No bugs to close have been specified. Noone will know you have done this.")
else:
print("I: Will close bug(s): %s" % (Options["Done"]))
game_over()
Logger = daklog.Logger("override")
dsc_otype_id = get_override_type('dsc').overridetype_id
# We're already in a transaction
# We're in "do it" mode, we have something to do... do it
if newpriority != oldpriority:
session.execute("""
UPDATE override
SET priority = :newprioid
WHERE package = :package
AND override.type != :otypedsc
AND suite = (SELECT id FROM suite WHERE suite_name = :suite_name)""",
{'newprioid': newprioid, 'package': package,
'otypedsc': dsc_otype_id, 'suite_name': suite_name})
Logger.log(["changed priority", package, oldpriority, newpriority])
if newsection != oldsection:
q = session.execute("""
UPDATE override
SET section = :newsecid
WHERE package = :package
AND suite = (SELECT id FROM suite WHERE suite_name = :suite_name)""",
{'newsecid': newsecid, 'package': package,
'suite_name': suite_name})
Logger.log(["changed section", package, oldsection, newsection])
session.commit()
if "Done" in Options:
if "Dinstall::BugServer" not in cnf:
utils.warn("Asked to send Done message but Dinstall::BugServer is not configured")
Logger.close()
return
Subst = {}
Subst["__OVERRIDE_ADDRESS__"] = cnf["Dinstall::MyEmailAddress"]
Subst["__BUG_SERVER__"] = cnf["Dinstall::BugServer"]
bcc = []
if cnf.find("Dinstall::Bcc") != "":
bcc.append(cnf["Dinstall::Bcc"])
if bcc:
Subst["__BCC__"] = "Bcc: " + ", ".join(bcc)
else:
Subst["__BCC__"] = "X-Filler: 42"
if "Dinstall::PackagesServer" in cnf:
Subst["__CC__"] = "Cc: " + package + "@" + cnf["Dinstall::PackagesServer"] + "\nX-DAK: dak override"
else:
Subst["__CC__"] = "X-DAK: dak override"
Subst["__ADMIN_ADDRESS__"] = cnf["Dinstall::MyAdminAddress"]
Subst["__DISTRO__"] = cnf["Dinstall::MyDistribution"]
Subst["__WHOAMI__"] = utils.whoami()
Subst["__SOURCE__"] = package
summary = "Concerning package %s...\n" % (package)
summary += "Operating on the %s suite\n" % (suite_name)
if newpriority != oldpriority:
summary += "Changed priority from %s to %s\n" % (oldpriority, newpriority)
if newsection != oldsection:
summary += "Changed section from %s to %s\n" % (oldsection, newsection)
Subst["__SUMMARY__"] = summary
template = os.path.join(cnf["Dir::Templates"], "override.bug-close")
for bug in utils.split_args(Options["Done"]):
Subst["__BUG_NUMBER__"] = bug
mail_message = utils.TemplateSubst(Subst, template)
utils.send_mail(mail_message)
Logger.log(["closed bug", bug])
Logger.close()
#################################################################################
if __name__ == '__main__':
main()