]> git.decadent.org.uk Git - dak.git/blobdiff - utils.py
Remove versions for unreleased suites, since they're not released yet :)Add "Tree...
[dak.git] / utils.py
index 29175bbdcbe908a36ecdfeab0362fe02ba210b2e..a40133f4ea88cbecdb2a111e142ce820ea9b96e2 100644 (file)
--- a/utils.py
+++ b/utils.py
@@ -1,6 +1,6 @@
 # Utility functions
 # Copyright (C) 2000  James Troup <james@nocrew.org>
-# $Id: utils.py,v 1.1.1.1 2000-11-24 00:20:09 troup Exp $
+# $Id: utils.py,v 1.14 2001-02-04 04:28:34 troup Exp $
 
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -23,12 +23,16 @@ 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)');
 
 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 file.";
 cant_open_exc = "Can't read file.";
 unknown_hostname_exc = "Unknown hostname";
+cant_overwrite_exc = "Permission denied; can't overwrite existent file."
        
 ######################################################################################
 
@@ -53,15 +57,81 @@ def our_raw_input():
 
 ######################################################################################
 
-def parse_changes(filename):
+# What a mess.  FIXME
+def extract_component_from_section(section):
+    component = "";
+    
+    if string.find(section, '/') != -1: 
+        component = string.split(section, '/')[0];
+    if string.lower(component) == "non-us" and string.count(section, '/') > 0:
+        s = string.split(section, '/')[1];
+        if s == "main" or s == "non-free" or s == "contrib": # Avoid e.g. non-US/libs
+            component = string.split(section, '/')[0]+ '/' + string.split(section, '/')[1];
+
+    if string.lower(section) == "non-us":
+        component = "non-US/main";
+            
+    if component == "":
+        component = "main";
+    elif string.lower(component) == "non-us":
+        component = "non-US/main";
+
+    return (section, component);
+
+######################################################################################
+
+# dsc_whitespace_rules turns on strict format checking to avoid
+# allowing in source packages which are unextracable by the
+# inappropriately fragile dpkg-source.
+#
+# The rules are:
+#
+#
+# o The PGP header consists of "-----BEGIN PGP SIGNED MESSAGE-----"
+#   followed by any PGP header data and must end with a blank line.
+#
+# o The data section must end with a blank line and must be followed by
+#   "-----BEGIN PGP SIGNATURE-----".
+
+def parse_changes(filename, dsc_whitespace_rules):
     changes_in = open_file(filename,'r');
-    error = ""
+    error = "";
     changes = {};
     lines = changes_in.readlines();
+
+    # Reindex by line number so we can easily verify the format of
+    # .dsc files...
+    index = 0;
+    indexed_lines = {};
     for line in lines:
+        index = index + 1;
+        indexed_lines[index] = line[:-1];
+
+    inside_signature = 0;
+
+    indices = indexed_lines.keys()
+    index = 0;
+    while index < max(indices):
+        index = index + 1;
+        line = indexed_lines[index];
+        if line == "":
+            if dsc_whitespace_rules:
+                index = index + 1;
+                if index > max(indices):
+                    raise invalid_dsc_format_exc, index;
+                line = indexed_lines[index];
+                if not re.match('^-----BEGIN PGP SIGNATURE', line):
+                    raise invalid_dsc_format_exc, index;
+                inside_signature = 0;
+                break;
         if re.match('^-----BEGIN PGP SIGNATURE', line):
             break;
-        if re.match(r'^\s*$|^-----BEGIN PGP SIGNED MESSAGE', line):
+        if re.match(r'^-----BEGIN PGP SIGNED MESSAGE', line):
+            if dsc_whitespace_rules:
+                inside_signature = 1;
+                while index < max(indices) and line != "":
+                    index = index + 1;
+                    line = indexed_lines[index];
             continue;
         slf = re.match(r'^(\S*)\s*:\s*(.*)', line);
         if slf:
@@ -77,10 +147,16 @@ def parse_changes(filename):
            changes[field] = changes[field] + mlf.groups()[0] + '\n';
             continue;
        error = error + line;
+
+    if dsc_whitespace_rules and inside_signature:
+        raise invalid_dsc_format_exc, index;
+        
     changes_in.close();
     changes["filecontents"] = string.join (lines, "");
+
     if error != "":
        raise changes_parse_error_exc, error;
+
     return changes;
 
 ######################################################################################
@@ -103,23 +179,20 @@ def build_file_list(changes, dsc):
         if i == "":
             break
         s = string.split(i)
-        section = priority = component = ""
-        if dsc != "":
-            (md5, size, name) = s
-        else:
-            (md5, size, section, priority, name) = s
+        section = priority = "";
+        try:
+            if dsc != "":
+                (md5, size, name) = s
+            else:
+                (md5, size, section, priority, name) = s
+        except ValueError:
+            raise changes_parse_error_exc, i
 
         if section == "": section = "-"
         if priority == "": priority = "-"
 
-        if string.find(section, '/') != -1: 
-           component = string.split(section, '/')[0]
-       if string.lower(component) == "non-us":
-           component = string.split(section, '/')[0]+ '/' + string.split(section, '/')[1]
-
-        if component == "":
-            component = "main"
-
+        (section, component) = extract_component_from_section(section);
+        
         files[name] = { "md5sum" : md5,
                         "size" : size,
                         "section": section,
@@ -154,7 +227,7 @@ def fix_maintainer (maintainer):
 # sendmail wrapper, takes _either_ a message string or a file as arguments
 def send_mail (message, filename):
        #### FIXME, how do I get this out of Cnf in katie?
-       sendmail_command = "/usr/sbin/sendmail -oi -t";
+       sendmail_command = "/usr/sbin/sendmail -odq -oi -t";
 
        # Sanity check arguments
        if message != "" and filename != "":
@@ -180,6 +253,9 @@ def send_mail (message, filename):
 def poolify (source, component):
     if component != "":
        component = component + '/';
+    # FIXME: this is nasty
+    component = string.lower(component);
+    component = string.replace(component, 'non-us/', 'non-US/');
     if source[:3] == "lib":
        return component + source[:4] + '/' + source + '/'
     else:
@@ -188,7 +264,7 @@ def poolify (source, component):
 ######################################################################################
 
 def move (src, dest):
-    if os.path.exists(dest) and stat.S_ISDIR(os.stat(dest)[stat.ST_MODE]):
+    if os.path.exists(dest) and os.path.isdir(dest):
        dest_dir = dest;
     else:
        dest_dir = os.path.dirname(dest);
@@ -197,10 +273,32 @@ def move (src, dest):
        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 = dest + '/' + os.path.basename(src);
+    # Check for overwrite permission on existent files
+    if os.path.exists(dest) and not os.access(dest, os.W_OK):
+        raise cant_overwrite_exc
     shutil.copy2(src, dest);
     os.chmod(dest, 0664);
     os.unlink(src);
 
+def copy (src, dest):
+    if os.path.exists(dest) and os.path.isdir(dest):
+       dest_dir = dest;
+    else:
+       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);
+    if os.path.exists(dest) and os.path.isdir(dest):
+       dest = dest + '/' + os.path.basename(src);
+    if os.path.exists(dest) and not os.access(dest, os.W_OK):
+        raise cant_overwrite_exc
+    shutil.copy2(src, dest);
+    os.chmod(dest, 0664);
+
 ######################################################################################
 
 # FIXME: this is inherently nasty.  Can't put this mapping in a conf
@@ -211,7 +309,7 @@ def where_am_i ():
     res = socket.gethostbyaddr(socket.gethostname());
     if res[0] == 'pandora.debian.org':
         return 'non-US';
-    elif res[1] == 'auric.debian.org':
+    elif res[0] == 'auric.debian.org':
         return 'ftp-master';
     else:
         raise unknown_hostname_exc, res;
@@ -231,3 +329,21 @@ def which_conf_file ():
 
 ######################################################################################
 
+# Escape characters which have meaning to SQL's regex comparison operator ('~')
+# (woefully incomplete)
+
+def regex_safe (s):
+    s = string.replace(s, '+', '\\\\+');
+    return s
+
+######################################################################################
+
+def size_type (c):
+    t  = " b";
+    if c > 10000:
+        c = c / 1000;
+        t = " Kb";
+    if c > 10000:
+        c = c / 1000;
+        t = " Mb";
+    return ("%d%s" % (c, t))