X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=shania;h=799aebd49566f0b883b768684fb22fb1e85477e0;hb=c5617d291dc17395a9d23c757d7dc815f6eed49e;hp=b12fb0ab766d084a89365469c02bfe7b2a0822bf;hpb=e8eacb00ee41d7ab974ba913fff40e5c082b8e1a;p=dak.git diff --git a/shania b/shania index b12fb0ab..799aebd4 100755 --- a/shania +++ b/shania @@ -1,8 +1,8 @@ #!/usr/bin/env python # Clean incoming of old unused files -# Copyright (C) 2000 James Troup -# $Id: shania,v 1.1 2000-12-13 03:18:50 troup Exp $ +# Copyright (C) 2000, 2001, 2002 James Troup +# $Id: shania,v 1.17 2002-10-16 02:47:32 troup Exp $ # 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 @@ -18,181 +18,192 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# Caveat Emptor: If run with -m/--mail argument, expects to be in -# Incoming/REJECT or somewhere with .reason files. - ################################################################################ -import os, re, stat, string, sys, time -import utils -import apt_pkg; +# Bdale, a ham-er, and the leader, +# Willy, a GCC maintainer, +# Lamont-work, 'cause he's the top uploader.... +# Penguin Puff' save the day! +# Porting code, trying to build the world, +# Here they come just in time... +# The Penguin Puff' Guys! +# [repeat] +# Penguin Puff'! +# willy: btw, if you don't maintain gcc you need to start, since +# the lyrics fit really well that way ################################################################################ -re_ischanges = re.compile(r"\.changes$") -re_isdsc = re.compile(r"\.dsc$") +import os, stat, sys, time; +import utils; +import apt_pkg; ################################################################################ -def file_to_string (filename): - try: - file = utils.open_file(filename, 'r'); - except utils.cant_open_exc: - return ""; - - contents = ""; - for line in file.readlines(): - contents = contents + line; - return contents; +Cnf = None; +Options = None; +del_dir = None; +delete_date = None; ################################################################################ -def main (): - Cnf = None; - all_files = {}; - changes_files = []; +def usage (exit_code=0): + print """Usage: shania [OPTIONS] +Clean out incoming directories. - apt_pkg.init(); - - Cnf = apt_pkg.newConfiguration(); - apt_pkg.ReadConfigFileISC(Cnf,utils.which_conf_file()); + -d, --days=DAYS remove anything older than DAYS old + -i, --incoming=INCOMING the incoming directory to clean + -n, --no-action don't do anything + -v, --verbose explain what is being done + -h, --help show this help and exit""" - Arguments = [('D',"debug","Shania::Options::Debug", "IntVal"), - ('h',"help","Shania::Options::Help"), - ('V',"version","Shania::Options::Version"), - ('d',"days","Shania::Options::Days", "IntVal"), - ('i',"incoming","Shania::Options::Incoming", "HasArg"), - ('m',"mail","Shania::Options::Mail"), - ('n',"no-action","Shania::Options::No-Action"), - ('v',"verbose","Shania::Options::Verbose")]; + sys.exit(exit_code) - apt_pkg.ParseCommandLine(Cnf,Arguments,sys.argv); +################################################################################ - delete_date = int(time.time())-(int(Cnf["Shania::Options::Days"])*84600); - del_dir = Cnf["Dir::Morgue"] + '/' + Cnf["Shania::MorgueSubDir"]; +def init (): + global delete_date, del_dir; - if not os.path.exists(del_dir): - sys.stderr.write("W: Creating morgue directory '%s'.\n" % (del_dir)); - os.mkdir(del_dir); - elif not os.path.isdir(del_dir): - sys.stderr.write("E: %s must be a directory.\n" % (del_dir)); + delete_date = int(time.time())-(int(Options["Days"])*84600); - incoming = Cnf["Shania::Options::Incoming"]; - if incoming == "": - incoming = Cnf["Dir::IncomingDir"]; + # Ensure a directory exists to remove files to + if not Options["No-Action"]: + date = time.strftime("%Y-%m-%d"); + del_dir = Cnf["Dir::Morgue"] + '/' + Cnf["Shania::MorgueSubDir"] + '/' + date; + if not os.path.exists(del_dir): + os.makedirs(del_dir, 02775); + if not os.path.isdir(del_dir): + utils.fubar("%s must be a directory." % (del_dir)); + # Move to the directory to clean + incoming = Options["Incoming"]; + if incoming == "": + incoming = Cnf["Dir::Queue::Unchecked"]; os.chdir(incoming); +# Remove a file to the morgue +def remove (file): + if os.access(file, os.R_OK): + dest_filename = del_dir + '/' + os.path.basename(file); + # If the destination file exists; try to find another filename to use + if os.path.exists(dest_filename): + dest_filename = utils.find_next_free(dest_filename, 10); + utils.move(file, dest_filename, 0660); + else: + utils.warn("skipping '%s', permission denied." % (os.path.basename(file))); + +# Removes any old files. +# [Used for Incoming/REJECT] +# +def flush_old (): + for file in os.listdir('.'): + if os.path.isfile(file): + if os.stat(file)[stat.ST_MTIME] < delete_date: + if Options["No-Action"]: + print "I: Would delete '%s'." % (os.path.basename(file)); + else: + if Options["Verbose"]: + print "Removing '%s' (to '%s')." % (os.path.basename(file), del_dir); + remove(file); + else: + if Options["Verbose"]: + print "Skipping, too new, '%s'." % (os.path.basename(file)); + +# Removes any files which are old orphans (not associated with a valid .changes file). +# [Used for Incoming] +# +def flush_orphans (): + all_files = {}; + changes_files = []; + # Build up the list of all files in the directory for i in os.listdir('.'): if os.path.isfile(i): all_files[i] = 1; - if re_ischanges.search(i) != None: + if i.endswith(".changes"): changes_files.append(i); # Proces all .changes and .dsc files. for changes_filename in changes_files: try: - changes = utils.parse_changes(changes_filename) - except: - continue; - try: - files = utils.build_file_list(changes, ""); + changes = utils.parse_changes(changes_filename); + files = utils.build_file_list(changes); except: + utils.warn("error processing '%s'; skipping it. [Got %s]" % (changes_filename, sys.exc_type)); continue; dsc_files = {}; for file in files.keys(): - if re_isdsc.search(file) != None: + if file.endswith(".dsc"): try: - dsc = utils.parse_changes(file) + dsc = utils.parse_changes(file); + dsc_files = utils.build_file_list(dsc, is_a_dsc=1); except: - continue; - try: - dsc_files = utils.build_file_list(dsc, 1) - except: - continue; - - # If passed -m/--mail, assume in REJECT/ and send appropriate mails - if Cnf["Shania::Options::Mail"]: - reason_filename = re_ischanges.sub('.reason', changes_filename); - if not os.access(reason_filename, os.R_OK): - sys.stderr.write("W: %s lacks a (readable) reason file ('%s').\n" % (changes_filename, reason_filename)); - continue; - - if os.stat(reason_filename)[stat.ST_MTIME] > delete_date: - # Ensure the files aren't later deleted. - for keys in (files.keys(), dsc_files.keys(), changes_filename, reason_filename): - for i in keys: - if all_files.has_key(i): - del all_files[i]; - - # Grab a copy of the .changes and .reason files for inclusion in the mail - try: - changes_contents = file_to_string(changes_filename); - except utils.cant_open_exc: - sys.stderr.write("W: %s lacks a (readable) changes file ('%s').\n" % (changes_filename, changes_filename)); + utils.warn("error processing '%s'; skipping it. [Got %s]" % (file, sys.exc_type)); continue; - reason_contents = file_to_string(reason_filename); - - # Fix the maintainer address to be RFC-822 compatible - (changes["maintainer822"], changes["maintainername"], changes["maintaineremail"]) = utils.fix_maintainer (changes["maintainer"]) - - if Cnf["Shania::Options::No-Action"]: - print "Would send a reminder email to %s." % (changes["maintainer822"]); - else: # FIXME: need msg to be configurable - mail_message = """Return-Path: %s -From: %s -To: %s -Bcc: troup@auric.debian.org -Subject: Reminder: %s was rejected - -This is an automated reminder. Your Debian upload was rejected. Its -files are in %s/REJECT on %s. - -If the upload has been superceded, please delete it. If not, please -correct the error. You do not have to reupload good files; simply -move them from incoming/REJECT to incoming. Do erase any bad files. -This reminder is sent on Monday mornings. After two reminders, the -upload is deleted. - ----------------------------------------------------------------------- -%s ----------------------------------------------------------------------- - ----------------------------------------------------------------------- -%s ----------------------------------------------------------------------- - --- -Debian distribution maintenance software -""" % (Cnf["Dinstall::MyEmailAddress"], Cnf["Dinstall::MyEmailAddress"], changes["maintainer822"], changes_filename, Cnf["Dir::IncomingDir"], Cnf["Archive::%s::OriginServer" % (utils.where_am_i())], changes_contents, reason_contents) - utils.send_mail(mail_message, ""); - if Cnf["Shania::Options::Verbose"]: - print "Sent reminder email to %s." % (changes["maintainer822"]); - else: - # Ensure the files aren't deleted - for keys in (files.keys(), dsc_files.keys(), changes_filename): - for i in keys: - if all_files.has_key(i): - del all_files[i]; - - # Anthing left at this stage is not referenced by a .changes or - # .dsc and should be deleted if old enough. + # Ensure all the files we've seen aren't deleted + keys = []; + for i in (files.keys(), dsc_files.keys(), [changes_filename]): + keys.extend(i); + for key in keys: + if all_files.has_key(key): + if Options["Verbose"]: + print "Skipping, has parents, '%s'." % (key); + del all_files[key]; + + # Anthing left at this stage is not referenced by a .changes (or + # a .dsc) and should be deleted if old enough. for file in all_files.keys(): if os.stat(file)[stat.ST_MTIME] < delete_date: - if Cnf["Shania::Options::No-Action"]: - print "Would delete '%s'." % (os.path.basename(file)); + if Options["No-Action"]: + print "I: Would delete '%s'." % (os.path.basename(file)); else: - if Cnf["Shania::Options::Verbose"]: + if Options["Verbose"]: print "Removing '%s' (to '%s')." % (os.path.basename(file), del_dir); - utils.move(file, del_dir); + remove(file); else: - if Cnf["Shania::Options::Verbose"]: + if Options["Verbose"]: print "Skipping, too new, '%s'." % (os.path.basename(file)); +################################################################################ + +def main (): + global Cnf, Options; + + Cnf = utils.get_conf() + + for i in ["Help", "Incoming", "No-Action", "Verbose" ]: + if not Cnf.has_key("Shania::Options::%s" % (i)): + Cnf["Shania::Options::%s" % (i)] = ""; + if not Cnf.has_key("Shania::Options::Days"): + Cnf["Shania::Options::Days"] = "14"; + + Arguments = [('h',"help","Shania::Options::Help"), + ('d',"days","Shania::Options::Days", "IntLevel"), + ('i',"incoming","Shania::Options::Incoming", "HasArg"), + ('n',"no-action","Shania::Options::No-Action"), + ('v',"verbose","Shania::Options::Verbose")]; + + apt_pkg.ParseCommandLine(Cnf,Arguments,sys.argv); + Options = Cnf.SubTree("Shania::Options") + + if Options["Help"]: + usage(); + + init(); + + if Options["Verbose"]: + print "Processing incoming..." + flush_orphans(); + + if os.path.exists("REJECT") and os.path.isdir("REJECT"): + if Options["Verbose"]: + print "Processing incoming/REJECT..." + os.chdir("REJECT"); + flush_old(); + ####################################################################################### if __name__ == '__main__': - main() + main();