]> git.decadent.org.uk Git - dak.git/blobdiff - lisa
sync
[dak.git] / lisa
diff --git a/lisa b/lisa
index ab94ed4f03e2ac308b029c60182b7985aacf37da..45c500f677296c2880c71ae10d3d1906664c1088 100755 (executable)
--- a/lisa
+++ b/lisa
@@ -1,8 +1,8 @@
 #!/usr/bin/env python
 
 # Handles NEW and BYHAND packages
-# Copyright (C) 2001  James Troup <james@nocrew.org>
-# $Id: lisa,v 1.3 2002-02-22 01:03:07 troup Exp $
+# Copyright (C) 2001, 2002  James Troup <james@nocrew.org>
+# $Id: lisa,v 1.12 2002-05-19 02:00:48 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
 
 ################################################################################
 
-import errno, os, readline, string, stat, sys, tempfile;
+import copy, errno, os, readline, string, stat, sys, tempfile;
 import apt_pkg, apt_inst;
 import db_access, fernanda, katie, logging, utils;
 
 # Globals
-lisa_version = "$Revision: 1.3 $";
+lisa_version = "$Revision: 1.12 $";
 
 Cnf = None;
 Options = None;
@@ -85,6 +85,9 @@ def determine_new (changes, files):
         pkg = f["package"];
         priority = f["priority"];
         section = f["section"];
+        # FIXME: unhardcode
+        if section == "non-US/main":
+            section = "non-US";
         type = get_type(f);
         component = f["component"];
 
@@ -110,7 +113,7 @@ def determine_new (changes, files):
         if f.has_key("othercomponents"):
             new[pkg]["othercomponents"] = f["othercomponents"];
 
-    for suite in changes["distribution"].keys():
+    for suite in changes["suite"].keys():
         suite_id = db_access.get_suite_id(suite);
         for pkg in new.keys():
             component_id = db_access.get_component_id(new[pkg]["component"]);
@@ -123,60 +126,72 @@ def determine_new (changes, files):
                         del files[file]["new"];
                 del new[pkg];
 
+    if changes["suite"].has_key("stable"):
+        print "WARNING: overrides will be added for stable!";
+    for pkg in new.keys():
+        if new[pkg].has_key("othercomponents"):
+            print "WARNING: %s already present in %s distribution." % (pkg, new[pkg]["othercomponents"]);
+
     return new;
 
 ################################################################################
 
-# Sort by 'have source', by ctime, by source name, by source version number, by filename
+# Sort by 'have note', 'have source', by ctime, by source name, by
+# source version number, and finally by filename
 
-def changes_compare_by_time (a, b):
+def changes_compare (a, b):
     try:
-        a_changes = utils.parse_changes(a, 0)
+        a_changes = utils.parse_changes(a);
     except:
         return 1;
 
     try:
-        b_changes = utils.parse_changes(b, 0)
+        b_changes = utils.parse_changes(b);
     except:
         return -1;
 
     utils.cc_fix_changes (a_changes);
     utils.cc_fix_changes (b_changes);
 
-    # Sort by 'have source'
+    # Sort by 'have note';
+    a_has_note = a_changes.get("lisa note");
+    b_has_note = b_changes.get("lisa note");
+    if a_has_note and not b_has_note:
+        return -1;
+    elif b_has_note and not a_has_note:
+        return 1;
 
-    a_has_source = a_changes["architecture"].get("source")
-    b_has_source = b_changes["architecture"].get("source")
+    # 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 ctime
-    a_ctime = os.stat(a)[stat.ST_CTIME];
-    b_ctime = os.stat(b)[stat.ST_CTIME];
-    q = cmp (a_ctime, b_ctime);
-    if q:
-        return q;
-
-    # Sort by source name
-
+    # Sort by ctime-per-source
     a_source = a_changes.get("source");
     b_source = b_changes.get("source");
+    if a_source != b_source:
+        a_ctime = os.stat(a)[stat.ST_CTIME];
+        b_ctime = os.stat(b)[stat.ST_CTIME];
+        q = cmp (a_ctime, b_ctime);
+        if q:
+            return q;
+
+    # Sort by source name
     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
+        return -q;
 
     # Fall back to sort by filename
-
     return cmp(a, b);
 
 ################################################################################
@@ -242,7 +257,7 @@ def check_valid (new):
 
 def print_new (new, indexed, file=sys.stdout):
     check_valid(new);
-    ret_code = 0;
+    broken = 0;
     index = 0;
     for pkg in new.keys():
         index = index + 1;
