X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=utils.py;h=96c61dbfc95d9e94476f6707d123fcb56614dbcb;hb=c279afcedf5878810de6280d3cb45c62e04c416d;hp=71b44fc3b1a46ae6c26f0eb6fbbee9bfda92fd96;hpb=e84597db51975546f2a3dfb25d5e47780cc031e9;p=dak.git diff --git a/utils.py b/utils.py index 71b44fc3..96c61dbf 100644 --- a/utils.py +++ b/utils.py @@ -1,6 +1,6 @@ # Utility functions -# Copyright (C) 2000 James Troup -# $Id: utils.py,v 1.25 2001-06-01 00:17:45 troup Exp $ +# Copyright (C) 2000, 2001 James Troup +# $Id: utils.py,v 1.40 2002-03-14 14:12:04 ajt 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 @@ -16,7 +16,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -import commands, os, pwd, re, socket, shutil, stat, string, sys, tempfile +import commands, os, pwd, re, socket, shutil, string, sys, tempfile import apt_pkg re_comments = re.compile(r"\#.*") @@ -24,14 +24,12 @@ re_no_epoch = re.compile(r"^\d*\:") re_no_revision = re.compile(r"\-[^-]*$") re_arch_from_filename = re.compile(r"/binary-[^/]+/") re_extract_src_version = re.compile (r"(\S+)\s*\((.*)\)") -re_isadeb = re.compile (r".*\.u?deb$"); -re_issource = re.compile (r"(.+)_(.+?)\.(orig\.tar\.gz|diff\.gz|tar\.gz|dsc)"); +re_isadeb = re.compile (r"(.+?)_(.+?)_(.+)\.u?deb$"); +re_issource = re.compile (r"(.+)_(.+?)\.(orig\.tar\.gz|diff\.gz|tar\.gz|dsc)$"); -re_begin_pgp_signature = re.compile("^-----BEGIN PGP SIGNATURE"); -re_begin_pgp_signed_msg = re.compile("^-----BEGIN PGP SIGNED MESSAGE"); re_single_line_field = re.compile(r"^(\S*)\s*:\s*(.*)"); -re_multi_line_description = re.compile(r"^ \.$"); re_multi_line_field = re.compile(r"^\s(.*)"); +re_taint_free = re.compile(r"^[-+\.\w]+$"); re_parse_maintainer = re.compile(r"^\s*(\S.*\S)\s*\<([^\> \t]+)\>"); @@ -45,27 +43,36 @@ cant_overwrite_exc = "Permission denied; can't overwrite existent file." file_exists_exc = "Destination file exists"; send_mail_invalid_args_exc = "Both arguments are non-null."; sendmail_failed_exc = "Sendmail invocation failed"; +tried_too_hard_exc = "Tried too hard to find a free filename."; + +default_config = "/etc/katie/katie.conf"; +default_apt_config = "/etc/katie/apt.conf"; ###################################################################################### -def open_file(filename, mode): +def open_file(filename, mode='r'): try: f = open(filename, mode); except IOError: raise cant_open_exc, filename return f +def touch_file(filename): + fd = os.open(filename, os.O_RDONLY | os.O_CREAT); + os.close(fd); + ###################################################################################### -# From reportbug -def our_raw_input(): - sys.stdout.flush() +def our_raw_input(prompt=""): + if prompt: + sys.stdout.write(prompt); + sys.stdout.flush(); try: - ret = raw_input() + ret = raw_input(); return ret except EOFError: - sys.stderr.write('\nUser interrupt (^D).\n') - raise SystemExit + sys.stderr.write('\nUser interrupt (^D).\n'); + raise SystemExit; ###################################################################################### @@ -77,23 +84,30 @@ def str_isnum (s): ###################################################################################### -# What a mess. FIXME def extract_component_from_section(section): component = ""; - - if string.find(section, '/') != -1: + + if string.find(section, '/') != -1: component = string.split(section, '/')[0]; if string.lower(component) == "non-us" and string.count(section, '/') > 0: - s = string.split(section, '/')[1]; - if s == "main" or s == "non-free" or s == "contrib": # Avoid e.g. non-US/libs - component = string.split(section, '/')[0]+ '/' + string.split(section, '/')[1]; + s = component + '/' + string.split(section, '/')[1]; + if Cnf.has_key("Component::%s" % s): # Avoid e.g. non-US/libs + component = s; if string.lower(section) == "non-us": component = "non-US/main"; - + + # non-US prefix is case insensitive + if string.lower(component)[:6] == "non-us": + component = "non-US"+component[6:]; + + # Expand default component if component == "": - component = "main"; - elif string.lower(component) == "non-us": + if Cnf.has_key("Component::%s" % section): + component = section; + else: + component = "main"; + elif component == "non-US": component = "non-US/main"; return (section, component); @@ -114,12 +128,12 @@ def extract_component_from_section(section): # "-----BEGIN PGP SIGNATURE-----". def parse_changes(filename, dsc_whitespace_rules): - changes_in = open_file(filename,'r'); + changes_in = open_file(filename); error = ""; changes = {}; lines = changes_in.readlines(); - if lines == []: + if not lines: raise changes_parse_error_exc, "[Empty changes file]"; # Reindex by line number so we can easily verify the format of @@ -143,13 +157,13 @@ def parse_changes(filename, dsc_whitespace_rules): if index > max(indices): raise invalid_dsc_format_exc, index; line = indexed_lines[index]; - if not re_begin_pgp_signature.match(line): + if string.find(line, "-----BEGIN PGP SIGNATURE") != 0: raise invalid_dsc_format_exc, index; inside_signature = 0; break; - if re_begin_pgp_signature.match(line): + if string.find(line, "-----BEGIN PGP SIGNATURE") == 0: break; - if re_begin_pgp_signed_msg.match(line): + if string.find(line, "-----BEGIN PGP SIGNED MESSAGE") == 0: if dsc_whitespace_rules: inside_signature = 1; while index < max(indices) and line != "": @@ -162,8 +176,7 @@ def parse_changes(filename, dsc_whitespace_rules): changes[field] = slf.groups()[1]; first = 1; continue; - mld = re_multi_line_description.match(line); - if mld: + if line == " .": changes[field] = changes[field] + '\n'; continue; mlf = re_multi_line_field.match(line); @@ -177,7 +190,7 @@ def parse_changes(filename, dsc_whitespace_rules): if dsc_whitespace_rules and inside_signature: raise invalid_dsc_format_exc, index; - + changes_in.close(); changes["filecontents"] = string.join (lines, ""); @@ -196,12 +209,12 @@ def build_file_list(changes, dsc): if format != "": format = float(format) if dsc == "" and (format < 1.5 or format > 2.0): - raise nk_format_exc, changes["format"]; + raise nk_format_exc, format; # No really, this has happened. Think 0 length .dsc file. if not changes.has_key("files"): raise no_files_exc - + for i in string.split(changes["files"], "\n"): if i == "": break @@ -219,7 +232,7 @@ def build_file_list(changes, dsc): if priority == "": priority = "-" (section, component) = extract_component_from_section(section); - + files[name] = { "md5sum" : md5, "size" : size, "section": section, @@ -236,7 +249,7 @@ def build_file_list(changes, dsc): # 06:28| 'The standard sucks, but my tool is supposed to # interoperate with it. I know - I'll fix the suckage # and make things incompatible!' - + def fix_maintainer (maintainer): m = re_parse_maintainer.match(maintainer); rfc822 = maintainer @@ -253,9 +266,6 @@ def fix_maintainer (maintainer): # sendmail wrapper, takes _either_ a message string or a file as arguments def send_mail (message, filename): - #### FIXME, how do I get this out of Cnf in katie? - sendmail_command = "/usr/sbin/sendmail -odq -oi -t"; - # Sanity check arguments if message != "" and filename != "": raise send_mail_invalid_args_exc; @@ -268,7 +278,7 @@ def send_mail (message, filename): os.close (fd); # Invoke sendmail - (result, output) = commands.getstatusoutput("%s < %s" % (sendmail_command, filename)); + (result, output) = commands.getstatusoutput("%s < %s" % (Cnf["Dinstall::SendmailCommand"], filename)); if (result != 0): raise sendmail_failed_exc, output; @@ -291,7 +301,7 @@ def poolify (source, component): ###################################################################################### -def move (src, dest, overwrite = 0): +def move (src, dest, overwrite = 0, perms = 0664): if os.path.exists(dest) and os.path.isdir(dest): dest_dir = dest; else: @@ -311,10 +321,10 @@ def move (src, dest, overwrite = 0): if not os.access(dest, os.W_OK): raise cant_overwrite_exc shutil.copy2(src, dest); - os.chmod(dest, 0664); + os.chmod(dest, perms); os.unlink(src); -def copy (src, dest, overwrite = 0): +def copy (src, dest, overwrite = 0, perms = 0664): if os.path.exists(dest) and os.path.isdir(dest): dest_dir = dest; else: @@ -334,46 +344,31 @@ def copy (src, dest, overwrite = 0): if not os.access(dest, os.W_OK): raise cant_overwrite_exc shutil.copy2(src, dest); - os.chmod(dest, 0664); + os.chmod(dest, perms); ###################################################################################### -# FIXME: this is inherently nasty. Can't put this mapping in a conf -# file because the conf file depends on the archive.. doh. Maybe an -# archive independent conf file is needed. - def where_am_i (): res = socket.gethostbyaddr(socket.gethostname()); - if res[0] == 'pandora.debian.org': - return 'non-US'; - elif res[0] == 'auric.debian.org': - return 'ftp-master'; + database_hostname = Cnf.get("Config::" + res[0] + "::DatabaseHostname"); + if database_hostname: + return database_hostname; else: - raise unknown_hostname_exc, res; - -###################################################################################### - -# FIXME: this isn't great either. + return res[0]; def which_conf_file (): - archive = where_am_i (); - if archive == 'non-US': - return '/org/non-us.debian.org/katie/katie.conf-non-US'; - elif archive == 'ftp-master': - return '/org/ftp.debian.org/katie/katie.conf'; + res = socket.gethostbyaddr(socket.gethostname()); + if Cnf.get("Config::" + res[0] + "::KatieConfig"): + return Cnf["Config::" + res[0] + "::KatieConfig"] else: - raise unknown_hostname_exc, archive - -# FIXME: if the above isn't great, this can't be either :) + return default_config; def which_apt_conf_file (): - archive = where_am_i (); - if archive == 'non-US': - return '/org/non-us.debian.org/katie/apt.conf-non-US'; - elif archive == 'ftp-master': - return '/org/ftp.debian.org/katie/apt.conf'; + res = socket.gethostbyaddr(socket.gethostname()); + if Cnf.get("Config::" + res[0] + "::AptConfig"): + return Cnf["Config::" + res[0] + "::AptConfig"] else: - raise unknown_hostname_exc, archive + return default_apt_config; ###################################################################################### @@ -387,7 +382,7 @@ def regex_safe (s): ###################################################################################### -# Perform a substition of template +# Perform a substition of template def TemplateSubst(Map,Template): for x in Map.keys(): Template = string.replace(Template,x,Map[x]); @@ -436,14 +431,14 @@ def cc_fix_changes (changes): def changes_compare (a, b): try: a_changes = parse_changes(a, 0) - except changes_parse_error_exc, line: + except: return -1; try: b_changes = parse_changes(b, 0) - except changes_parse_error_exc, line: + except: return 1; - + cc_fix_changes (a_changes); cc_fix_changes (b_changes); @@ -457,7 +452,7 @@ def changes_compare (a, b): return 1; # Sort by source name - + a_source = a_changes.get("source"); b_source = b_changes.get("source"); q = cmp (a_source, b_source); @@ -477,3 +472,47 @@ def changes_compare (a, b): return cmp(a, b); ################################################################################ + +def find_next_free (dest, too_many=100): + extra = 0; + orig_dest = dest; + while os.path.exists(dest) and extra < too_many: + dest = orig_dest + '.' + repr(extra); + extra = extra + 1; + if extra >= too_many: + raise tried_too_hard_exc; + return dest; + +################################################################################ + +def result_join (original, sep = '\t'): + list = []; + for i in xrange(len(original)): + if original[i] == None: + list.append(""); + else: + list.append(original[i]); + return string.join(list, sep); + +def plural (x): + if x > 1: + return "s"; + else: + return ""; + +################################################################################ + +def get_conf(): + return Cnf; + +################################################################################ + +apt_pkg.init() + +Cnf = apt_pkg.newConfiguration(); +apt_pkg.ReadConfigFileISC(Cnf,default_config); + +if which_conf_file() != default_config: + apt_pkg.ReadConfigFileISC(Cnf,which_conf_file()) + +################################################################################