]> err.no Git - dak/commitdiff
compiled regexes; source-must-exist; obsoleted-by-unstable check for experimental.
authorJames Troup <james@nocrew.org>
Thu, 24 May 2001 18:56:23 +0000 (18:56 +0000)
committerJames Troup <james@nocrew.org>
Thu, 24 May 2001 18:56:23 +0000 (18:56 +0000)
TODO
katie
rene
utils.py

diff --git a/TODO b/TODO
index 7081d22b80f183cced96b64ffd8300271ecc0693..301235de92c5d40bb91c56c0201a32445ad3a64f 100644 (file)
--- a/TODO
+++ b/TODO
@@ -12,6 +12,15 @@ Urgent
     files from p-u when removing stuff superseded by newer versions.
 
   o experimental needs to auto clean (relative to unstable)
+  ['
+   SELECT s.source, s.version AS experimental, s2.version AS unstable 
+     FROM src_associations sa, source s, source s2, src_associations sa2 
+     WHERE sa.suite = 1 AND sa2.suite = 5 AND sa.source = s.id 
+       AND sa2.source = s2.id AND s.source = s2.source 
+       AND versioncmp(s.version, s2.version) < 0;
+  ']
+  [ but, needs to hook into melanie ... ]
+  [ and, err, fix the gay hardcoding of suites in rene ... ]
 
   o jenna doesn't handle arch: any -> arch: all transitions 
     [aj worked around; need to revisit]
diff --git a/katie b/katie
index 9efaa0beeef981b9bf32d0d8062b5339fc172761..49ffacc97b436281d7bd13aaa8437a808b82f4ff 100755 (executable)
--- a/katie
+++ b/katie
@@ -2,7 +2,7 @@
 
 # Installs Debian packaes
 # Copyright (C) 2000, 2001  James Troup <james@nocrew.org>
-# $Id: katie,v 1.41 2001-05-17 01:21:40 troup Exp $
+# $Id: katie,v 1.42 2001-05-24 18:56:23 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
@@ -38,11 +38,12 @@ import utils, db_access
 
 ###############################################################################
 
-re_isanum = re.compile (r'^\d+$');
-re_changes = re.compile (r'changes$');
+re_isanum = re.compile (r"^\d+$");
+re_changes = re.compile (r"changes$");
 re_default_answer = re.compile(r"\[(.*)\]");
 re_fdnic = re.compile("\n\n");
 re_bad_diff = re.compile("^[\-\+][\-\+][\-\+] /dev/null");
+re_bin_only_nmu = re.compile("\.\d+\.\d+$");
 
 #########################################################################################
 
@@ -327,6 +328,18 @@ def check_files():
             files[file]["source"] = control.Find("Source", "");
             if files[file]["source"] == "":
                 files[file]["source"] = files[file]["package"];
+            # Get the source version
+            source = files[file]["source"];
+            source_version = ""
+            if string.find(source, "(") != -1:
+                m = utils.re_extract_src_version.match(source)
+                source = m.group(1)
+                source_version = m.group(2)
+            if not source_version:
+                source_version = files[file]["version"];
+            files[file]["source package"] = source;
+            files[file]["source version"] = source_version;
+                
         # Checks for a source package...
         else:
             m = utils.re_issource.match(file)
@@ -376,8 +389,8 @@ def check_files():
             if not in_override_p(files[file]["package"], files[file]["component"], suite, files[file].get("dbtype",""), file):
                 files[file]["new"] = 1
                 
-            # Find any old binary packages
             if files[file]["type"] == "deb":
+                # Find any old binary packages
                 q = projectB.query("SELECT b.id, b.version, f.filename, l.path, c.name FROM binaries b, bin_associations ba, suite s, location l, component c, architecture a, files f WHERE b.package = '%s' AND s.suite_name = '%s' AND a.arch_string = '%s' AND ba.bin = b.id AND ba.suite = s.id AND b.architecture = a.id AND f.location = l.id AND l.component = c.id AND b.file = f.id"
                                    % (files[file]["package"], suite, files[file]["architecture"]))
                 oldfiles = q.dictresult()
@@ -392,6 +405,24 @@ def check_files():
                     if q.getresult() != []:
                         reject_message = reject_message + "Rejected: can not overwrite existing copy of '%s' already in the archive.\n" % (file)
 
+                # Check for existent source
+                # FIXME: this is no longer per suite
+                if changes["architecture"].has_key("source"):
+                    source_version = files[file]["source version"];
+                    if source_version != changes["version"]:
+                        reject_message = reject_message + "Rejected: source version (%s) for %s doesn't match changes version %s.\n" % (files[file]["sourceversion"], file, changes["version"]);
+                else:
+                    q = projectB.query("SELECT s.version FROM source s WHERE s.source = '%s'" % (files[file]["source package"]));
+                    ql = map(lambda x: x[0], q.getresult());
+                    if ql.count(source_version) == 0:
+                        # Maybe it's a binary only NMU ?
+                        if re_bin_only_nmu.search(source_version):
+                            orig_source_version = re_bin_only_nmu.sub('', source_version);
+                            if ql.count(orig_source_version) == 0:
+                                reject_message = reject_message + "Rejected: no source version (%s [or %s]) found in %s for %s (%s).\n" % (source_version, orig_source_version, suite, files[file]["source package"], file);
+                        else:
+                            reject_message = reject_message + "Rejected: no source version (%s) found in %s for %s (%s).\n" % (source_version, suite, files[file]["source package"], file);
+
             # Find any old .dsc files
             elif files[file]["type"] == "dsc":
                 q = projectB.query("SELECT s.id, s.version, f.filename, l.path, c.name FROM source s, src_associations sa, suite su, location l, component c, files f WHERE s.source = '%s' AND su.suite_name = '%s' AND sa.source = s.id AND sa.suite = su.id AND f.location = l.id AND l.component = c.id AND f.id = s.file"
@@ -803,14 +834,8 @@ def install (changes_filename, summary, short_summary):
             architecture_id = db_access.get_architecture_id (architecture);
             type = files[file]["dbtype"];
             dsc_component = files[file]["component"]
-            source = files[file]["source"]
-            source_version = ""
-            if string.find(source, "(") != -1:
-                m = utils.re_extract_src_version.match(source)
-                source = m.group(1)
-                source_version = m.group(2)
-            if not source_version:
-                source_version = version
+            source = files[file]["source package"]
+            source_version = files[file]["source version"];
             filename = files[file]["pool name"] + file;
             if not files[file]["files id"]:
                 files[file]["files id"] = db_access.set_files_id (filename, files[file]["size"], files[file]["md5sum"], files[file]["location id"])
@@ -1243,7 +1268,7 @@ def main():
     Subst = {}
     Subst["__ADMIN_ADDRESS__"] = Cnf["Dinstall::MyAdminAddress"];
     Subst["__BUG_SERVER__"] = Cnf["Dinstall::BugServer"];
-    bcc = "X-Katie: $Revision: 1.41 $"
+    bcc = "X-Katie: $Revision: 1.42 $"
     if Cnf.has_key("Dinstall::Bcc"):
         Subst["__BCC__"] = bcc + "\nBcc: %s" % (Cnf["Dinstall::Bcc"]);
     else:
@@ -1251,6 +1276,9 @@ def main():
     Subst["__DISTRO__"] = Cnf["Dinstall::MyDistribution"];
     Subst["__KATIE_ADDRESS__"] = Cnf["Dinstall::MyEmailAddress"];
 
+    # Sort the .changes files so that we process sourceful ones first
+    changes_files.sort(utils.changes_compare);
+
     # Process the changes files
     for changes_file in changes_files:
         print "\n" + changes_file;
diff --git a/rene b/rene
index 696729102daa50fd73aeed330f1f17f3bbc9c2d1..efac5ac7f702015ef1fb01315a407c324af62b3b 100755 (executable)
--- a/rene
+++ b/rene
@@ -2,7 +2,7 @@
 
 # Check for obsolete binary packages
 # Copyright (C) 2000, 2001  James Troup <james@nocrew.org>
-# $Id: rene,v 1.4 2001-05-21 02:25:08 troup Exp $
+# $Id: rene,v 1.5 2001-05-24 18:56:23 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
@@ -151,6 +151,21 @@ def main ():
                     print " %s has no source [%s: %s]" % (package, source, source_binaries.get(source, "(source does not exist)"));
             packages.close();
 
+    # Check for packages in experimental obsoleted by versions in unstable
+    #
+    # [If melanie was callable from python, we could auto-remove these
+    #  packages...]
+
+    q = projectB.query("""
+SELECT s.source, s.version AS experimental, s2.version AS unstable 
+  FROM src_associations sa, source s, source s2, src_associations sa2 
+  WHERE sa.suite = 1 AND sa2.suite = 5 AND sa.source = s.id 
+   AND sa2.source = s2.id AND s.source = s2.source 
+   AND versioncmp(s.version, s2.version) < 0""");
+    ql = q.getresult();
+    if ql != []:
+        print
+        print q
 
 ####################################################################################################
 
index 33b7780516a382120dd6dbb0ca04e077773ca9a3..95a0882633dfb690d0f070cfa36102d5f91afcd6 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.22 2001-05-17 01:17:54 troup Exp $
+# $Id: utils.py,v 1.23 2001-05-24 18:56:23 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
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
 import commands, os, pwd, re, socket, shutil, stat, string, sys, tempfile
+import apt_pkg
 
 re_comments = re.compile(r"\#.*")
 re_no_epoch = re.compile(r"^\d*\:")
 re_no_revision = re.compile(r"\-[^-]*$")
 re_arch_from_filename = re.compile(r"/binary-[^/]+/")
 re_extract_src_version = re.compile (r"(\S+)\s*\((.*)\)")
-re_isadeb = re.compile (r'.*\.u?deb$');
-re_issource = re.compile (r'(.+)_(.+?)\.(orig\.tar\.gz|diff\.gz|tar\.gz|dsc)');
+re_isadeb = re.compile (r".*\.u?deb$");
+re_issource = re.compile (r"(.+)_(.+?)\.(orig\.tar\.gz|diff\.gz|tar\.gz|dsc)");
+
+re_begin_pgp_signature = re.compile("^-----BEGIN PGP SIGNATURE");
+re_begin_pgp_signed_msg = re.compile("^-----BEGIN PGP SIGNED MESSAGE");
+re_single_line_field = re.compile(r"^(\S*)\s*:\s*(.*)");
+re_multi_line_description = re.compile(r"^ \.$");
+re_multi_line_field = re.compile(r"^\s(.*)");
+
+re_parse_maintainer = re.compile(r"^\s*(\S.*\S)\s*\<([^\> \t]+)\>");
 
 changes_parse_error_exc = "Can't parse line in .changes file";
 invalid_dsc_format_exc = "Invalid .dsc file";
@@ -131,30 +140,30 @@ def parse_changes(filename, dsc_whitespace_rules):
                 if index > max(indices):
                     raise invalid_dsc_format_exc, index;
                 line = indexed_lines[index];
-                if not re.match('^-----BEGIN PGP SIGNATURE', line):
+                if not re_begin_pgp_signature.match(line):
                     raise invalid_dsc_format_exc, index;
                 inside_signature = 0;
                 break;
-        if re.match('^-----BEGIN PGP SIGNATURE', line):
+        if re_begin_pgp_signature.match(line):
             break;
-        if re.match(r'^-----BEGIN PGP SIGNED MESSAGE', line):
+        if re_begin_pgp_signed_msg.match(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);
+        slf = re_single_line_field.match(line);
         if slf:
             field = string.lower(slf.groups()[0]);
             changes[field] = slf.groups()[1];
            first = 1;
             continue;
-        mld = re.match(r'^ \.$', line);
+        mld = re_multi_line_description.match(line);
         if mld:
             changes[field] = changes[field] + '\n';
             continue;
-        mlf = re.match(r'^\s(.*)', line);
+        mlf = re_multi_line_field.match(line);
         if mlf:
             if first == 1 and changes[field] != "":
                 changes[field] = changes[field] + '\n';
@@ -226,15 +235,15 @@ def build_file_list(changes, dsc):
 #                and make things incompatible!'
         
 def fix_maintainer (maintainer):
-    m = re.match(r"^\s*(\S.*\S)\s*\<([^\> \t]+)\>", maintainer)
+    m = re_parse_maintainer.match(maintainer);
     rfc822 = maintainer
     name = ""
     email = ""
     if m != None and len(m.groups()) == 2:
         name = m.group(1)
         email = m.group(2)
-        if re.search(r'[,.]', name) != None:
-            rfc822 = re.sub(r"^\s*(\S.*\S)\s*\<([^\> \t]+)\>", r"\2 (\1)", maintainer)
+        if string.find(name, ',') != -1 or string.find(name, '.') != -1:
+            rfc822 = re_parse_maintainer.sub(r"\2 (\1)", maintainer)
     return (rfc822, name, email)
 
 ######################################################################################
@@ -398,3 +407,60 @@ def size_type (c):
         c = c / 1000;
         t = " Mb";
     return ("%d%s" % (c, t))
+
+################################################################################
+
+def cc_fix_changes (changes):
+    o = changes.get("architecture", "")
+    if o != "":
+        del changes["architecture"]
+    changes["architecture"] = {}
+    for j in string.split(o):
+        changes["architecture"][j] = 1
+
+# Sort by 'have source', by source name, by source version number, by filename
+
+def changes_compare (a, b):
+    try:
+        a_changes = parse_changes(a, 0)
+    except changes_parse_error_exc, line:
+        return -1;
+
+    try:
+        b_changes = parse_changes(b, 0)
+    except changes_parse_error_exc, line:
+        return 1;
+    
+    cc_fix_changes (a_changes);
+    cc_fix_changes (b_changes);
+
+    # Sort by 'have 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;
+    elif b_has_source and not a_has_source:
+        return 1;
+
+    # Sort by source name
+    
+    a_source = a_changes.get("source");
+    b_source = b_changes.get("source");
+    q = cmp (a_source, b_source);
+    if q:
+        return q;
+
+    # Sort by source version
+
+    a_version = a_changes.get("version");
+    b_version = b_changes.get("version");
+    q = apt_pkg.VersionCompare(a_version, b_version);
+    if q:
+        return q
+
+    # Fall back to sort by filename
+
+    return cmp(a, b);
+
+################################################################################