#!/usr/bin/env python
# Handles NEW and BYHAND packages
-# Copyright (C) 2001 James Troup <james@nocrew.org>
-# $Id: lisa,v 1.4 2002-02-22 02:20:06 troup Exp $
+# Copyright (C) 2001, 2002 James Troup <james@nocrew.org>
+# $Id: lisa,v 1.13 2002-05-19 19:55:56 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.4 $";
+lisa_version = "$Revision: 1.13 $";
Cnf = None;
Options = None;
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"]);
del files[file]["new"];
del new[pkg];
- if changes["distribution"].has_key("stable"):
+ 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"):
################################################################################
-# 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)
+ Katie.pkg.changes_file = a;
+ Katie.init_vars();
+ Katie.update_vars();
+ a_changes = copy.copy(Katie.pkg.changes);
except:
return 1;
try:
- b_changes = utils.parse_changes(b, 0)
+ Katie.pkg.changes_file = b;
+ Katie.init_vars();
+ Katie.update_vars();
+ b_changes = copy.copy(Katie.pkg.changes);
except:
return -1;
- utils.cc_fix_changes (a_changes);
- utils.cc_fix_changes (b_changes);
+ # 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;
# 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;
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);
################################################################################
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;
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';
file.write(line);
- return ret_code;
+ note = Katie.pkg.changes.get("lisa note");
+ if note:
+ print "*"*75;
+ print note;
+ print "*"*75;
+ return broken, note;
################################################################################
################################################################################
################################################################################
-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);
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;
Katie.pkg.files[file]["priority"] = priority;
new[pkg]["section"] = section;
new[pkg]["priority"] = priority;
- os.unlink(temp_filename);
################################################################################
got_answer = 1;
if answer == 'E':
- spawn_editor(new);
+ edit_new(new);
elif answer == 'D':
done = 1;
else:
################################################################################
+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);
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,"");
################################################################################
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"]);
projectB.query("COMMIT WORK");
- if Cnf.FindI("Dinstall::BXANotify"):
+ if Cnf.FindB("Dinstall::BXANotify"):
do_bxa_notification();
################################################################################
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));
if Options["No-Action"] or Options["Automatic"]:
answer = 'S';
- broken = print_new(new, 0);
+ (broken, note) = print_new(new, 0);
prompt = "";
- if not broken:
+
+ if not broken and not note:
prompt = "Add overrides, ";
- else:
+ 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, [S]kip, 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 = utils.our_raw_input(prompt);
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':
-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)
('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")
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"]:
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);
+ if len(changes_files) > 50:
+ sys.stderr.write("Sorting changes...\n");
+ 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);