@@ -250,19 +265,22 @@ def print_new (new, indexed, file=sys.stdout):
         priority = new[pkg]["priority"];
         if new[pkg]["section id"] == -1:
             section = section + "[!]";
-            ret_code = 1;
+            broken = 1;
         if new[pkg]["priority id"] == -1:
             priority = priority + "[!]";
-            ret_code = 1;
+            broken = 1;
         if indexed:
             line = "(%s): %-20s %-20s %-20s" % (index, pkg, priority, section);
         else:
             line = "%-20s %-20s %-20s" % (pkg, priority, section);
         line = string.strip(line)+'\n';
-        if new[pkg].has_key("othercomponents"):
-            line = line + "WARNING: Already present in %s distribution.\n" % (new[pkg]["othercomponents"]);
         file.write(line);
-    return ret_code;
+    note = Katie.pkg.changes.get("lisa note");
+    if note:
+        print "*"*75;
+        print note;
+        print "*"*75;
+    return broken, note;
 
 ################################################################################
 
@@ -293,7 +311,7 @@ def index_range (index):
 ################################################################################
 ################################################################################
 
-def spawn_editor (new):
+def edit_new (new):
     # Write the current data to a temporary file
     temp_filename = tempfile.mktemp();
     fd = os.open(temp_filename, os.O_RDWR|os.O_CREAT|os.O_EXCL, 0700);
@@ -305,10 +323,14 @@ def spawn_editor (new):
     editor = os.environ.get("EDITOR","vi")
     result = os.system("%s %s" % (editor, temp_filename))
     if result != 0:
-        utils.fubar ("vi invocation failed for `%s'!" % (temp_filename), result)
-    # Read the (edited) data back in
-    file = utils.open_file(temp_filename);
-    for line in file.readlines():
+        utils.fubar ("%s invocation failed for %s." % (editor, temp_filename), result)
+    # Read the edited data back in
+    temp_file = utils.open_file(temp_filename);
+    lines = temp_file.readlines();
+    temp_file.close();
+    os.unlink(temp_filename);
+    # Parse the new data
+    for line in lines:
         line = string.strip(line[:-1]);
         if line == "":
             continue;
@@ -329,7 +351,6 @@ def spawn_editor (new):
                 Katie.pkg.files[file]["priority"] = priority;
             new[pkg]["section"] = section;
             new[pkg]["priority"] = priority;
-    os.unlink(temp_filename);
 
 ################################################################################
 
@@ -349,7 +370,7 @@ def edit_index (new, index):
         edit_priority = edit_section = 0;
 
         while string.find(prompt, answer) == -1:
-            answer = raw_input(prompt);
+            answer = utils.our_raw_input(prompt);
             m = katie.re_default_answer.match(prompt)
             if answer == "":
                 answer = m.group(1)
@@ -369,7 +390,7 @@ def edit_index (new, index):
             readline.set_completer(Priorities.complete);
             got_priority = 0;
             while not got_priority:
-                new_priority = string.strip(raw_input("New priority: "));
+                new_priority = string.strip(utils.our_raw_input("New priority: "));
                 if Priorities.priorities.count(new_priority) == 0:
                     print "E: '%s' is not a valid priority, try again." % (new_priority);
                 else:
@@ -381,7 +402,7 @@ def edit_index (new, index):
             readline.set_completer(Sections.complete);
             got_section = 0;
             while not got_section:
-                new_section = string.strip(raw_input("New section: "));
+                new_section = string.strip(utils.our_raw_input("New section: "));
                 if Sections.sections.count(new_section) == 0:
                     print "E: '%s' is not a valid section, try again." % (new_section);
                 else:
@@ -415,8 +436,8 @@ def edit_overrides (new):
 
         got_answer = 0
         while not got_answer:
-            answer = raw_input(prompt)
-            answer = string.upper(answer[:1])
+            answer = utils.our_raw_input(prompt);
+            answer = string.upper(answer[:1]);
             if answer == "E" or answer == "D":
                 got_answer = 1;
             elif katie.re_isanum.match (answer):
@@ -427,7 +448,7 @@ def edit_overrides (new):
                     got_answer = 1;
 
         if answer == 'E':
-            spawn_editor(new);
+            edit_new(new);
         elif answer == 'D':
             done = 1;
         else:
@@ -437,6 +458,41 @@ def edit_overrides (new):
 
 ################################################################################
 
