+#!/usr/bin/env python
+
# Utility functions
# Copyright (C) 2000, 2001, 2002 James Troup <james@nocrew.org>
-# $Id: utils.py,v 1.48 2002-06-22 22:34:35 troup Exp $
+# $Id: utils.py,v 1.53 2002-11-26 15:49:16 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
# 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, string, sys, tempfile
-import apt_pkg
+################################################################################
+
+import commands, os, pwd, re, socket, shutil, string, sys, tempfile, traceback;
+import apt_pkg;
+import db_access;
+
+################################################################################
re_comments = re.compile(r"\#.*")
re_no_epoch = re.compile(r"^\d*\:")
def extract_component_from_section(section):
component = "";
- if string.find(section, '/') != -1:
- component = string.split(section, '/')[0];
- if string.lower(component) == "non-us" and string.count(section, '/') > 0:
- s = component + '/' + string.split(section, '/')[1];
+ if section.find('/') != -1:
+ component = section.split('/')[0];
+ if component.lower() == "non-us" and section.count('/') > 0:
+ s = component + '/' + section.split('/')[1];
if Cnf.has_key("Component::%s" % s): # Avoid e.g. non-US/libs
component = s;
- if string.lower(section) == "non-us":
+ if section.lower() == "non-us":
component = "non-US/main";
# non-US prefix is case insensitive
- if string.lower(component)[:6] == "non-us":
+ if component.lower()[:6] == "non-us":
component = "non-US"+component[6:];
# Expand default component
index = 0;
indexed_lines = {};
for line in lines:
- index = index + 1;
+ index += 1;
indexed_lines[index] = line[:-1];
inside_signature = 0;
indices = indexed_lines.keys()
index = 0;
+ first = -1;
while index < max(indices):
- index = index + 1;
+ index += 1;
line = indexed_lines[index];
if line == "":
if dsc_whitespace_rules:
- index = index + 1;
+ index += 1;
if index > max(indices):
raise invalid_dsc_format_exc, index;
line = indexed_lines[index];
- if string.find(line, "-----BEGIN PGP SIGNATURE") != 0:
+ if not line.startswith("-----BEGIN PGP SIGNATURE"):
raise invalid_dsc_format_exc, index;
inside_signature = 0;
break;
- if string.find(line, "-----BEGIN PGP SIGNATURE") == 0:
+ if line.startswith("-----BEGIN PGP SIGNATURE"):
break;
- if string.find(line, "-----BEGIN PGP SIGNED MESSAGE") == 0:
+ if line.startswith("-----BEGIN PGP SIGNED MESSAGE"):
if dsc_whitespace_rules:
inside_signature = 1;
while index < max(indices) and line != "":
- index = index + 1;
+ index += 1;
line = indexed_lines[index];
continue;
slf = re_single_line_field.match(line);
if slf:
- field = string.lower(slf.groups()[0]);
+ field = slf.groups()[0].lower();
changes[field] = slf.groups()[1];
first = 1;
continue;
if line == " .":
- changes[field] = changes[field] + '\n';
+ changes[field] += '\n';
continue;
mlf = re_multi_line_field.match(line);
if mlf:
+ if first == -1:
+ raise changes_parse_error_exc, "'%s'\n [Multi-line field continuing on from nothing?]" % (line);
if first == 1 and changes[field] != "":
- changes[field] = changes[field] + '\n';
+ changes[field] += '\n';
first = 0;
- changes[field] = changes[field] + mlf.groups()[0] + '\n';
+ changes[field] += mlf.groups()[0] + '\n';
continue;
- error = error + line;
+ error += line;
if dsc_whitespace_rules and inside_signature:
raise invalid_dsc_format_exc, index;
changes_in.close();
- changes["filecontents"] = string.join (lines, "");
+ changes["filecontents"] = "".join(lines);
if error != "":
raise changes_parse_error_exc, error;
if not changes.has_key("files"):
raise no_files_exc
- for i in string.split(changes["files"], "\n"):
+ for i in changes["files"].split("\n"):
if i == "":
break
- s = string.split(i)
+ s = i.split();
section = priority = "";
try:
if is_a_dsc:
if m != None and len(m.groups()) == 2:
name = m.group(1)
email = m.group(2)
- if string.find(name, ',') != -1 or string.find(name, '.') != -1:
+ if name.find(',') != -1 or name.find('.') != -1:
rfc822 = re_parse_maintainer.sub(r"\2 (\1)", maintainer)
return (rfc822, name, email)
def poolify (source, component):
if component != "":
- component = component + '/';
+ component += '/';
# FIXME: this is nasty
- component = string.lower(component);
- component = string.replace(component, 'non-us/', 'non-US/');
+ component = component.lower().replace('non-us/', 'non-US/');
if source[:3] == "lib":
return component + source[:4] + '/' + source + '/'
else:
os.umask(umask);
#print "Moving %s to %s..." % (src, dest);
if os.path.exists(dest) and os.path.isdir(dest):
- dest = dest + '/' + os.path.basename(src);
+ dest += '/' + os.path.basename(src);
# Don't overwrite unless forced to
if os.path.exists(dest):
if not overwrite:
os.umask(umask);
#print "Copying %s to %s..." % (src, dest);
if os.path.exists(dest) and os.path.isdir(dest):
- dest = dest + '/' + os.path.basename(src);
+ dest += '/' + os.path.basename(src);
# Don't overwrite unless forced to
if os.path.exists(dest):
if not overwrite:
# (woefully incomplete)
def regex_safe (s):
- s = string.replace(s, '+', '\\\\+');
- s = string.replace(s, '.', '\\\\.');
+ s = s.replace('+', '\\\\+');
+ s = s.replace('.', '\\\\.');
return s
######################################################################################
file = open_file(filename);
template = file.read();
for x in map.keys():
- template = string.replace(template,x,map[x]);
+ template = template.replace(x,map[x]);
file.close();
return template;
# Returns the user name with a laughable attempt at rfc822 conformancy
# (read: removing stray periods).
def whoami ():
- return string.replace(string.split(pwd.getpwuid(os.getuid())[4],',')[0], '.', '');
+ return pwd.getpwuid(os.getuid())[4].split(',')[0].replace('.', '');
######################################################################################
if o != "":
del changes["architecture"]
changes["architecture"] = {}
- for j in string.split(o):
+ for j in o.split():
changes["architecture"][j] = 1
# Sort by source name, source version, 'have source', and then by filename
orig_dest = dest;
while os.path.exists(dest) and extra < too_many:
dest = orig_dest + '.' + repr(extra);
- extra = extra + 1;
+ extra += 1;
if extra >= too_many:
raise tried_too_hard_exc;
return dest;
list.append("");
else:
list.append(original[i]);
- return string.join(list, sep);
+ return sep.join(list);
################################################################################
def prefix_multi_line_string(str, prefix):
out = "";
- for line in string.split(str, '\n'):
- line = string.strip(line);
+ for line in str.split('\n'):
+ line = line.strip();
if line:
- out = out + "%s%s\n" % (prefix, line);
+ out += "%s%s\n" % (prefix, line);
# Strip trailing new line
if out:
out = out[:-1];
error = None;
orig_filename = file
- if file[-6:] == ".katie":
+ if file.endswith(".katie"):
file = file[:-6]+".changes";
- if file[-8:] != ".changes":
+ if not file.endswith(".changes"):
error = "invalid file type; not a changes file";
else:
if not os.access(file,os.R_OK):
################################################################################
+def join_with_commas_and(list):
+ if len(list) == 0: return "nothing";
+ if len(list) == 1: return list[0];
+ return ", ".join(list[:-1]) + " and " + list[-1];
+
+################################################################################
+
def get_conf():
return Cnf;
################################################################################
+# Handle -a, -c and -s arguments; returns them as SQL constraints
+def parse_args(Options):
+ # Process suite
+ if Options["Suite"]:
+ suite_ids_list = [];
+ for suite in Options["Suite"].split():
+ suite_id = db_access.get_suite_id(suite);
+ if suite_id == -1:
+ warn("suite '%s' not recognised." % (suite));
+ else:
+ suite_ids_list.append(suite_id);
+ if suite_ids_list:
+ con_suites = "AND su.id IN (%s)" % ", ".join(map(str, suite_ids_list));
+ else:
+ fubar("No valid suite given.");
+ else:
+ con_suites = "";
+
+ # Process component
+ if Options["Component"]:
+ component_ids_list = [];
+ for component in Options["Component"].split():
+ component_id = db_access.get_component_id(component);
+ if component_id == -1:
+ warn("component '%s' not recognised." % (component));
+ else:
+ component_ids_list.append(component_id);
+ if component_ids_list:
+ con_components = "AND c.id IN (%s)" % ", ".join(map(str, component_ids_list));
+ else:
+ fubar("No valid component given.");
+ else:
+ con_components = "";
+
+ # Process architecture
+ con_architectures = "";
+ if Options["Architecture"]:
+ arch_ids_list = [];
+ check_source = 0;
+ for architecture in Options["Architecture"].split():
+ if architecture == "source":
+ check_source = 1;
+ else:
+ architecture_id = db_access.get_architecture_id(architecture);
+ if architecture_id == -1:
+ warn("architecture '%s' not recognised." % (architecture));
+ else:
+ arch_ids_list.append(architecture_id);
+ if arch_ids_list:
+ con_architectures = "AND a.id IN (%s)" % ", ".join(map(str, arch_ids_list));
+ else:
+ if not check_source:
+ fubar("No valid architecture given.");
+ else:
+ check_source = 1;
+
+ return (con_suites, con_architectures, con_components, check_source);
+
+################################################################################
+
+# Inspired(tm) by Bryn Keller's print_exc_plus (See
+# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52215)
+
+def print_exc():
+ tb = sys.exc_info()[2];
+ while tb.tb_next:
+ tb = tb.tb_next;
+ stack = [];
+ frame = tb.tb_frame;
+ while frame:
+ stack.append(frame);
+ frame = frame.f_back;
+ stack.reverse();
+ traceback.print_exc();
+ for frame in stack:
+ print "\nFrame %s in %s at line %s" % (frame.f_code.co_name,
+ frame.f_code.co_filename,
+ frame.f_lineno);
+ for key, value in frame.f_locals.items():
+ print "\t%20s = " % key,;
+ try:
+ print value;
+ except:
+ print "<unable to print>";
+
+################################################################################
+
+def try_with_debug(function):
+ try:
+ function();
+ except SystemExit:
+ raise;
+ except:
+ print_exc();
+
+################################################################################
+
apt_pkg.init()
Cnf = apt_pkg.newConfiguration();