--- /dev/null
+#!/usr/bin/env python
+# coding=utf8
+
+"""
+per-queue NEW comments and permissions
+
+@contact: Debian FTP Master <ftpmaster@debian.org>
+@copyright: 2012 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
+
+statements = [
+"""
+ALTER TABLE new_comments
+ADD COLUMN policy_queue_id INTEGER REFERENCES policy_queue(id)
+""",
+
+"""
+UPDATE new_comments
+SET policy_queue_id = (SELECT id FROM policy_queue WHERE queue_name = 'new')
+""",
+
+"""
+ALTER TABLE new_comments ALTER COLUMN policy_queue_id SET NOT NULL
+""",
+
+"""
+CREATE OR REPLACE FUNCTION trigger_check_policy_queue_permission() RETURNS TRIGGER
+SET search_path = public, pg_temp
+LANGUAGE plpgsql
+AS $$
+DECLARE
+ v_row RECORD;
+ v_suite_id suite.id%TYPE;
+ v_policy_queue_name policy_queue.queue_name%TYPE;
+BEGIN
+
+ CASE TG_OP
+ WHEN 'INSERT', 'UPDATE' THEN
+ v_row := NEW;
+ WHEN 'DELETE' THEN
+ v_row := OLD;
+ ELSE
+ RAISE EXCEPTION 'Unexpected TG_OP (%)', TG_OP;
+ END CASE;
+
+ IF TG_OP = 'UPDATE' AND OLD.policy_queue_id != NEW.policy_queue_id THEN
+ RAISE EXCEPTION 'Cannot change policy_queue_id';
+ END IF;
+
+ SELECT suite_id, queue_name INTO STRICT v_suite_id, v_policy_queue_name
+ FROM policy_queue WHERE id = v_row.policy_queue_id;
+ IF NOT has_suite_permission(TG_OP, v_suite_id) THEN
+ RAISE EXCEPTION 'Not allowed to % in %', TG_OP, v_policy_queue_name;
+ END IF;
+
+ RETURN v_row;
+
+END;
+$$
+""",
+
+"""
+CREATE CONSTRAINT TRIGGER trigger_new_comments_permission
+ AFTER INSERT OR UPDATE OR DELETE
+ ON new_comments
+ FOR EACH ROW
+ EXECUTE PROCEDURE trigger_check_policy_queue_permission()
+""",
+]
+
+################################################################################
+def do_update(self):
+ print __doc__
+ try:
+ cnf = Config()
+
+ c = self.db.cursor()
+
+ for stmt in statements:
+ c.execute(stmt)
+
+ c.execute("UPDATE config SET value = '91' WHERE name = 'db_revision'")
+ self.db.commit()
+
+ except psycopg2.ProgrammingError as msg:
+ self.db.rollback()
+ raise DBUpdateError('Unable to apply sick update 91, rollback issued. Error message: {0}'.format(msg))
if not m['valid']:
line = line + ' [!]'
print >>file, line
- notes = get_new_comments(upload.changes.source)
+ notes = get_new_comments(upload.policy_queue, upload.changes.source)
for note in notes:
print "\nAuthor: %s\nVersion: %s\nTimestamp: %s\n\n%s" \
% (note.author, note.version, note.notedate, note.comment)
missing = edit_overrides (missing, upload, session)
elif answer == 'M' and not Options["Trainee"]:
reason = Options.get('Manual-Reject', '') + "\n"
- reason = reason + "\n\n=====\n\n".join([n.comment for n in get_new_comments(upload.changes.source, session=session)])
+ reason = reason + "\n\n=====\n\n".join([n.comment for n in get_new_comments(upload.policy_queue, upload.changes.source, session=session)])
reason = get_reject_reason(reason)
if reason is not None:
Logger.log(["NEW REJECT", upload.changes.changesname])
handler.reject(reason)
done = True
elif answer == 'N':
- if edit_note(get_new_comments(upload.changes.source, session=session),
+ if edit_note(get_new_comments(upload.policy_queue, upload.changes.source, session=session),
upload, session, bool(Options["Trainee"])) == 0:
end()
sys.exit(0)
elif answer == 'P' and not Options["Trainee"]:
- if prod_maintainer(get_new_comments(upload.changes.source, session=session),
+ if prod_maintainer(get_new_comments(upload.policy_queue, upload.changes.source, session=session),
upload) == 0:
end()
sys.exit(0)
elif answer == 'R' and not Options["Trainee"]:
confirm = utils.our_raw_input("Really clear note (y/N)? ").lower()
if confirm == "y":
- for c in get_new_comments(upload.changes.source, upload.changes.version, session=session):
+ for c in get_new_comments(upload.policy_queue, upload.changes.source, upload.changes.version, session=session):
session.delete(c)
session.commit()
elif answer == 'O' and not Options["Trainee"]:
confirm = utils.our_raw_input("Really clear all notes (y/N)? ").lower()
if confirm == "y":
- for c in get_new_comments(upload.changes.source, session=session):
+ for c in get_new_comments(upload.policy_queue, upload.changes.source, session=session):
session.delete(c)
session.commit()
################################################################################
-def sort_uploads(uploads, session, nobinaries=False):
+def sort_uploads(new_queue, uploads, session, nobinaries=False):
sources = {}
sorteduploads = []
suitesrc = [s.source for s in session.query(DBSource.source). \
filter(DBSource.suites.any(Suite.suite_name.in_(['unstable', 'experimental'])))]
comments = [p.package for p in session.query(NewComment.package). \
- filter_by(trainee=False).distinct()]
+ filter_by(trainee=False, policy_queue=new_queue).distinct()]
for upload in uploads:
source = upload.changes.source
if not source in sources:
if len(uploads) > 1:
sys.stderr.write("Sorting changes...\n")
- uploads = sort_uploads(uploads, session, Options["No-Binaries"])
+ uploads = sort_uploads(new_queue, uploads, session, Options["No-Binaries"])
if Options["Comments"]:
show_new_comments(uploads, session)
else:
if mtime < oldest:
oldest = mtime
- have_note += has_new_comment(d.changes.source, d.changes.version)
+ have_note += has_new_comment(d.policy_queue, d.changes.source, d.changes.version)
per_source[source]["oldest"] = oldest
if not have_note:
per_source[source]["note_state"] = 0; # none
################################################################################
Cnf = None
-required_database_schema = 90
+required_database_schema = 91
################################################################################
__all__.append('NewComment')
@session_wrapper
-def has_new_comment(package, version, session=None):
+def has_new_comment(policy_queue, package, version, session=None):
"""
Returns true if the given combination of C{package}, C{version} has a comment.
@return: true/false
"""
- q = session.query(NewComment)
+ q = session.query(NewComment).filter_by(policy_queue=policy_queue)
q = q.filter_by(package=package)
q = q.filter_by(version=version)
__all__.append('has_new_comment')
@session_wrapper
-def get_new_comments(package=None, version=None, comment_id=None, session=None):
+def get_new_comments(policy_queue, package=None, version=None, comment_id=None, session=None):
"""
Returns (possibly empty) list of NewComment objects for the given
parameters
@return: A (possibly empty) list of NewComment objects will be returned
"""
- q = session.query(NewComment)
+ q = session.query(NewComment).filter_by(policy_queue=policy_queue)
if package is not None: q = q.filter_by(package=package)
if version is not None: q = q.filter_by(version=version)
if comment_id is not None: q = q.filter_by(comment_id=comment_id)
extension = validator)
mapper(NewComment, self.tbl_new_comments,
- properties = dict(comment_id = self.tbl_new_comments.c.id))
+ properties = dict(comment_id = self.tbl_new_comments.c.id,
+ policy_queue = relation(PolicyQueue)))
mapper(Override, self.tbl_override,
properties = dict(suite_id = self.tbl_override.c.suite,
return 0
comment = NewComment()
+ comment.policy_queue = upload.policy_queue
comment.package = upload.changes.source
comment.version = upload.changes.version
comment.comment = newnote