# Copyright (C) 2001 Martin Michlmayr # $Id$ # 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 # This is a collection of software to track down developers who are # Missing In Action (MIA). # To Veronika, who is missing in action -- action's not the same without her. # -- tbm import os, stat, sys, re, time, string days = 21 origin = '/org/qa.debian.org/mia/db' info = { } matches = { } def find_status(path=origin): files = [] for file in os.listdir(path): root, ext = os.path.splitext(file) if ext == '.summary': files.append(root) return files def read_status(files): for file in files: try: summary = open(origin + '/' + file + '.summary', 'r') except IOError: print 'Cannot open summary file %s' % file sys.exit(1) info[file] = { } for line in summary.readlines(): result = re.search("(\d+):\s*(.*)", line) if result is not None: info[file][int(result.group(1))] = result.group(2) else: print 'Error parsing file %s: %s' % (file, line) sys.exit(1) summary.close() def write_status(file, id, summary): try: status = open(origin + '/' + file + '.summary', 'a') except IOError: print 'Cannot open summary file to write!' sys.exit(1) string = str(id) + ': ' + summary + '\n' status.write(string) status.close() def print_history(file): all_contacts = info[file].keys() all_contacts.sort() for when in all_contacts: date = time.gmtime(int(when)) print ' %s: %.60s' % (time.strftime('%Y-%m-%d', date), info[file][when]) def latest(file): return max(info[file].keys()) def compile_matches(): matches['ignore'] = [ 'willfix' ] matches['in'] = [ 'S-V', 'FHS', 'RC', 'NMU', 'Hint' ] matches['out'] = [ 'Fixed', 'Orphaned', 'Orphaning', 'Removed', 'Removing' ] matches['latest'] = [ 'Maintainer has no packages anymore', 'Retired', 'Retiring' ] for key in matches.keys(): matches[key] = map(string.lower, matches[key]) def last_is_final(file): if string.lower(info[file][latest(file)]) in matches['latest']: return 1 def has_stuff_todo(file): if last_is_final(file): return found = { } for key in matches.keys(): found[key] = { } for entry in info[file].values(): fields = re.split(':\s+', entry, 2) if len(fields) > 1: what = re.split('\s+|&', fields[0])[0] packages = re.split(',\s*', fields[1]) for key in matches.keys(): if string.lower(what) in matches[key]: for package in packages: found[key][package] = 1 break else: print 'Error: do not know what to do with "%s"' % what sys.exit(1) # temporary hack to show cases without any INs. if not len(found['in']): return [ 'no-todo-list' ] for item in found['out'].keys(): try: del found['in'][item] except KeyError: print 'Warning: "%s" was not on the TODO list' % item if len(found['in']): # something has not been dealt with yet outstanding = found['in'].keys() outstanding.sort() return outstanding # 'main()' compile_matches()