+def edit_note(note):
+    # Write the current data to a temporary file
+    temp_filename = tempfile.mktemp();
+    fd = os.open(temp_filename, os.O_RDWR|os.O_CREAT|os.O_EXCL, 0700);
+    os.close(fd);
+    temp_file = utils.open_file(temp_filename, 'w');
+    temp_file.write(note);
+    temp_file.close();
+    editor = os.environ.get("EDITOR","vi")
+    answer = 'E';
+    while answer == 'E':
+        os.system("%s %s" % (editor, temp_filename))
+        temp_file = utils.open_file(temp_filename);
+        note = string.rstrip(temp_file.read());
+        temp_file.close();
+        print "Note:";
+        print utils.prefix_multi_line_string(note,"  ");
+        prompt = "[D]one, Edit, Abandon, Quit ?"
+        answer = "XXX";
+        while string.find(prompt, answer) == -1:
+            answer = utils.our_raw_input(prompt);
+            m = katie.re_default_answer.search(prompt);
+            if answer == "":
+                answer = m.group(1);
+            answer = string.upper(answer[:1]);
+    os.unlink(temp_filename);
+    if answer == 'A':
+        return;
+    elif answer == 'Q':
+        sys.exit(0);
+    Katie.pkg.changes["lisa note"] = note;
+    Katie.dump_vars(Cnf["Dir::Queue::New"]);
+
+################################################################################
+
 def check_pkg ():
     try:
         less_fd = os.popen("less -", 'w', 0);
@@ -478,7 +534,7 @@ def do_bxa_notification():
             summary = summary + "Package: %s\n" % (control.Find("Package"));
             summary = summary + "Description: %s\n" % (control.Find("Description"));
     Katie.Subst["__BINARY_DESCRIPTIONS__"] = summary;
-    bxa_mail = utils.TemplateSubst(Katie.Subst,open(Cnf["Dir::TemplatesDir"]+"/lisa.bxa_notification","r").read());
+    bxa_mail = utils.TemplateSubst(Katie.Subst,Cnf["Dir::Templates"]+"/lisa.bxa_notification");
     utils.send_mail(bxa_mail,"");
 
 ################################################################################
@@ -488,7 +544,7 @@ def add_overrides (new):
     files = Katie.pkg.files;
 
     projectB.query("BEGIN WORK");
-    for suite in changes["distribution"].keys():
+    for suite in changes["suite"].keys():
         suite_id = db_access.get_suite_id(suite);
         for pkg in new.keys():
             component_id = db_access.get_component_id(new[pkg]["component"]);
@@ -503,7 +559,7 @@ def add_overrides (new):
 
     projectB.query("COMMIT WORK");
 
-    if Cnf.FindI("Dinstall::BXANotify"):
+    if Cnf.FindB("Dinstall::BXANotify"):
         do_bxa_notification();
 
 ################################################################################
@@ -513,14 +569,17 @@ def do_new():
     files = Katie.pkg.files;
     changes = Katie.pkg.changes;
 
+    # Make a copy of distribution we can happily trample on
+    changes["suite"] = copy.copy(changes["distribution"]);
+
     # Fix up the list of target suites
-    for suite in changes["distribution"].keys():
+    for suite in changes["suite"].keys():
         override = Cnf.Find("Suite::%s::OverrideSuite" % (suite));
         if override:
-            del changes["distribution"][suite];
-            changes["distribution"][override] = 1;
+            del changes["suite"][suite];
+            changes["suite"][override] = 1;
     # Validate suites
-    for suite in changes["distribution"].keys():
+    for suite in changes["suite"].keys():
         suite_id = db_access.get_suite_id(suite);
         if suite_id == -1:
             utils.fubar("%s has invalid suite '%s' (possibly overriden).  say wha?" % (changes, suite));
@@ -536,23 +595,24 @@ def do_new():
 
         answer = "XXX";
         if Options["No-Action"] or Options["Automatic"]:
-            answer = 'S'
-        if Options["Automatic"]:
-            answer = 'A';
+            answer = 'S';
 
-        broken = print_new(new, 0);
+        (broken, note) = print_new(new, 0);
         prompt = "";
-        if not broken:
-            prompt = "[A]dd overrides, ";
-        else:
+
+        if not broken and not note:
+            prompt = "Add overrides, ";
+        if broken:
             print "W: [!] marked entries must be fixed before package can be processed.";
-            if answer == 'A':
-                answer = 'E';
-        prompt = prompt + "Edit overrides, Check, Manual reject, Skip, Quit ?";
+        if note:
+            print "W: note must be removed before package can be processed.";
+            prompt = prompt + "Remove note, ";
+
+        prompt = prompt + "Edit overrides, Check, Manual reject, Note edit, [S]kip, Quit ?";
 
         while string.find(prompt, answer) == -1:
