X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=dak%2Fprocess_new.py;h=d631b53aa7b90f67b6dd4d4537e4063efde90c82;hb=87bf163d12ec8328d87e1b2a2ca2239221a73bd6;hp=08f784f772a288be53f34ba12f5197fe90e9da8c;hpb=332c0c069ba9c04995fe29755dd454a152fc00fd;p=dak.git diff --git a/dak/process_new.py b/dak/process_new.py index 08f784f7..d631b53a 100755 --- a/dak/process_new.py +++ b/dak/process_new.py @@ -41,6 +41,8 @@ ################################################################################ +from __future__ import with_statement + import copy import errno import os @@ -48,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 @@ -55,7 +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 +from daklib.dak_exceptions import CantOpenError, AlreadyLockedError, CantGetLockError # Globals Cnf = None #: Configuration, apt_pkg.Configuration @@ -581,7 +585,7 @@ def prod_maintainer (note): answer = 'E' while answer == 'E': os.system("%s %s" % (editor, temp_filename)) - temp_fh = util.open_file(temp_filename) + temp_fh = utils.open_file(temp_filename) prod_message = "".join(temp_fh.readlines()) temp_fh.close() print "Prod message:" @@ -594,12 +598,12 @@ def prod_maintainer (note): 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"]) @@ -683,7 +687,12 @@ def do_new(): answer = answer[:1].upper() if answer == 'A' and not Options["Trainee"]: - done = add_overrides (new) + try: + check_daily_lock() + done = add_overrides (new) + except CantGetLockError: + print "Hello? Operator! Give me the number for 911!" + print "Dinstall in the locked area, cant process packages, come back later" elif answer == 'C': check_pkg() elif answer == 'E' and not Options["Trainee"]: @@ -699,7 +708,7 @@ def do_new(): 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': + elif answer == 'R' and not Options["Trainee"]: confirm = utils.our_raw_input("Really clear note (y/N)? ").lower() if confirm == "y": database.delete_new_comments(changes.get("source"), changes.get("version")) @@ -817,22 +826,41 @@ def do_byhand(): ################################################################################ -def get_accept_lock(): - retry = 0 - while retry < 10: - try: - os.open(Cnf["Process-New::AcceptedLockFile"], os.O_RDONLY | os.O_CREAT | os.O_EXCL) - retry = 10 - except OSError, e: - if e.errno == errno.EACCES or e.errno == errno.EEXIST: - retry += 1 - if (retry >= 10): - utils.fubar("Couldn't obtain lock; assuming 'dak process-unchecked' is already running.") - else: - print("Unable to get accepted lock (try %d of 10)" % retry) - time.sleep(60) - else: - raise +def check_daily_lock(): + """ + Raises CantGetLockError if the dinstall daily.lock exists. + """ + + try: + os.open(Cnf["Process-New::DinstallLockFile"], os.O_RDONLY | os.O_CREAT | os.O_EXCL) + except OSError, e: + if e.errno == errno.EEXIST or e.errno == errno.EACCES: + raise CantGetLockError + + os.unlink(Cnf["Process-New::DinstallLockFile"]) + + +@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) @@ -871,7 +899,7 @@ def _accept(): if Options["No-Action"]: return (summary, short_summary) = Upload.build_summaries() - Upload.accept(summary, short_summary) + Upload.accept(summary, short_summary, targetdir=Cnf["Dir::Queue::Newstage"]) os.unlink(Upload.pkg.changes_file[:-8]+".dak") def do_accept_stableupdate(suite, q): @@ -917,30 +945,25 @@ def do_accept_stableupdate(suite, q): def do_accept(): print "ACCEPT" if not Options["No-Action"]: - get_accept_lock() (summary, short_summary) = Upload.build_summaries() - try: - if Cnf.FindB("Dinstall::SecurityQueueHandling"): - Upload.dump_vars(Cnf["Dir::Queue::Embargoed"]) - move_to_dir(Cnf["Dir::Queue::Embargoed"]) - Upload.queue_build("embargoed", Cnf["Dir::Queue::Embargoed"]) - # Check for override disparities - Upload.Subst["__SUMMARY__"] = summary - else: - # Stable updates need to be copied to proposed-updates holding - # area instead of accepted. Sourceful uploads need to go - # to it directly, binaries only if the source has not yet been - # accepted into p-u. - for suite, q in [("proposed-updates", "ProposedUpdates"), - ("oldstable-proposed-updates", "OldProposedUpdates")]: - if not Upload.pkg.changes["distribution"].has_key(suite): - continue - return do_accept_stableupdate(suite, q) - # Just a normal upload, accept it... - _accept() - finally: - if not Options["No-Action"]: - os.unlink(Cnf["Process-New::AcceptedLockFile"]) + if Cnf.FindB("Dinstall::SecurityQueueHandling"): + Upload.dump_vars(Cnf["Dir::Queue::Embargoed"]) + move_to_dir(Cnf["Dir::Queue::Embargoed"]) + Upload.queue_build("embargoed", Cnf["Dir::Queue::Embargoed"]) + # Check for override disparities + Upload.Subst["__SUMMARY__"] = summary + else: + # Stable updates need to be copied to proposed-updates holding + # area instead of accepted. Sourceful uploads need to go + # to it directly, binaries only if the source has not yet been + # accepted into p-u. + for suite, q in [("proposed-updates", "ProposedUpdates"), + ("oldstable-proposed-updates", "OldProposedUpdates")]: + if not Upload.pkg.changes["distribution"].has_key(suite): + continue + return do_accept_stableupdate(suite, q) + # Just a normal upload, accept it... + _accept() def check_status(files): new = byhand = 0 @@ -958,19 +981,30 @@ 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) + try: + check_daily_lock() + except CantGetLockError: + print "Hello? Operator! Give me the number for 911!" + print "Dinstall in the locked area, cant process packages, come back later" + sys.exit(1) - 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) ################################################################################ @@ -1069,6 +1103,7 @@ def main(): if not changes_file: continue print "\n" + changes_file + do_pkg (changes_file) end()