]> git.decadent.org.uk Git - dak.git/blobdiff - dak/lib/utils.py
Enmasse adaptation for removal of silly names.
[dak.git] / dak / lib / utils.py
index 580ceda8d0920734dafd0a9ce65951b638a419fc..4b103f53a30fa495318002f0c93b42d377c7aed7 100644 (file)
@@ -1,7 +1,7 @@
 #!/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 $
 
 ################################################################################
@@ -23,9 +23,9 @@
 ################################################################################
 
 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
 
 ################################################################################
 
@@ -34,34 +34,34 @@ 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_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.
@@ -71,68 +71,68 @@ class ParseMaintError(Error):
     """
 
     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)
 
 ################################################################################
 
@@ -157,127 +157,127 @@ The rules for (signing_rules == 1)-mode are:
     "-----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
 
@@ -287,27 +287,27 @@ def force_to_utf8(s):
     """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)
 
 ################################################################################
 
@@ -327,38 +327,38 @@ contains '.' or ',' (as allowed by Debian policy), (1) and (2) are
 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)
 
 ################################################################################
 
@@ -366,27 +366,27 @@ switched to 'email (name)' format."""
 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:
@@ -396,39 +396,39 @@ def poolify (source, component):
 
 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:
@@ -436,32 +436,32 @@ def copy (src, dest, overwrite = 0, perms = 0664):
         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
 
 ################################################################################
 
@@ -469,140 +469,140 @@ def which_apt_conf_file ():
 # (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'
@@ -613,61 +613,61 @@ argument:
  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
 
 ################################################################################
 
@@ -675,59 +675,59 @@ def get_conf():
 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)
 
 ################################################################################
 
@@ -735,36 +735,36 @@ def parse_args(Options):
 # 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()
 
 ################################################################################
 
@@ -773,29 +773,29 @@ def try_with_debug(function):
 
 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(",")
 
 ################################################################################
 
@@ -806,64 +806,64 @@ def Dict(**dict): return dict
 # 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
 
 ############################################################
 
@@ -883,168 +883,168 @@ a *list* of keyrings to use.
 
     # 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
 
 ################################################################################
 
@@ -1054,29 +1054,29 @@ If 'directory' is non-null, it will be the directory the file is pre-created in.
 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())
 
 ################################################################################