#!/usr/bin/env python
# Utility functions
-# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 James Troup <james@nocrew.org>
+# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 James Troup <james@nocrew.org>
# $Id: utils.py,v 1.73 2005-03-18 05:24:38 troup Exp $
################################################################################
################################################################################
import codecs, commands, email.Header, os, pwd, re, select, socket, shutil, \
- string, sys, tempfile, traceback;
-import apt_pkg;
-import db_access;
+ string, sys, tempfile, traceback
+import apt_pkg
+import dak.lib.database
################################################################################
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_single_line_field = re.compile(r"^(\S*)\s*:\s*(.*)");
-re_multi_line_field = re.compile(r"^\s(.*)");
-re_taint_free = re.compile(r"^[-+~/\.\w]+$");
+re_single_line_field = re.compile(r"^(\S*)\s*:\s*(.*)")
+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*\<([^\>]+)\>");
+re_parse_maintainer = re.compile(r"^\s*(\S.*\S)\s*\<([^\>]+)\>")
-changes_parse_error_exc = "Can't parse line in .changes file";
-invalid_dsc_format_exc = "Invalid .dsc file";
-nk_format_exc = "Unknown Format: in .changes file";
-no_files_exc = "No Files: field in .dsc or .changes file.";
-cant_open_exc = "Can't open file";
-unknown_hostname_exc = "Unknown hostname";
+changes_parse_error_exc = "Can't parse line in .changes file"
+invalid_dsc_format_exc = "Invalid .dsc file"
+nk_format_exc = "Unknown Format: in .changes file"
+no_files_exc = "No Files: field in .dsc or .changes file."
+cant_open_exc = "Can't open file"
+unknown_hostname_exc = "Unknown hostname"
cant_overwrite_exc = "Permission denied; can't overwrite existent file."
-file_exists_exc = "Destination file exists";
-sendmail_failed_exc = "Sendmail invocation failed";
-tried_too_hard_exc = "Tried too hard to find a free filename.";
+file_exists_exc = "Destination file exists"
+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";
+default_config = "/etc/dak/dak.conf"
+default_apt_config = "/etc/dak/apt.conf"
################################################################################
class Error(Exception):
"""Base class for exceptions in this module."""
- pass;
+ pass
class ParseMaintError(Error):
"""Exception raised for errors in parsing a maintainer field.
"""
def __init__(self, message):
- self.args = message,;
- self.message = message;
+ self.args = message,
+ self.message = message
################################################################################
def open_file(filename, mode='r'):
try:
- f = open(filename, mode);
+ f = open(filename, mode)
except IOError:
- raise cant_open_exc, filename;
+ raise cant_open_exc, filename
return f
################################################################################
def our_raw_input(prompt=""):
if prompt:
- sys.stdout.write(prompt);
- sys.stdout.flush();
+ sys.stdout.write(prompt)
+ sys.stdout.flush()
try:
- ret = raw_input();
- return ret;
+ 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
################################################################################
def str_isnum (s):
for c in s:
if c not in string.digits:
- return 0;
- return 1;
+ return 0
+ return 1
################################################################################
def extract_component_from_section(section):
- component = "";
+ component = ""
if section.find('/') != -1:
- component = section.split('/')[0];
+ component = section.split('/')[0]
if component.lower() == "non-us" and section.find('/') != -1:
- s = component + '/' + section.split('/')[1];
+ s = component + '/' + section.split('/')[1]
if Cnf.has_key("Component::%s" % s): # Avoid e.g. non-US/libs
- component = s;
+ component = s
if section.lower() == "non-us":
- component = "non-US/main";
+ component = "non-US/main"
# non-US prefix is case insensitive
if component.lower()[:6] == "non-us":
- component = "non-US"+component[6:];
+ component = "non-US"+component[6:]
# Expand default component
if component == "":
if Cnf.has_key("Component::%s" % section):
- component = section;
+ component = section
else:
- component = "main";
+ component = "main"
elif component == "non-US":
- component = "non-US/main";
+ component = "non-US/main"
- return (section, component);
+ return (section, component)
################################################################################
"-----BEGIN PGP SIGNATURE-----".
"""
- error = "";
- changes = {};
+ error = ""
+ changes = {}
- changes_in = open_file(filename);
- lines = changes_in.readlines();
+ changes_in = open_file(filename)
+ lines = changes_in.readlines()
if not lines:
- raise changes_parse_error_exc, "[Empty changes file]";
+ raise changes_parse_error_exc, "[Empty changes file]"
# Reindex by line number so we can easily verify the format of
# .dsc files...
- index = 0;
- indexed_lines = {};
+ index = 0
+ indexed_lines = {}
for line in lines:
- index += 1;
- indexed_lines[index] = line[:-1];
+ index += 1
+ indexed_lines[index] = line[:-1]
- inside_signature = 0;
+ inside_signature = 0
- num_of_lines = len(indexed_lines.keys());
- index = 0;
- first = -1;
+ num_of_lines = len(indexed_lines.keys())
+ index = 0
+ first = -1
while index < num_of_lines:
- index += 1;
- line = indexed_lines[index];
+ index += 1
+ line = indexed_lines[index]
if line == "":
if signing_rules == 1:
- index += 1;
+ index += 1
if index > num_of_lines:
- raise invalid_dsc_format_exc, index;
- line = indexed_lines[index];
+ raise invalid_dsc_format_exc, index
+ line = indexed_lines[index]
if not line.startswith("-----BEGIN PGP SIGNATURE"):
- raise invalid_dsc_format_exc, index;
- inside_signature = 0;
- break;
+ raise invalid_dsc_format_exc, index
+ inside_signature = 0
+ break
else:
- continue;
+ continue
if line.startswith("-----BEGIN PGP SIGNATURE"):
- break;
+ break
if line.startswith("-----BEGIN PGP SIGNED MESSAGE"):
- inside_signature = 1;
+ inside_signature = 1
if signing_rules == 1:
while index < num_of_lines and line != "":
- index += 1;
- line = indexed_lines[index];
- continue;
+ index += 1
+ line = indexed_lines[index]
+ continue
# If we're not inside the signed data, don't process anything
if signing_rules >= 0 and not inside_signature:
- continue;
- slf = re_single_line_field.match(line);
+ continue
+ slf = re_single_line_field.match(line)
if slf:
- field = slf.groups()[0].lower();
- changes[field] = slf.groups()[1];
- first = 1;
- continue;
+ field = slf.groups()[0].lower()
+ changes[field] = slf.groups()[1]
+ first = 1
+ continue
if line == " .":
- changes[field] += '\n';
- continue;
- mlf = re_multi_line_field.match(line);
+ 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);
+ raise changes_parse_error_exc, "'%s'\n [Multi-line field continuing on from nothing?]" % (line)
if first == 1 and changes[field] != "":
- changes[field] += '\n';
- first = 0;
- changes[field] += mlf.groups()[0] + '\n';
- continue;
- error += line;
+ changes[field] += '\n'
+ first = 0
+ changes[field] += mlf.groups()[0] + '\n'
+ continue
+ error += line
if signing_rules == 1 and inside_signature:
- raise invalid_dsc_format_exc, index;
+ raise invalid_dsc_format_exc, index
- changes_in.close();
- changes["filecontents"] = "".join(lines);
+ changes_in.close()
+ changes["filecontents"] = "".join(lines)
if error:
- raise changes_parse_error_exc, error;
+ raise changes_parse_error_exc, error
- return changes;
+ return changes
################################################################################
# Dropped support for 1.4 and ``buggy dchanges 3.4'' (?!) compared to di.pl
def build_file_list(changes, is_a_dsc=0):
- files = {};
+ files = {}
# Make sure we have a Files: field to parse...
if not changes.has_key("files"):
- raise no_files_exc;
+ raise no_files_exc
# Make sure we recognise the format of the Files: field
- format = changes.get("format", "");
+ format = changes.get("format", "")
if format != "":
- format = float(format);
+ format = float(format)
if not is_a_dsc and (format < 1.5 or format > 2.0):
- raise nk_format_exc, format;
+ raise nk_format_exc, format
# Parse each entry/line:
for i in changes["files"].split('\n'):
if not i:
- break;
- s = i.split();
- section = priority = "";
+ break
+ s = i.split()
+ section = priority = ""
try:
if is_a_dsc:
- (md5, size, name) = s;
+ (md5, size, name) = s
else:
- (md5, size, section, priority, name) = s;
+ (md5, size, section, priority, name) = s
except ValueError:
- raise changes_parse_error_exc, i;
+ raise changes_parse_error_exc, i
if section == "":
- section = "-";
+ section = "-"
if priority == "":
- priority = "-";
+ priority = "-"
- (section, component) = extract_component_from_section(section);
+ (section, component) = extract_component_from_section(section)
files[name] = Dict(md5sum=md5, size=size, section=section,
- priority=priority, component=component);
+ priority=priority, component=component)
return files
"""Forces a string to UTF-8. If the string isn't already UTF-8,
it's assumed to be ISO-8859-1."""
try:
- unicode(s, 'utf-8');
- return s;
+ unicode(s, 'utf-8')
+ return s
except UnicodeError:
- latin1_s = unicode(s,'iso8859-1');
- return latin1_s.encode('utf-8');
+ latin1_s = unicode(s,'iso8859-1')
+ return latin1_s.encode('utf-8')
def rfc2047_encode(s):
"""Encodes a (header) string per RFC2047 if necessary. If the
string is neither ASCII nor UTF-8, it's assumed to be ISO-8859-1."""
try:
codecs.lookup('ascii')[1](s)
- return s;
+ return s
except UnicodeError:
- pass;
+ pass
try:
codecs.lookup('utf-8')[1](s)
- h = email.Header.Header(s, 'utf-8', 998);
- return str(h);
+ h = email.Header.Header(s, 'utf-8', 998)
+ return str(h)
except UnicodeError:
- h = email.Header.Header(s, 'iso-8859-1', 998);
- return str(h);
+ h = email.Header.Header(s, 'iso-8859-1', 998)
+ return str(h)
################################################################################
switched to 'email (name)' format."""
maintainer = maintainer.strip()
if not maintainer:
- return ('', '', '', '');
+ return ('', '', '', '')
if maintainer.find("<") == -1:
- email = maintainer;
- name = "";
+ email = maintainer
+ name = ""
elif (maintainer[0] == "<" and maintainer[-1:] == ">"):
- email = maintainer[1:-1];
- name = "";
+ email = maintainer[1:-1]
+ name = ""
else:
- m = re_parse_maintainer.match(maintainer);
+ m = re_parse_maintainer.match(maintainer)
if not m:
raise ParseMaintError, "Doesn't parse as a valid Maintainer field."
- name = m.group(1);
- email = m.group(2);
+ name = m.group(1)
+ email = m.group(2)
# Get an RFC2047 compliant version of the name
- rfc2047_name = rfc2047_encode(name);
+ rfc2047_name = rfc2047_encode(name)
# Force the name to be UTF-8
- name = force_to_utf8(name);
+ name = force_to_utf8(name)
if name.find(',') != -1 or name.find('.') != -1:
- rfc822_maint = "%s (%s)" % (email, name);
- rfc2047_maint = "%s (%s)" % (email, rfc2047_name);
+ rfc822_maint = "%s (%s)" % (email, name)
+ rfc2047_maint = "%s (%s)" % (email, rfc2047_name)
else:
- rfc822_maint = "%s <%s>" % (name, email);
- rfc2047_maint = "%s <%s>" % (rfc2047_name, email);
+ rfc822_maint = "%s <%s>" % (name, email)
+ rfc2047_maint = "%s <%s>" % (rfc2047_name, email)
if email.find("@") == -1 and email.find("buildd_") != 0:
raise ParseMaintError, "No @ found in email address part."
- return (rfc822_maint, rfc2047_maint, name, email);
+ return (rfc822_maint, rfc2047_maint, name, email)
################################################################################
def send_mail (message, filename=""):
# If we've been passed a string dump it into a temporary file
if message:
- filename = tempfile.mktemp();
- fd = os.open(filename, os.O_RDWR|os.O_CREAT|os.O_EXCL, 0700);
- os.write (fd, message);
- os.close (fd);
+ filename = tempfile.mktemp()
+ fd = os.open(filename, os.O_RDWR|os.O_CREAT|os.O_EXCL, 0700)
+ os.write (fd, message)
+ os.close (fd)
# Invoke sendmail
- (result, output) = commands.getstatusoutput("%s < %s" % (Cnf["Dinstall::SendmailCommand"], filename));
+ (result, output) = commands.getstatusoutput("%s < %s" % (Cnf["Dinstall::SendmailCommand"], filename))
if (result != 0):
- raise sendmail_failed_exc, output;
+ raise sendmail_failed_exc, output
# Clean up any temporary files
if message:
- os.unlink (filename);
+ os.unlink (filename)
################################################################################
def poolify (source, component):
if component:
- component += '/';
+ component += '/'
# FIXME: this is nasty
- component = component.lower().replace("non-us/", "non-US/");
+ component = component.lower().replace("non-us/", "non-US/")
if source[:3] == "lib":
return component + source[:4] + '/' + source + '/'
else:
def move (src, dest, overwrite = 0, perms = 0664):
if os.path.exists(dest) and os.path.isdir(dest):
- dest_dir = dest;
+ dest_dir = dest
else:
- dest_dir = os.path.dirname(dest);
+ dest_dir = os.path.dirname(dest)
if not os.path.exists(dest_dir):
- umask = os.umask(00000);
- os.makedirs(dest_dir, 02775);
- os.umask(umask);
- #print "Moving %s to %s..." % (src, dest);
+ umask = os.umask(00000)
+ os.makedirs(dest_dir, 02775)
+ os.umask(umask)
+ #print "Moving %s to %s..." % (src, dest)
if os.path.exists(dest) and os.path.isdir(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:
- fubar("Can't move %s to %s - file already exists." % (src, dest));
+ fubar("Can't move %s to %s - file already exists." % (src, dest))
else:
if not os.access(dest, os.W_OK):
- fubar("Can't move %s to %s - can't write to existing file." % (src, dest));
- shutil.copy2(src, dest);
- os.chmod(dest, perms);
- os.unlink(src);
+ fubar("Can't move %s to %s - can't write to existing file." % (src, dest))
+ shutil.copy2(src, dest)
+ os.chmod(dest, perms)
+ os.unlink(src)
def copy (src, dest, overwrite = 0, perms = 0664):
if os.path.exists(dest) and os.path.isdir(dest):
- dest_dir = dest;
+ dest_dir = dest
else:
- dest_dir = os.path.dirname(dest);
+ dest_dir = os.path.dirname(dest)
if not os.path.exists(dest_dir):
- umask = os.umask(00000);
- os.makedirs(dest_dir, 02775);
- os.umask(umask);
- #print "Copying %s to %s..." % (src, dest);
+ umask = os.umask(00000)
+ os.makedirs(dest_dir, 02775)
+ os.umask(umask)
+ #print "Copying %s to %s..." % (src, dest)
if os.path.exists(dest) and os.path.isdir(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:
else:
if not os.access(dest, os.W_OK):
raise cant_overwrite_exc
- shutil.copy2(src, dest);
- os.chmod(dest, perms);
+ shutil.copy2(src, dest)
+ os.chmod(dest, perms)
################################################################################
def where_am_i ():
- res = socket.gethostbyaddr(socket.gethostname());
- database_hostname = Cnf.get("Config::" + res[0] + "::DatabaseHostname");
+ res = socket.gethostbyaddr(socket.gethostname())
+ database_hostname = Cnf.get("Config::" + res[0] + "::DatabaseHostname")
if database_hostname:
- return database_hostname;
+ return database_hostname
else:
- return res[0];
+ return res[0]
def which_conf_file ():
- res = socket.gethostbyaddr(socket.gethostname());
- if Cnf.get("Config::" + res[0] + "::KatieConfig"):
- return Cnf["Config::" + res[0] + "::KatieConfig"]
+ res = socket.gethostbyaddr(socket.gethostname())
+ if Cnf.get("Config::" + res[0] + "::DakConfig"):
+ return Cnf["Config::" + res[0] + "::DakConfig"]
else:
- return default_config;
+ return default_config
def which_apt_conf_file ():
- res = socket.gethostbyaddr(socket.gethostname());
+ res = socket.gethostbyaddr(socket.gethostname())
if Cnf.get("Config::" + res[0] + "::AptConfig"):
return Cnf["Config::" + res[0] + "::AptConfig"]
else:
- return default_apt_config;
+ return default_apt_config
################################################################################
# (woefully incomplete)
def regex_safe (s):
- s = s.replace('+', '\\\\+');
- s = s.replace('.', '\\\\.');
+ s = s.replace('+', '\\\\+')
+ s = s.replace('.', '\\\\.')
return s
################################################################################
# Perform a substition of template
def TemplateSubst(map, filename):
- file = open_file(filename);
- template = file.read();
+ file = open_file(filename)
+ template = file.read()
for x in map.keys():
- template = template.replace(x,map[x]);
- file.close();
- return template;
+ template = template.replace(x,map[x])
+ file.close()
+ return template
################################################################################
def fubar(msg, exit_code=1):
- sys.stderr.write("E: %s\n" % (msg));
- sys.exit(exit_code);
+ sys.stderr.write("E: %s\n" % (msg))
+ sys.exit(exit_code)
def warn(msg):
- sys.stderr.write("W: %s\n" % (msg));
+ sys.stderr.write("W: %s\n" % (msg))
################################################################################
# Returns the user name with a laughable attempt at rfc822 conformancy
# (read: removing stray periods).
def whoami ():
- return pwd.getpwuid(os.getuid())[4].split(',')[0].replace('.', '');
+ return pwd.getpwuid(os.getuid())[4].split(',')[0].replace('.', '')
################################################################################
def size_type (c):
- t = " B";
+ t = " B"
if c > 10240:
- c = c / 1024;
- t = " KB";
+ c = c / 1024
+ t = " KB"
if c > 10240:
- c = c / 1024;
- t = " MB";
+ c = c / 1024
+ t = " MB"
return ("%d%s" % (c, t))
################################################################################
def cc_fix_changes (changes):
- o = changes.get("architecture", "");
+ o = changes.get("architecture", "")
if o:
- del changes["architecture"];
- changes["architecture"] = {};
+ del changes["architecture"]
+ changes["architecture"] = {}
for j in o.split():
- changes["architecture"][j] = 1;
+ changes["architecture"][j] = 1
# Sort by source name, source version, 'have source', and then by filename
def changes_compare (a, b):
try:
- a_changes = parse_changes(a);
+ a_changes = parse_changes(a)
except:
- return -1;
+ return -1
try:
- b_changes = parse_changes(b);
+ b_changes = parse_changes(b)
except:
- return 1;
+ return 1
- cc_fix_changes (a_changes);
- cc_fix_changes (b_changes);
+ cc_fix_changes (a_changes)
+ cc_fix_changes (b_changes)
# Sort by source name
- a_source = a_changes.get("source");
- b_source = b_changes.get("source");
- q = cmp (a_source, b_source);
+ a_source = a_changes.get("source")
+ b_source = b_changes.get("source")
+ q = cmp (a_source, b_source)
if q:
- return q;
+ return q
# Sort by source version
- a_version = a_changes.get("version", "0");
- b_version = b_changes.get("version", "0");
- q = apt_pkg.VersionCompare(a_version, b_version);
+ a_version = a_changes.get("version", "0")
+ b_version = b_changes.get("version", "0")
+ q = apt_pkg.VersionCompare(a_version, b_version)
if q:
- return q;
+ return q
# Sort by 'have source'
- a_has_source = a_changes["architecture"].get("source");
- b_has_source = b_changes["architecture"].get("source");
+ a_has_source = a_changes["architecture"].get("source")
+ b_has_source = b_changes["architecture"].get("source")
if a_has_source and not b_has_source:
- return -1;
+ return -1
elif b_has_source and not a_has_source:
- return 1;
+ return 1
# Fall back to sort by filename
- return cmp(a, b);
+ return cmp(a, b)
################################################################################
def find_next_free (dest, too_many=100):
- extra = 0;
- orig_dest = dest;
+ extra = 0
+ orig_dest = dest
while os.path.exists(dest) and extra < too_many:
- dest = orig_dest + '.' + repr(extra);
- extra += 1;
+ dest = orig_dest + '.' + repr(extra)
+ extra += 1
if extra >= too_many:
- raise tried_too_hard_exc;
- return dest;
+ raise tried_too_hard_exc
+ return dest
################################################################################
def result_join (original, sep = '\t'):
- list = [];
+ list = []
for i in xrange(len(original)):
if original[i] == None:
- list.append("");
+ list.append("")
else:
- list.append(original[i]);
- return sep.join(list);
+ list.append(original[i])
+ return sep.join(list)
################################################################################
def prefix_multi_line_string(str, prefix, include_blank_lines=0):
- out = "";
+ out = ""
for line in str.split('\n'):
- line = line.strip();
+ line = line.strip()
if line or include_blank_lines:
- out += "%s%s\n" % (prefix, line);
+ out += "%s%s\n" % (prefix, line)
# Strip trailing new line
if out:
- out = out[:-1];
- return out;
+ out = out[:-1]
+ return out
################################################################################
def validate_changes_file_arg(filename, require_changes=1):
- """'filename' is either a .changes or .katie file. If 'filename' is a
-.katie file, it's changed to be the corresponding .changes file. The
+ """'filename' is either a .changes or .dak file. If 'filename' is a
+.dak file, it's changed to be the corresponding .changes file. The
function then checks if the .changes file a) exists and b) is
readable and returns the .changes filename if so. If there's a
problem, the next action depends on the option 'require_changes'
o If 'require_changes' == 0, a warning is given and 'None' is returned.
o If 'require_changes' == 1, a fatal error is raised.
"""
- error = None;
+ error = None
orig_filename = filename
- if filename.endswith(".katie"):
- filename = filename[:-6]+".changes";
+ if filename.endswith(".dak"):
+ filename = filename[:-6]+".changes"
if not filename.endswith(".changes"):
- error = "invalid file type; not a changes file";
+ error = "invalid file type; not a changes file"
else:
if not os.access(filename,os.R_OK):
if os.path.exists(filename):
- error = "permission denied";
+ error = "permission denied"
else:
- error = "file not found";
+ error = "file not found"
if error:
if require_changes == 1:
- fubar("%s: %s." % (orig_filename, error));
+ fubar("%s: %s." % (orig_filename, error))
elif require_changes == 0:
- warn("Skipping %s - %s" % (orig_filename, error));
- return None;
- else: # We only care about the .katie file
- return filename;
+ warn("Skipping %s - %s" % (orig_filename, error))
+ return None
+ else: # We only care about the .dak file
+ return filename
else:
- return filename;
+ return filename
################################################################################
def real_arch(arch):
- return (arch != "source" and arch != "all");
+ return (arch != "source" and arch != "all")
################################################################################
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];
+ if len(list) == 0: return "nothing"
+ if len(list) == 1: return list[0]
+ return ", ".join(list[:-1]) + " and " + list[-1]
################################################################################
def pp_deps (deps):
- pp_deps = [];
+ pp_deps = []
for atom in deps:
- (pkg, version, constraint) = atom;
+ (pkg, version, constraint) = atom
if constraint:
- pp_dep = "%s (%s %s)" % (pkg, constraint, version);
+ pp_dep = "%s (%s %s)" % (pkg, constraint, version)
else:
- pp_dep = pkg;
- pp_deps.append(pp_dep);
- return " |".join(pp_deps);
+ pp_dep = pkg
+ pp_deps.append(pp_dep)
+ return " |".join(pp_deps)
################################################################################
def get_conf():
- return Cnf;
+ return Cnf
################################################################################
def parse_args(Options):
# Process suite
if Options["Suite"]:
- suite_ids_list = [];
+ suite_ids_list = []
for suite in split_args(Options["Suite"]):
- suite_id = db_access.get_suite_id(suite);
+ suite_id = dak.lib.database.get_suite_id(suite)
if suite_id == -1:
- warn("suite '%s' not recognised." % (suite));
+ warn("suite '%s' not recognised." % (suite))
else:
- suite_ids_list.append(suite_id);
+ suite_ids_list.append(suite_id)
if suite_ids_list:
- con_suites = "AND su.id IN (%s)" % ", ".join(map(str, suite_ids_list));
+ con_suites = "AND su.id IN (%s)" % ", ".join(map(str, suite_ids_list))
else:
- fubar("No valid suite given.");
+ fubar("No valid suite given.")
else:
- con_suites = "";
+ con_suites = ""
# Process component
if Options["Component"]:
- component_ids_list = [];
+ component_ids_list = []
for component in split_args(Options["Component"]):
- component_id = db_access.get_component_id(component);
+ component_id = dak.lib.database.get_component_id(component)
if component_id == -1:
- warn("component '%s' not recognised." % (component));
+ warn("component '%s' not recognised." % (component))
else:
- component_ids_list.append(component_id);
+ component_ids_list.append(component_id)
if component_ids_list:
- con_components = "AND c.id IN (%s)" % ", ".join(map(str, component_ids_list));
+ con_components = "AND c.id IN (%s)" % ", ".join(map(str, component_ids_list))
else:
- fubar("No valid component given.");
+ fubar("No valid component given.")
else:
- con_components = "";
+ con_components = ""
# Process architecture
- con_architectures = "";
+ con_architectures = ""
if Options["Architecture"]:
- arch_ids_list = [];
- check_source = 0;
+ arch_ids_list = []
+ check_source = 0
for architecture in split_args(Options["Architecture"]):
if architecture == "source":
- check_source = 1;
+ check_source = 1
else:
- architecture_id = db_access.get_architecture_id(architecture);
+ architecture_id = dak.lib.database.get_architecture_id(architecture)
if architecture_id == -1:
- warn("architecture '%s' not recognised." % (architecture));
+ warn("architecture '%s' not recognised." % (architecture))
else:
- arch_ids_list.append(architecture_id);
+ arch_ids_list.append(architecture_id)
if arch_ids_list:
- con_architectures = "AND a.id IN (%s)" % ", ".join(map(str, 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.");
+ fubar("No valid architecture given.")
else:
- check_source = 1;
+ check_source = 1
- return (con_suites, con_architectures, con_components, check_source);
+ return (con_suites, con_architectures, con_components, check_source)
################################################################################
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52215)
def print_exc():
- tb = sys.exc_info()[2];
+ tb = sys.exc_info()[2]
while tb.tb_next:
- tb = tb.tb_next;
- stack = [];
- frame = tb.tb_frame;
+ tb = tb.tb_next
+ stack = []
+ frame = tb.tb_frame
while frame:
- stack.append(frame);
- frame = frame.f_back;
- stack.reverse();
- traceback.print_exc();
+ 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);
+ frame.f_lineno)
for key, value in frame.f_locals.items():
- print "\t%20s = " % key,;
+ print "\t%20s = " % key,
try:
- print value;
+ print value
except:
- print "<unable to print>";
+ print "<unable to print>"
################################################################################
def try_with_debug(function):
try:
- function();
+ function()
except SystemExit:
- raise;
+ raise
except:
- print_exc();
+ print_exc()
################################################################################
def arch_compare_sw (a, b):
if a == "source" and b == "source":
- return 0;
+ return 0
elif a == "source":
- return -1;
+ return -1
elif b == "source":
- return 1;
+ return 1
- return cmp (a, b);
+ return cmp (a, b)
################################################################################
# Split command line arguments which can be separated by either commas
# or whitespace. If dwim is set, it will complain about string ending
-# in comma since this usually means someone did 'madison -a i386, m68k
+# in comma since this usually means someone did 'dak ls -a i386, m68k
# foo' or something and the inevitable confusion resulting from 'm68k'
# being treated as an argument is undesirable.
def split_args (s, dwim=1):
if s.find(",") == -1:
- return s.split();
+ return s.split()
else:
if s[-1:] == "," and dwim:
- fubar("split_args: found trailing comma, spurious space maybe?");
- return s.split(",");
+ fubar("split_args: found trailing comma, spurious space maybe?")
+ return s.split(",")
################################################################################
# Our very own version of commands.getouputstatus(), hacked to support
# gpgv's status fd.
def gpgv_get_status_output(cmd, status_read, status_write):
- cmd = ['/bin/sh', '-c', cmd];
- p2cread, p2cwrite = os.pipe();
- c2pread, c2pwrite = os.pipe();
- errout, errin = os.pipe();
- pid = os.fork();
+ cmd = ['/bin/sh', '-c', cmd]
+ p2cread, p2cwrite = os.pipe()
+ c2pread, c2pwrite = os.pipe()
+ errout, errin = os.pipe()
+ pid = os.fork()
if pid == 0:
# Child
- os.close(0);
- os.close(1);
- os.dup(p2cread);
- os.dup(c2pwrite);
- os.close(2);
- os.dup(errin);
+ os.close(0)
+ os.close(1)
+ os.dup(p2cread)
+ os.dup(c2pwrite)
+ os.close(2)
+ os.dup(errin)
for i in range(3, 256):
if i != status_write:
try:
- os.close(i);
+ os.close(i)
except:
- pass;
+ pass
try:
- os.execvp(cmd[0], cmd);
+ os.execvp(cmd[0], cmd)
finally:
- os._exit(1);
+ os._exit(1)
# Parent
os.close(p2cread)
- os.dup2(c2pread, c2pwrite);
- os.dup2(errout, errin);
+ os.dup2(c2pread, c2pwrite)
+ os.dup2(errout, errin)
- output = status = "";
+ output = status = ""
while 1:
- i, o, e = select.select([c2pwrite, errin, status_read], [], []);
- more_data = [];
+ i, o, e = select.select([c2pwrite, errin, status_read], [], [])
+ more_data = []
for fd in i:
- r = os.read(fd, 8196);
+ r = os.read(fd, 8196)
if len(r) > 0:
- more_data.append(fd);
+ more_data.append(fd)
if fd == c2pwrite or fd == errin:
- output += r;
+ output += r
elif fd == status_read:
- status += r;
+ status += r
else:
- fubar("Unexpected file descriptor [%s] returned from select\n" % (fd));
+ fubar("Unexpected file descriptor [%s] returned from select\n" % (fd))
if not more_data:
pid, exit_status = os.waitpid(pid, 0)
try:
- os.close(status_write);
- os.close(status_read);
- os.close(c2pread);
- os.close(c2pwrite);
- os.close(p2cwrite);
- os.close(errin);
- os.close(errout);
+ os.close(status_write)
+ os.close(status_read)
+ os.close(c2pread)
+ os.close(c2pwrite)
+ os.close(p2cwrite)
+ os.close(errin)
+ os.close(errout)
except:
- pass;
- break;
+ pass
+ break
- return output, status, exit_status;
+ return output, status, exit_status
############################################################
# Ensure the filename contains no shell meta-characters or other badness
if not re_taint_free.match(sig_filename):
- reject("!!WARNING!! tainted signature filename: '%s'." % (sig_filename));
- return None;
+ reject("!!WARNING!! tainted signature filename: '%s'." % (sig_filename))
+ return None
if data_filename and not re_taint_free.match(data_filename):
- reject("!!WARNING!! tainted data filename: '%s'." % (data_filename));
- return None;
+ reject("!!WARNING!! tainted data filename: '%s'." % (data_filename))
+ return None
if not keyrings:
keyrings = (Cnf["Dinstall::PGPKeyring"], Cnf["Dinstall::GPGKeyring"])
# Build the command line
status_read, status_write = os.pipe();
- cmd = "gpgv --status-fd %s" % (status_write);
+ cmd = "gpgv --status-fd %s" % (status_write)
for keyring in keyrings:
- cmd += " --keyring %s" % (keyring);
- cmd += " %s %s" % (sig_filename, data_filename);
+ cmd += " --keyring %s" % (keyring)
+ cmd += " %s %s" % (sig_filename, data_filename)
# Invoke gpgv on the file
- (output, status, exit_status) = gpgv_get_status_output(cmd, status_read, status_write);
+ (output, status, exit_status) = gpgv_get_status_output(cmd, status_read, status_write)
# Process the status-fd output
- keywords = {};
- bad = internal_error = "";
+ keywords = {}
+ bad = internal_error = ""
for line in status.split('\n'):
- line = line.strip();
+ line = line.strip()
if line == "":
- continue;
- split = line.split();
+ continue
+ split = line.split()
if len(split) < 2:
- internal_error += "gpgv status line is malformed (< 2 atoms) ['%s'].\n" % (line);
- continue;
- (gnupg, keyword) = split[:2];
+ internal_error += "gpgv status line is malformed (< 2 atoms) ['%s'].\n" % (line)
+ continue
+ (gnupg, keyword) = split[:2]
if gnupg != "[GNUPG:]":
- internal_error += "gpgv status line is malformed (incorrect prefix '%s').\n" % (gnupg);
- continue;
- args = split[2:];
+ internal_error += "gpgv status line is malformed (incorrect prefix '%s').\n" % (gnupg)
+ continue
+ args = split[2:]
if keywords.has_key(keyword) and (keyword != "NODATA" and keyword != "SIGEXPIRED"):
- internal_error += "found duplicate status token ('%s').\n" % (keyword);
- continue;
+ internal_error += "found duplicate status token ('%s').\n" % (keyword)
+ continue
else:
- keywords[keyword] = args;
+ keywords[keyword] = args
# If we failed to parse the status-fd output, let's just whine and bail now
if internal_error:
- reject("internal error while performing signature check on %s." % (sig_filename));
- reject(internal_error, "");
- reject("Please report the above errors to the Archive maintainers by replying to this mail.", "");
- return None;
+ reject("internal error while performing signature check on %s." % (sig_filename))
+ reject(internal_error, "")
+ reject("Please report the above errors to the Archive maintainers by replying to this mail.", "")
+ return None
# Now check for obviously bad things in the processed output
if keywords.has_key("SIGEXPIRED"):
- reject("The key used to sign %s has expired." % (sig_filename));
- bad = 1;
+ reject("The key used to sign %s has expired." % (sig_filename))
+ bad = 1
if keywords.has_key("KEYREVOKED"):
- reject("The key used to sign %s has been revoked." % (sig_filename));
- bad = 1;
+ reject("The key used to sign %s has been revoked." % (sig_filename))
+ bad = 1
if keywords.has_key("BADSIG"):
- reject("bad signature on %s." % (sig_filename));
- bad = 1;
+ reject("bad signature on %s." % (sig_filename))
+ bad = 1
if keywords.has_key("ERRSIG") and not keywords.has_key("NO_PUBKEY"):
- reject("failed to check signature on %s." % (sig_filename));
- bad = 1;
+ reject("failed to check signature on %s." % (sig_filename))
+ bad = 1
if keywords.has_key("NO_PUBKEY"):
- args = keywords["NO_PUBKEY"];
+ args = keywords["NO_PUBKEY"]
if len(args) >= 1:
- key = args[0];
- reject("The key (0x%s) used to sign %s wasn't found in the keyring(s)." % (key, sig_filename));
- bad = 1;
+ key = args[0]
+ reject("The key (0x%s) used to sign %s wasn't found in the keyring(s)." % (key, sig_filename))
+ bad = 1
if keywords.has_key("BADARMOR"):
- reject("ASCII armour of signature was corrupt in %s." % (sig_filename));
- bad = 1;
+ reject("ASCII armour of signature was corrupt in %s." % (sig_filename))
+ bad = 1
if keywords.has_key("NODATA"):
- reject("no signature found in %s." % (sig_filename));
- bad = 1;
+ reject("no signature found in %s." % (sig_filename))
+ bad = 1
if bad:
- return None;
+ return None
# Next check gpgv exited with a zero return code
if exit_status:
- reject("gpgv failed while checking %s." % (sig_filename));
+ reject("gpgv failed while checking %s." % (sig_filename))
if status.strip():
- reject(prefix_multi_line_string(status, " [GPG status-fd output:] "), "");
+ reject(prefix_multi_line_string(status, " [GPG status-fd output:] "), "")
else:
- reject(prefix_multi_line_string(output, " [GPG output:] "), "");
- return None;
+ reject(prefix_multi_line_string(output, " [GPG output:] "), "")
+ return None
# Sanity check the good stuff we expect
if not keywords.has_key("VALIDSIG"):
- reject("signature on %s does not appear to be valid [No VALIDSIG]." % (sig_filename));
- bad = 1;
+ reject("signature on %s does not appear to be valid [No VALIDSIG]." % (sig_filename))
+ bad = 1
else:
- args = keywords["VALIDSIG"];
+ args = keywords["VALIDSIG"]
if len(args) < 1:
- reject("internal error while checking signature on %s." % (sig_filename));
- bad = 1;
+ reject("internal error while checking signature on %s." % (sig_filename))
+ bad = 1
else:
- fingerprint = args[0];
+ fingerprint = args[0]
if not keywords.has_key("GOODSIG"):
- reject("signature on %s does not appear to be valid [No GOODSIG]." % (sig_filename));
- bad = 1;
+ reject("signature on %s does not appear to be valid [No GOODSIG]." % (sig_filename))
+ bad = 1
if not keywords.has_key("SIG_ID"):
- reject("signature on %s does not appear to be valid [No SIG_ID]." % (sig_filename));
- bad = 1;
+ reject("signature on %s does not appear to be valid [No SIG_ID]." % (sig_filename))
+ bad = 1
# Finally ensure there's not something we don't recognise
known_keywords = Dict(VALIDSIG="",SIG_ID="",GOODSIG="",BADSIG="",ERRSIG="",
SIGEXPIRED="",KEYREVOKED="",NO_PUBKEY="",BADARMOR="",
- NODATA="");
+ NODATA="")
for keyword in keywords.keys():
if not known_keywords.has_key(keyword):
- reject("found unknown status token '%s' from gpgv with args '%r' in %s." % (keyword, keywords[keyword], sig_filename));
- bad = 1;
+ reject("found unknown status token '%s' from gpgv with args '%r' in %s." % (keyword, keywords[keyword], sig_filename))
+ bad = 1
if bad:
- return None;
+ return None
else:
- return fingerprint;
+ return fingerprint
################################################################################
# Inspired(tm) by http://www.zopelabs.com/cookbook/1022242603
def wrap(paragraph, max_length, prefix=""):
- line = "";
- s = "";
- have_started = 0;
- words = paragraph.split();
+ line = ""
+ s = ""
+ have_started = 0
+ words = paragraph.split()
for word in words:
- word_size = len(word);
+ word_size = len(word)
if word_size > max_length:
if have_started:
- s += line + '\n' + prefix;
- s += word + '\n' + prefix;
+ s += line + '\n' + prefix
+ s += word + '\n' + prefix
else:
if have_started:
- new_length = len(line) + word_size + 1;
+ new_length = len(line) + word_size + 1
if new_length > max_length:
- s += line + '\n' + prefix;
- line = word;
+ s += line + '\n' + prefix
+ line = word
else:
- line += ' ' + word;
+ line += ' ' + word
else:
- line = word;
- have_started = 1;
+ line = word
+ have_started = 1
if have_started:
- s += line;
+ s += line
- return s;
+ return s
################################################################################
# Relativize an absolute symlink from 'src' -> 'dest' relative to 'root'.
# Returns fixed 'src'
def clean_symlink (src, dest, root):
- src = src.replace(root, '', 1);
- dest = dest.replace(root, '', 1);
- dest = os.path.dirname(dest);
- new_src = '../' * len(dest.split('/'));
- return new_src + src;
+ src = src.replace(root, '', 1)
+ dest = dest.replace(root, '', 1)
+ dest = os.path.dirname(dest)
+ new_src = '../' * len(dest.split('/'))
+ return new_src + src
################################################################################
If 'dotprefix' is non-null, the filename will be prefixed with a '.'."""
if directory:
- old_tempdir = tempfile.tempdir;
- tempfile.tempdir = directory;
+ old_tempdir = tempfile.tempdir
+ tempfile.tempdir = directory
- filename = tempfile.mktemp();
+ filename = tempfile.mktemp()
if dotprefix:
- filename = "%s/.%s" % (os.path.dirname(filename), os.path.basename(filename));
- fd = os.open(filename, os.O_RDWR|os.O_CREAT|os.O_EXCL, perms);
- os.close(fd);
+ filename = "%s/.%s" % (os.path.dirname(filename), os.path.basename(filename))
+ fd = os.open(filename, os.O_RDWR|os.O_CREAT|os.O_EXCL, perms)
+ os.close(fd)
if directory:
- tempfile.tempdir = old_tempdir;
+ tempfile.tempdir = old_tempdir
- return filename;
+ return filename
################################################################################
-apt_pkg.init();
+apt_pkg.init()
-Cnf = apt_pkg.newConfiguration();
-apt_pkg.ReadConfigFileISC(Cnf,default_config);
+Cnf = apt_pkg.newConfiguration()
+apt_pkg.ReadConfigFileISC(Cnf,default_config)
if which_conf_file() != default_config:
- apt_pkg.ReadConfigFileISC(Cnf,which_conf_file());
+ apt_pkg.ReadConfigFileISC(Cnf,which_conf_file())
################################################################################