from daklib import utils
from daklib.dbconn import *
+from sqlalchemy.orm.exc import NoResultFound
################################################################################
s-a add SUITE ARCH add ARCH to suite
s-a rm SUITE ARCH remove ARCH from suite (will only work if
no packages remain for the arch in the suite)
+
+ version-check / v-c:
+ v-c list show version checks for all suites
+ v-c list-suite SUITE show version checks for suite SUITE
+ v-c add SUITE CHECK REFERENCE add a version check for suite SUITE
+ v-c rm SUITE CHECK REFERENCE rmove a version check
+ where
+ CHECK is one of Enhances, MustBeNewerThan, MustBeOlderThan
+ REFERENCE is another suite name
"""
sys.exit(exit_code)
################################################################################
+def __version_check_list(d):
+ session = d.session()
+ for s in session.query(Suite).order_by('suite_name'):
+ __version_check_list_suite(d, s.suite_name)
+
+def __version_check_list_suite(d, suite_name):
+ vcs = get_version_checks(suite_name)
+ for vc in vcs:
+ print "%s %s %s" % (suite_name, vc.check, vc.reference.suite_name)
+
+def __version_check_add(d, suite_name, check, reference_name):
+ suite = get_suite(suite_name)
+ if not suite:
+ die("E: Could not find suite %s." % (suite_name))
+ reference = get_suite(reference_name)
+ if not reference:
+ die("E: Could not find reference suite %s." % (reference_name))
+
+ session = d.session()
+ vc = VersionCheck()
+ vc.suite = suite
+ vc.check = check
+ vc.reference = reference
+ session.add(vc)
+ session.commit()
+
+def __version_check_rm(d, suite_name, check, reference_name):
+ suite = get_suite(suite_name)
+ if not suite:
+ die("E: Could not find suite %s." % (suite_name))
+ reference = get_suite(reference_name)
+ if not reference:
+ die("E: Could not find reference suite %s." % (reference_name))
+
+ session = d.session()
+ try:
+ vc = session.query(VersionCheck).filter_by(suite=suite, check=check, reference=reference).one()
+ session.delete(vc)
+ session.commit()
+ except NoResultFound:
+ print "W: version-check not found."
+
+def version_check(command):
+ args = [str(x) for x in command]
+ Cnf = utils.get_conf()
+ d = DBConn()
+
+ die_arglen(args, 2, "E: version-check needs at least a command")
+ mode = args[1].lower()
+
+ if mode == 'list':
+ __version_check_list(d)
+ elif mode == 'list-suite':
+ if len(args) != 3:
+ die("E: version-check list-suite needs a single parameter")
+ __version_check_list_suite(d, args[2])
+ elif mode == 'add':
+ if len(args) != 5:
+ die("E: version-check add needs three parameters")
+ __version_check_add(d, args[2], args[3], args[4])
+ elif mode == 'rm':
+ if len(args) != 5:
+ die("E: version-check rm needs three parameters")
+ __version_check_rm(d, args[2], args[3], args[4])
+ else:
+ die("E: version-check command unknown")
+
+dispatch['version-check'] = version_check
+dispatch['v-c'] = version_check
+
+################################################################################
+
def show_config(command):
args = [str(x) for x in command]
cnf = utils.get_conf()
from daklib.dbconn import *
from daklib import daklog
from daklib import utils
+from daklib.queue import get_suite_version_by_package, get_suite_version_by_source
#######################################################################################
#######################################################################################
-def set_suite(file, suite, session, britney=False):
+def version_checks(package, architecture, target_suite, new_version, session, force = False):
+ if architecture == "source":
+ suite_version_list = get_suite_version_by_source(package, session)
+ else:
+ suite_version_list = get_suite_version_by_package(package, architecture, session)
+
+ must_be_newer_than = [ vc.reference.suite_name for vc in get_version_checks(target_suite, "MustBeNewerThan") ]
+ must_be_older_than = [ vc.reference.suite_name for vc in get_version_checks(target_suite, "MustBeOlderThan") ]
+
+ # Must be newer than an existing version in target_suite
+ if target_suite not in must_be_newer_than:
+ must_be_newer_than.append(target_suite)
+
+ violations = False
+
+ for suite, version in suite_version_list:
+ cmp = apt_pkg.VersionCompare(new_version, version)
+ if suite in must_be_newer_than and cmp < 1:
+ utils.warn("%s (%s): version check violated: %s targeted at %s is *not* newer than %s in %s" % (package, architecture, new_version, target_suite, version, suite))
+ violations = True
+ if suite in must_be_older_than and cmp > 1:
+ utils.warn("%s (%s): version check violated: %s targeted at %s is *not* older than %s in %s" % (package, architecture, new_version, target_suite, version, suite))
+ violations = True
+
+ if violations:
+ if force:
+ utils.warn("Continuing anyway (forced)...")
+ else:
+ utils.fubar("Aborting. Version checks violated and not forced.")
+
+#######################################################################################
+
+def set_suite(file, suite, session, britney=False, force=False):
suite_id = suite.suite_id
lines = file.readlines()
for key in desired.keys():
if not current.has_key(key):
(package, version, architecture) = key.split()
+ version_checks(package, architecture, suite.suite_name, version, session, force)
pkid = get_id (package, version, architecture, session)
if not pkid:
continue
#######################################################################################
-def process_file(file, suite, action, session, britney=False):
+def process_file(file, suite, action, session, britney=False, force=False):
if action == "set":
- set_suite(file, suite, session, britney)
+ set_suite(file, suite, session, britney, force)
return
suite_id = suite.suite_id
if not pkid:
continue
+ # Do version checks when adding packages
+ if action == "add":
+ version_checks(package, architecture, suite.suite_name, version, session, force)
+
if architecture == "source":
# Find the existing association ID, if any
q = session.execute("""SELECT id FROM src_associations
Arguments = [('a',"add","Control-Suite::Options::Add", "HasArg"),
('b',"britney","Control-Suite::Options::Britney"),
+ ('f','force','Control-Suite::Options::Force'),
('h',"help","Control-Suite::Options::Help"),
('l',"list","Control-Suite::Options::List","HasArg"),
('r',"remove", "Control-Suite::Options::Remove", "HasArg"),
session = DBConn().session()
+ force = Options.has_key("Force") and Options["Force"]
+
action = None
for i in ("add", "list", "remove", "set"):
Logger = daklog.Logger(cnf.Cnf, "control-suite")
if file_list:
for f in file_list:
- process_file(utils.open_file(f), suite, action, session, britney)
+ process_file(utils.open_file(f), suite, action, session, britney, force)
else:
- process_file(sys.stdin, suite, action, session, britney)
+ process_file(sys.stdin, suite, action, session, britney, force)
Logger.close()
#######################################################################################
--- /dev/null
+#!/usr/bin/env python
+# coding=utf8
+
+"""
+Add table for version checks.
+
+@contact: Debian FTP Master <ftpmaster@debian.org>
+@copyright: 2011 Ansgar Burchardt <ansgar@debian.org>
+@license: GNU General Public License version 2 or later
+"""
+
+# 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
+
+################################################################################
+
+import psycopg2
+from daklib.dak_exceptions import DBUpdateError
+from daklib.config import Config
+
+################################################################################
+def do_update(self):
+ """
+ Add table for version checks.
+ """
+ print __doc__
+ try:
+ cnf = Config()
+ c = self.db.cursor()
+
+ c.execute("""
+ CREATE TABLE version_check (
+ suite INTEGER NOT NULL REFERENCES suite(id),
+ "check" TEXT NOT NULL CHECK ("check" IN ('Enhances', 'MustBeNewerThan', 'MustBeOlderThan')),
+ reference INTEGER NOT NULL REFERENCES suite(id),
+ PRIMARY KEY(suite, "check", reference)
+ )""")
+
+ c.execute("SELECT suite_name, id FROM suite")
+ suites = c.fetchall()
+ suite_id_map = {}
+ for suite_name, suite_id in suites:
+ suite_id_map[suite_name] = suite_id
+
+ for check in ["Enhances", "MustBeNewerThan", "MustBeOlderThan"]:
+ for suite_name in suite_id_map.keys():
+ for reference_name in [ s.lower() for s in cnf.ValueList("Suite::%s::VersionChecks::%s" % (suite_name, check)) ]:
+ c.execute("""INSERT INTO version_check (suite, "check", reference) VALUES (%s, %s, %s)""", (suite_id_map[suite_name], check, suite_id_map[reference_name]))
+
+ c.execute("UPDATE config SET value = '52' WHERE name = 'db_revision'")
+ self.db.commit()
+
+ except psycopg2.ProgrammingError, msg:
+ self.db.rollback()
+ raise DBUpdateError, 'Unable to apply sick update 52, rollback issued. Error message : %s' % (str(msg))
################################################################################
Cnf = None
-required_database_schema = 51
+required_database_schema = 52
################################################################################
################################################################################
+class VersionCheck(ORMObject):
+ def __init__(self, *args, **kwargs):
+ pass
+
+ def properties(self):
+ #return ['suite_id', 'check', 'reference_id']
+ return ['check']
+
+ def not_null_constraints(self):
+ return ['suite', 'check', 'reference']
+
+__all__.append('VersionCheck')
+
+@session_wrapper
+def get_version_checks(suite_name, check = None, session = None):
+ suite = get_suite(suite_name, session)
+ if not suite:
+ return None
+ q = session.query(VersionCheck).filter_by(suite=suite)
+ if check:
+ q = q.filter_by(check=check)
+ return q.all()
+
+__all__.append('get_version_checks')
+
+################################################################################
+
class DBConn(object):
"""
database module init.
'suite_src_formats',
'uid',
'upload_blocks',
+ 'version_check',
)
views = (
key = relation(MetadataKey),
value = self.tbl_source_metadata.c.value))
+ mapper(VersionCheck, self.tbl_version_check,
+ properties = dict(
+ suite_id = self.tbl_version_check.c.suite,
+ suite = relation(Suite, primaryjoin=self.tbl_version_check.c.suite==self.tbl_suite.c.id),
+ reference_id = self.tbl_version_check.c.reference,
+ reference = relation(Suite, primaryjoin=self.tbl_version_check.c.reference==self.tbl_suite.c.id, lazy='joined')))
+
## Connection functions
def __createconn(self):
from config import Config
"""
Cnf = Config()
anyversion = None
- anysuite = [suite] + Cnf.ValueList("Suite::%s::VersionChecks::Enhances" % (suite))
+ anysuite = [suite] + [ vc.reference.suite_name for vc in get_version_checks(suite, "Enhances") ]
for (s, v) in sv_list:
if s in [ x.lower() for x in anysuite ]:
if not anyversion or apt_pkg.VersionCompare(anyversion, v) <= 0:
# Check versions for each target suite
for target_suite in self.pkg.changes["distribution"].keys():
- must_be_newer_than = [ i.lower() for i in cnf.ValueList("Suite::%s::VersionChecks::MustBeNewerThan" % (target_suite)) ]
- must_be_older_than = [ i.lower() for i in cnf.ValueList("Suite::%s::VersionChecks::MustBeOlderThan" % (target_suite)) ]
+ must_be_newer_than = [ vc.reference.suite_name for vc in get_version_checks(target_suite, "MustBeNewerThan") ]
+ must_be_older_than = [ vc.reference.suite_name for vc in get_version_checks(target_suite, "MustBeOlderThan") ]
# Enforce "must be newer than target suite" even if conffile omits it
if target_suite not in must_be_newer_than: