X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=dak%2Fprocess_new.py;h=52e1f4e9780350d722e533a0a179b0f290a4c577;hb=35cd0972b5e14dc8727403e13fccd30776f3ae02;hp=9ecfcdc6bbc2ade5ca50079f3880319d7fa23756;hpb=ee00ba60099f741819f991db13b4d0fc65bdd960;p=dak.git diff --git a/dak/process_new.py b/dak/process_new.py index 9ecfcdc6..52e1f4e9 100755 --- a/dak/process_new.py +++ b/dak/process_new.py @@ -5,6 +5,7 @@ @contact: Debian FTP Master @copyright: 2001, 2002, 2003, 2004, 2005, 2006 James Troup +@copyright: 2009 Joerg Jaspert @license: GNU General Public License version 2 or later """ # This program is free software; you can redistribute it and/or modify @@ -40,6 +41,8 @@ ################################################################################ +from __future__ import with_statement + import copy import errno import os @@ -47,6 +50,8 @@ import readline import stat import sys import time +import contextlib +import pwd import apt_pkg, apt_inst import examine_package from daklib import database @@ -54,6 +59,7 @@ from daklib import logging from daklib import queue from daklib import utils from daklib.regexes import re_no_epoch, re_default_answer, re_isanum +from daklib.dak_exceptions import CantOpenError, AlreadyLockedError # Globals Cnf = None #: Configuration, apt_pkg.Configuration @@ -112,7 +118,7 @@ def recheck(): if reject_message.find("Rejected") != -1: answer = "XXX" - if Options["No-Action"] or Options["Automatic"]: + if Options["No-Action"] or Options["Automatic"] or Options["Trainee"]: answer = 'S' print "REJECT\n" + reject_message, @@ -219,7 +225,7 @@ def sort_changes(changes_files): mtime = os.stat(d["filename"])[stat.ST_MTIME] if mtime < oldest: oldest = mtime - have_note += (d.has_key("process-new note")) + have_note += (database.has_new_comment(d["source"], d["version"])) per_source[source]["oldest"] = oldest if not have_note: per_source[source]["note_state"] = 0; # none @@ -301,11 +307,10 @@ def print_new (new, indexed, file=sys.stdout): line = "%-20s %-20s %-20s" % (pkg, priority, section) line = line.strip()+'\n' file.write(line) - note = Upload.pkg.changes.get("process-new note") - if note: - print "*"*75 - print note - print "*"*75 + note = database.get_new_comments(Upload.pkg.changes.get("source")) + if len(note) > 0: + for line in note: + print line return broken, note ################################################################################ @@ -468,18 +473,15 @@ def edit_overrides (new): def edit_note(note): # Write the current data to a temporary file (fd, temp_filename) = utils.temp_filename() - temp_file = os.fdopen(fd, 'w') - temp_file.write(note) - temp_file.close() editor = os.environ.get("EDITOR","vi") answer = 'E' while answer == 'E': os.system("%s %s" % (editor, temp_filename)) temp_file = utils.open_file(temp_filename) - note = temp_file.read().rstrip() + newnote = temp_file.read().rstrip() temp_file.close() - print "Note:" - print utils.prefix_multi_line_string(note," ") + print "New Note:" + print utils.prefix_multi_line_string(newnote," ") prompt = "[D]one, Edit, Abandon, Quit ?" answer = "XXX" while prompt.find(answer) == -1: @@ -494,8 +496,7 @@ def edit_note(note): elif answer == 'Q': end() sys.exit(0) - Upload.pkg.changes["process-new note"] = note - Upload.dump_vars(Cnf["Dir::Queue::New"]) + database.add_new_comment(Upload.pkg.changes["source"], Upload.pkg.changes["version"], newnote, utils.whoami()) ################################################################################ @@ -572,16 +573,21 @@ def add_overrides (new): ################################################################################ -def prod_maintainer (): +def prod_maintainer (note): # Here we prepare an editor and get them ready to prod... (fd, temp_filename) = utils.temp_filename() + temp_file = os.fdopen(fd, 'w') + if len(note) > 0: + for line in note: + temp_file.write(line) + temp_file.close() editor = os.environ.get("EDITOR","vi") answer = 'E' while answer == 'E': os.system("%s %s" % (editor, temp_filename)) - f = os.fdopen(fd) - prod_message = "".join(f.readlines()) - f.close() + temp_fh = utils.open_file(temp_filename) + prod_message = "".join(temp_fh.readlines()) + temp_fh.close() print "Prod message:" print utils.prefix_multi_line_string(prod_message," ",include_blank_lines=1) prompt = "[P]rod, Edit, Abandon, Quit ?" @@ -592,12 +598,12 @@ def prod_maintainer (): if answer == "": answer = m.group(1) answer = answer[:1].upper() - os.unlink(temp_filename) - if answer == 'A': - return - elif answer == 'Q': - end() - sys.exit(0) + os.unlink(temp_filename) + if answer == 'A': + return + elif answer == 'Q': + end() + sys.exit(0) # Otherwise, do the proding... user_email_address = utils.whoami() + " <%s>" % ( Cnf["Dinstall::MyAdminAddress"]) @@ -680,25 +686,27 @@ def do_new(): answer = m.group(1) answer = answer[:1].upper() - if answer == 'A': + if answer == 'A' and not Options["Trainee"]: done = add_overrides (new) elif answer == 'C': check_pkg() - elif answer == 'E': + elif answer == 'E' and not Options["Trainee"]: new = edit_overrides (new) - elif answer == 'M': - aborted = Upload.do_reject(1, Options["Manual-Reject"]) + elif answer == 'M' and not Options["Trainee"]: + aborted = Upload.do_reject(manual=1, + reject_message=Options["Manual-Reject"], + note=database.get_new_comments(changes.get("source", ""))) if not aborted: os.unlink(Upload.pkg.changes_file[:-8]+".dak") done = 1 elif answer == 'N': - edit_note(changes.get("process-new note", "")) - elif answer == 'P': - prod_maintainer() - elif answer == 'R': + edit_note(database.get_new_comments(changes.get("source", ""))) + elif answer == 'P' and not Options["Trainee"]: + prod_maintainer(database.get_new_comments(changes.get("source", ""))) + elif answer == 'R' and not Options["Trainee"]: confirm = utils.our_raw_input("Really clear note (y/N)? ").lower() if confirm == "y": - del changes["process-new note"] + database.delete_new_comments(changes.get("source"), changes.get("version")) elif answer == 'S': done = 1 elif answer == 'Q': @@ -716,6 +724,7 @@ def usage (exit_code=0): -C, --comments-dir=DIR use DIR as comments-dir, for [o-]p-u-new -m, --manual-reject=MSG manual reject with `msg' -n, --no-action don't do anything + -t, --trainee FTP Trainee mode -V, --version display the version number and exit""" sys.exit(exit_code) @@ -730,9 +739,10 @@ def init(): ('h',"help","Process-New::Options::Help"), ('C',"comments-dir","Process-New::Options::Comments-Dir", "HasArg"), ('m',"manual-reject","Process-New::Options::Manual-Reject", "HasArg"), + ('t',"trainee","Process-New::Options::Trainee"), ('n',"no-action","Process-New::Options::No-Action")] - for i in ["automatic", "help", "manual-reject", "no-action", "version", "comments-dir"]: + for i in ["automatic", "help", "manual-reject", "no-action", "version", "comments-dir", "trainee"]: if not Cnf.has_key("Process-New::Options::%s" % (i)): Cnf["Process-New::Options::%s" % (i)] = "" @@ -748,7 +758,10 @@ def init(): Upload = queue.Upload(Cnf) if not Options["No-Action"]: - Logger = Upload.Logger = logging.Logger(Cnf, "process-new") + try: + Logger = Upload.Logger = logging.Logger(Cnf, "process-new") + except CantOpenError, e: + Options["Trainee"] = "Oh yes" projectB = Upload.projectB @@ -825,6 +838,29 @@ def get_accept_lock(): else: raise + +@contextlib.contextmanager +def lock_package(package): + """ + Lock C{package} so that noone else jumps in processing it. + + @type package: string + @param package: source package name to lock + """ + + path = os.path.join(Cnf["Process-New::LockDir"], package) + try: + fd = os.open(path, os.O_CREAT | os.O_EXCL | os.O_RDONLY) + except OSError, e: + if e.errno == errno.EEXIST or e.errno == errno.EACCES: + user = pwd.getpwuid(os.stat(path)[stat.ST_UID])[4].split(',')[0].replace('.', '') + raise AlreadyLockedError, user + + try: + yield fd + finally: + os.unlink(path) + def move_to_dir (dest, perms=0660, changesperms=0664): utils.move (Upload.pkg.changes_file, dest, perms=changesperms) file_keys = Upload.pkg.files.keys() @@ -949,19 +985,23 @@ def do_pkg(changes_file): Upload.update_subst() files = Upload.pkg.files - if not recheck(): - return - - (new, byhand) = check_status(files) - if new or byhand: - if new: - do_new() - if byhand: - do_byhand() - (new, byhand) = check_status(files) - - if not new and not byhand: - do_accept() + try: + with lock_package(Upload.pkg.changes["source"]): + if not recheck(): + return + + (new, byhand) = check_status(files) + if new or byhand: + if new: + do_new() + if byhand: + do_byhand() + (new, byhand) = check_status(files) + + if not new and not byhand: + do_accept() + except AlreadyLockedError, e: + print "Seems to be locked by %s already, skipping..." % (e) ################################################################################ @@ -976,7 +1016,7 @@ def end(): sys.stderr.write("Accepted %d package %s, %s.\n" % (accept_count, sets, utils.size_type(int(accept_bytes)))) Logger.log(["total",accept_count,accept_bytes]) - if not Options["No-Action"]: + if not Options["No-Action"] and not Options["Trainee"]: Logger.close() ################################################################################