]> git.decadent.org.uk Git - dak.git/blobdiff - katie.py
Add version-tracking aids for BTS.
[dak.git] / katie.py
index 198ee00140171a557c7decd6ed168d3e966c4b6e..776310ddd73be779815dc93bfe721fbe01918b51 100644 (file)
--- a/katie.py
+++ b/katie.py
@@ -1,8 +1,8 @@
 #!/usr/bin/env python
 
 # Utility functions for katie
-# Copyright (C) 2001, 2002, 2003  James Troup <james@nocrew.org>
-# $Id: katie.py,v 1.35 2003-07-29 14:00:39 ajt Exp $
+# Copyright (C) 2001, 2002, 2003, 2004  James Troup <james@nocrew.org>
+# $Id: katie.py,v 1.44 2004-02-27 20:07:40 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
@@ -93,7 +93,6 @@ class Katie:
 
     def __init__(self, Cnf):
         self.Cnf = Cnf;
-        self.values = {};
         # Read in the group-maint override file
         self.nmu = nmu_p(Cnf);
         self.accept_count = 0;
@@ -263,7 +262,7 @@ class Katie:
                 if files[file]["type"] == "deb":
                     summary += apt_pkg.ParseSection(apt_inst.debExtractControl(utils.open_file(file)))["Description"] + '\n';
             else:
-                files[file]["pool name"] = utils.poolify (changes["source"], files[file]["component"])
+                files[file]["pool name"] = utils.poolify (changes.get("source",""), files[file]["component"])
                 destination = self.Cnf["Dir::PoolRoot"] + files[file]["pool name"] + file
                 summary += file + "\n  to " + destination + "\n"
 
@@ -293,25 +292,42 @@ class Katie:
 
         bugs.sort();
         if not self.nmu.is_an_nmu(self.pkg):
-            summary += "Closing bugs: ";
-            for bug in bugs:
-                summary += "%s " % (bug);
-                if action:
-                    Subst["__BUG_NUMBER__"] = bug;
-                    if changes["distribution"].has_key("stable"):
-                        Subst["__STABLE_WARNING__"] = """
+            if changes["distribution"].has_key("experimental"):
+               # tag bugs as fixed-in-experimental for uploads to experimental
+               summary += "Setting bugs to severity fixed: ";
+               control_message = "";
+               for bug in bugs:
+                   summary += "%s " % (bug);
+                   control_message += "tag %s + fixed-in-experimental\n" % (bug);
+               if action and control_message != "":
+                   Subst["__CONTROL_MESSAGE__"] = control_message;
+                   mail_message = utils.TemplateSubst(Subst,Cnf["Dir::Templates"]+"/jennifer.bug-experimental-fixed");
+                   utils.send_mail (mail_message);
+               if action:
+                   self.Logger.log(["setting bugs to fixed"]+bugs);
+
+
+           else:
+               summary += "Closing bugs: ";
+               for bug in bugs:
+                   summary += "%s " % (bug);
+                   if action:
+                       Subst["__BUG_NUMBER__"] = bug;
+                       if changes["distribution"].has_key("stable"):
+                           Subst["__STABLE_WARNING__"] = """
 Note that this package is not part of the released stable Debian
 distribution.  It may have dependencies on other unreleased software,
 or other instabilities.  Please take care if you wish to install it.
 The update will eventually make its way into the next released Debian
 distribution.""";
-                    else:
-                        Subst["__STABLE_WARNING__"] = "";
-                    mail_message = utils.TemplateSubst(Subst,Cnf["Dir::Templates"]+"/jennifer.bug-close");
-                    utils.send_mail (mail_message);
-            if action:
-                self.Logger.log(["closing bugs"]+bugs);
-        else:                     # NMU
+                       else:
+                           Subst["__STABLE_WARNING__"] = "";
+                           mail_message = utils.TemplateSubst(Subst,Cnf["Dir::Templates"]+"/jennifer.bug-close");
+                           utils.send_mail (mail_message);
+                if action:
+                    self.Logger.log(["closing bugs"]+bugs);
+
+       else:                     # NMU
             summary += "Setting bugs to severity fixed: ";
             control_message = "";
             for bug in bugs:
@@ -452,7 +468,9 @@ distribution.""";
             return;
 
         summary = "";
-        for file in files.keys():
+        file_keys = files.keys();
+        file_keys.sort();
+        for file in file_keys:
             if not files[file].has_key("new") and files[file]["type"] == "deb":
                 section = files[file]["section"];
                 override_section = files[file]["override section"];