-            answer = raw_input(prompt)
-            m = katie.re_default_answer.match(prompt)
+            answer = utils.our_raw_input(prompt);
+            m = katie.re_default_answer.search(prompt);
             if answer == "":
                 answer = m.group(1)
             answer = string.upper(answer[:1])
@@ -564,9 +624,16 @@ def do_new():
         elif answer == 'E':
             new = edit_overrides (new);
         elif answer == 'M':
-            Katie.do_reject(1, Options["Manual-Reject"]);
-            os.unlink(Katie.pkg.changes_file[:-8]+".katie");
-            done = 1;
+            aborted = Katie.do_reject(1, Options["Manual-Reject"]);
+            if not aborted:
+                os.unlink(Katie.pkg.changes_file[:-8]+".katie");
+                done = 1;
+        elif answer == 'N':
+            edit_note(changes.get("lisa note", ""));
+        elif answer == 'R':
+            confirm = string.lower(utils.our_raw_input("Really clear note (y/N)? "));
+            if confirm == "y":
+                del changes["lisa note"];
         elif answer == 'S':
             done = 1;
         elif answer == 'Q':
@@ -582,7 +649,6 @@ def usage (exit_code=0):
   -h, --help                show this help and exit.
   -m, --manual-reject=MSG   manual reject with `msg'
   -n, --no-action           don't do anything
-  -s, --sort=TYPE           sort type ('time' or 'normal')
   -V, --version             display the version number and exit"""
     sys.exit(exit_code)
 
@@ -597,14 +663,11 @@ def init():
                  ('h',"help","Lisa::Options::Help"),
                  ('m',"manual-reject","Lisa::Options::Manual-Reject", "HasArg"),
                  ('n',"no-action","Lisa::Options::No-Action"),
-                 ('s',"sort","Lisa::Options::Sort","HasArg"),
                  ('V',"version","Lisa::Options::Version")];
 
     for i in ["automatic", "help", "manual-reject", "no-action", "version"]:
         if not Cnf.has_key("Lisa::Options::%s" % (i)):
             Cnf["Lisa::Options::%s" % (i)] = "";
-    if not Cnf.has_key("Lisa::Options::Sort"):
-        Cnf["Lisa::Options::Sort"] = "time";
 
     changes_files = apt_pkg.ParseCommandLine(Cnf,Arguments,sys.argv);
     Options = Cnf.SubTree("Lisa::Options")
@@ -616,9 +679,6 @@ def init():
         print "lisa %s" % (lisa_version);
         sys.exit(0);
 
-    if Options["Sort"] != "time" and Options["Sort"] != "normal":
-        utils.fubar("Unrecognised sort type '%s'. (Recognised sort types are: time and normal)" % (Options["Sort"]));
-
     Katie = katie.Katie(Cnf);
 
     if not Options["No-Action"]:
@@ -660,11 +720,11 @@ def do_byhand():
             prompt = "Manual reject, [S]kip, Quit ?";
 
         while string.find(prompt, answer) == -1:
-            answer = raw_input(prompt)
-            m = katie.re_default_answer.match(prompt)
+            answer = utils.our_raw_input(prompt);
+            m = katie.re_default_answer.search(prompt);
             if answer == "":
-                answer = m.group(1)
-            answer = string.upper(answer[:1])
+                answer = m.group(1);
+            answer = string.upper(answer[:1]);
 
         if answer == 'A':
             done = 1;
@@ -735,22 +795,20 @@ def end():
 
 def main():
     changes_files = init();
-
-    # Sort the changes files
-    if Options["Sort"] == "time":
-        changes_files.sort(changes_compare_by_time);
-    else:
-        changes_files.sort(utils.changes_compare);
+    changes_files.sort(changes_compare);
 
     # Kill me now? **FIXME**
     Cnf["Dinstall::Options::No-Mail"] = "";
-    bcc = "X-Lisa: %s" % (lisa_version);
+    bcc = "X-Katie: %s" % (lisa_version);
     if Cnf.has_key("Dinstall::Bcc"):
         Katie.Subst["__BCC__"] = bcc + "\nBcc: %s" % (Cnf["Dinstall::Bcc"]);
     else:
         Katie.Subst["__BCC__"] = bcc;
 
     for changes_file in changes_files:
+        changes_file = utils.validate_changes_file_arg(changes_file, 0);
+        if not changes_file:
+            continue;
         print "\n" + changes_file;
         do_pkg (changes_file);