@@ -553,7 +571,7 @@ distribution.""";
         pkg = self.pkg;
 
         reason_filename = pkg.changes_file[:-8] + ".reason";
-        reject_filename = Cnf["Dir::Queue::Reject"] + '/' + reason_filename;
+        reason_filename = Cnf["Dir::Queue::Reject"] + '/' + reason_filename;
 
         # Move all the files into the reject directory
         reject_files = pkg.files.keys() + [pkg.changes_file];
@@ -561,16 +579,15 @@ distribution.""";
 
         # If we fail here someone is probably trying to exploit the race
         # so let's just raise an exception ...
-        if os.path.exists(reject_filename):
-            os.unlink(reject_filename);
-        fd = os.open(reject_filename, os.O_RDWR|os.O_CREAT|os.O_EXCL, 0644);
+        if os.path.exists(reason_filename):
+            os.unlink(reason_filename);
+        reason_file = os.open(reason_filename, os.O_RDWR|os.O_CREAT|os.O_EXCL, 0644);
 
         if not manual:
             Subst["__REJECTOR_ADDRESS__"] = Cnf["Dinstall::MyEmailAddress"];
             Subst["__MANUAL_REJECT_MESSAGE__"] = "";
             Subst["__CC__"] = "X-Katie-Rejection: automatic (moo)";
-            os.write(fd, reject_message);
-            os.close(fd);
+            os.write(reason_file, reject_message);
             reject_mail_message = utils.TemplateSubst(Subst,Cnf["Dir::Templates"]+"/katie.rejected");
         else:
             # Build up the rejection email
@@ -580,10 +597,10 @@ distribution.""";
             Subst["__MANUAL_REJECT_MESSAGE__"] = reject_message;
             Subst["__CC__"] = "Cc: " + Cnf["Dinstall::MyEmailAddress"];
             reject_mail_message = utils.TemplateSubst(Subst,Cnf["Dir::Templates"]+"/katie.rejected");
-
             # Write the rejection email out as the <foo>.reason file
-            os.write(fd, reject_mail_message);
-            os.close(fd);
+            os.write(reason_file, reject_mail_message);
+
+        os.close(reason_file);
 
         # Send the rejection mail if appropriate
         if not Cnf["Dinstall::Options::No-Mail"]:
@@ -604,33 +621,46 @@ distribution.""";
     def source_exists (self, package, source_version, suites = ["any"]):
        okay = 1
        for suite in suites:
-           if suites == "any":
+           if suite == "any":
                que = "SELECT s.version FROM source s WHERE s.source = '%s'" % \
                    (package)
            else:
-               suite_id = db_access.get_suite_id(suite);
-               que = "SELECT s.version FROM source s JOIN src_associations sa ON (s.id = sa.source) WHERE sa.suite = %d AND s.source = '%s'" % (suite_id, package)
+               # source must exist in suite X, or in some other suite that's
+               # mapped to X, recursively... silent-maps are counted too,
+               # unreleased-maps aren't.
+               maps = self.Cnf.ValueList("SuiteMappings")[:]
+               maps.reverse()
+               maps = [ m.split() for m in maps ]
+               maps = [ (x[1], x[2]) for x in maps 
+                               if x[0] == "map" or x[0] == "silent-map" ]
+               s = [suite]
+               for x in maps:
+                       if x[1] in s and x[0] not in s:
+                               s.append(x[0])
+               
+               que = "SELECT s.version FROM source s JOIN src_associations sa ON (s.id = sa.source) JOIN suite su ON (sa.suite = su.id) WHERE s.source = '%s' AND (%s)" % (package, string.join(["su.suite_name = '%s'" % a for a in s], " OR "));
             q = self.projectB.query(que)
 
             # Reduce the query results to a list of version numbers
             ql = map(lambda x: x[0], q.getresult());
 
             # Try (1)
-            if ql.count(source_version):
+            if source_version in ql:
                 continue
 
             # Try (2)
             orig_source_version = re_bin_only_nmu_of_mu.sub('', source_version)
-            if ql.count(orig_source_version):
+            if orig_source_version in ql:
                 continue
 
             # Try (3)
             orig_source_version = re_bin_only_nmu_of_nmu.sub('', source_version)
-            if ql.count(orig_source_version):
+            if orig_source_version in ql:
                 continue
 
             # No source found...
             okay = 0
+       return okay
 
     ################################################################################
 
@@ -734,7 +764,7 @@ SELECT b.id FROM binaries b, architecture a
                                    files[file]["version"],
                                    files[file]["architecture"]))
         if q.getresult():
-            self.reject("can not overwrite existing copy of '%s' already in the archive." % (file));
+            self.reject("%s: can not overwrite existing copy already in the archive." % (file));
 
         return self.reject_message;