--- a/log.pl Thu Mar 26 09:44:00 2009 +0100
+++ b/log.pl Thu Mar 26 09:46:50 2009 +0100
@@ -13,7 +13,27 @@
start special file processing (assuming output
from apt, with text (default: APT: upgrade) going
to the first line)
+ --logfile=s use this(!) logfile
#
+# something about charsets
+# * We assume the LOG file is always UTF-8!
+# (I know, it's not true for historical entries, may be we can
+# build some tool to convert the file line-by-line, or at least
+# entry-by-entry -- and our database too.
+# * The mail is sent always as UTF-8!
+# * The current charset could be found using "langinfo CODESET"
+# (hopefully - needs to be tested)
+# Conclusion:
+# - On opening/reading the log file: convert from UTF-8 -> current codeset
+# - If this fails, issue a warning, use "head <something>" to show the
+# last LOG entry directly and then fire up the editor with an
+# empty file (or just added notice why we do not show the old
+# messages)
+# - After editing: convert the current messsage to from the current
+# codeset UTF-8
+# - The same is for message on command line (but this is more easy, we
+# do not have to cope with the old message log
+
use strict;
use warnings;
@@ -25,6 +45,8 @@
use Mail::Mailer;
use DBI;
use MIME::QuotedPrint;
+use I18N::Langinfo qw(langinfo CODESET);
+use Text::Iconv;
use Logbuch::HG;
@@ -47,19 +69,19 @@
my $ME = basename $0;
-my $DSN = "DBI:mysql:logbuch:pu.schlittermann.de";
+my $DSN = "DBI:mysql:logbuch:pu.schlittermann.de";
my $USER = "logbuch";
-my $PW = "HIDDEN";
+my $PW = "HIDDEN";
-my $LOG = "$ENV{HOME}/LOG";
my $EDITOR = $ENV{VISUAL} || $ENV{EDITOR} || "vim";
my $MAGIC = "#--- all changes below are ignored ---#\n";
-my $opt_db = 1;
-my $opt_mail = 1;
+my $opt_db = 1;
+my $opt_mail = 1;
my $opt_message = "";
-my $opt_apt = "";
+my $opt_apt = "";
my $opt_initdir = "";
+my $opt_file = "$ENV{HOME}/LOG";
my $Dbh;
@@ -70,213 +92,214 @@
MAIN: {
- GetOptions("db!" => \$opt_db,
- "mail!" => \$opt_mail,
- "message=s" => \$opt_message,
- "type=s" => \$opt_apt,
- "init-dir=s" => \$opt_initdir,
+ GetOptions(
+ "db!" => \$opt_db,
+ "mail!" => \$opt_mail,
+ "message=s" => \$opt_message,
+ "type=s" => \$opt_apt,
+ "init-dir=s" => \$opt_initdir,
+ "file=s" => \$opt_file,
) or die eval "\"$USAGE\"";
if ($opt_message =~ /^@(.*)/) {
- @ARGV = $1;
- $opt_message = join "", <>;
- } elsif ($opt_message eq "-") {
- $opt_message = join "", <STDIN>;
- } elsif ($opt_message =~ /^apt(?::(.*))?\@(\S+)/) {
- open(I, $2) or die "Can't open $2: $!\n";
- $opt_message = ($1 ? "APT: $1\n" : "APT: upgrade\n")
- . join "", map {
- if (/^\d/) { ($_) }
- elsif ( /^(?:Inst|Conf|Remv|Purg)/ ) { ("- $_") }
- else { () }
- } <I>;
+ @ARGV = $1;
+ $opt_message = join "", <>;
+ }
+ elsif ($opt_message eq "-") {
+ $opt_message = join "", <STDIN>;
+ }
+ elsif ($opt_message =~ /^apt(?::(.*))?\@(\S+)/) {
+ open(I, $2) or die "Can't open $2: $!\n";
+ $opt_message = ($1 ? "APT: $1\n" : "APT: upgrade\n") . join "", map {
+ if (/^\d/) { ($_) }
+ elsif (/^(?:Inst|Conf|Remv|Purg)/) { ("- $_") }
+ else { () }
+ } <I>;
}
if ($opt_message =~ /\n/) {
- $opt_message =~ s/\n/\n /g;
+ $opt_message =~ s/\n/\n /g;
}
if (defined @config::notify_dirs || $opt_initdir) {
- check_hg_bin();
+ check_hg_bin();
}
if ($opt_initdir) {
- my $repo = Logbuch::HG->new( repo => $opt_initdir );
+ my $repo = Logbuch::HG->new(repo => $opt_initdir);
- $repo->is_repository() and
- die "$ME: directory already initialized, skipping\n";
+ $repo->is_repository()
+ and die "$ME: directory already initialized, skipping\n";
- $repo->init() or
- die "E: initialization failed\n";
-
- $repo->addremove();
- $repo->commit("initial check in");
+ $repo->init()
+ or die "E: initialization failed\n";
- exit 0;
+ $repo->addremove();
+ $repo->commit("initial check in");
+
+ exit 0;
}
my $hg_status_text = "";
if (defined @config::notify_dirs) {
- foreach my $dir (@config::notify_dirs) {
- -d $dir or next;
+ foreach my $dir (@config::notify_dirs) {
+ -d $dir or next;
- print "$ME: Checking $dir for modifications\n";
+ print "$ME: Checking $dir for modifications\n";
- my $repo = Logbuch::HG->new( repo => $dir );
- $repo->is_repository() or
- die "$ME: directory $dir not initialized please call: \n",
- " # $ME --init-dir $dir \n";
+ my $repo = Logbuch::HG->new(repo => $dir);
+ $repo->is_repository()
+ or die "$ME: directory $dir not initialized please call: \n",
+ " # $ME --init-dir $dir \n";
- $repo->addremove();
- $hg_status_text .= $repo->status();
- }
+ $repo->addremove();
+ $hg_status_text .= $repo->status();
+ }
}
if ($opt_db) {
- $Dbh = DBI->connect($DSN, $USER, $PW, {RaiseError => 1})
- or die $DBI::errstr;
- END { $Dbh->disconnect() if $Dbh; }
+ $Dbh = DBI->connect($DSN, $USER, $PW, { RaiseError => 1 })
+ or die $DBI::errstr;
+ END { $Dbh->disconnect() if $Dbh; }
}
# Temporärfile öffnen
- my ($fh, $file);
- END { unlink $file if $file; }
- ($fh, $file) = tempfile(DIR => "/tmp");
+ my ($fh, $file) = tempfile(DIR => "/tmp", UNLINK => 1);
- my $auto_message = (not $hg_status_text) ? "" :
- "\n"
- . " Modified config files since last log entry listend below...\n"
- . $hg_status_text
- . "\n";
+ my $auto_message =
+ (not $hg_status_text)
+ ? ""
+ : "\n"
+ . " Modified config files since last log entry listend below...\n"
+ . $hg_status_text . "\n";
# Kopftext eintragen
- print $fh
- "Date: ", scalar(localtime()), "\n",
- "User: ", identity(), "\n",
- "MailTo: ", mailto(), "\n",
- "\n",
- " * $opt_message",
- "\n",
- $auto_message,
- "\n", $MAGIC, "\n";
+ print $fh "Date: ", scalar(localtime()), "\n",
+ "User: ", identity(), "\n",
+ "MailTo: ", mailto(), "\n",
+ "\n",
+ " * $opt_message",
+ "\n",
+ $auto_message,
+ "\n", $MAGIC, "\n";
- if (!-e $LOG) {
- open(X, $_ = ">>$LOG") or die "Can't open $_: $!\n";
- close X;
- };
+ if (!-e $opt_file) {
+ open(X, $_ = ">>$opt_file") or die "Can't open $_: $!\n";
+ close X;
+ }
- open(IN, $_ = $LOG) or die "Can't open $_: $!\n";
+ open(IN, $_ = $opt_file) or die "Can't open $_: $!\n";
print $fh <IN>;
close IN;
if (!$opt_message) {
- my $stamp = stat($file)->mtime();
- system($EDITOR, "+5", $file);
-
- if ($stamp == stat($file)->mtime()) {
- print STDERR "Nothing changed. Discarding the note.\n";
- unlink $file;
- exit 0;
- }
+ my $stamp = stat($file)->mtime();
+ system($EDITOR, "+5", $file);
+
+ if ($stamp == stat($file)->mtime()) {
+ print STDERR "Nothing changed. Discarding the note.\n";
+ unlink $file;
+ exit 0;
+ }
}
# Jetzt wie versprochen den (eventuell geänderten Rest) aus der
# Temp-Datei wegschneiden
{
- my ($date, $user, $head, $text, $mailto);
- my $pos;
+ my ($date, $user, $head, $text, $mailto);
+ my $pos;
+
+ seek $fh, 0, 0;
+ for ($pos = tell $fh ; defined($_ = <$fh>) ; $pos = tell $fh) {
- seek $fh, 0, 0;
- for($pos = tell $fh; defined($_ = <$fh>); $pos = tell $fh) {
+ $head .= "$_" if not $text and /^\S+:/;
- $head .= "$_" if not $text and /^\S+:/;
+ /^Date:\s+(.*)/ and $date = $1, next;
+ /^User:\s+(.*)/ and $user = $1, next;
+ /^MailTo:\s(.*)/ and $mailto = $1, next;
+ last if $_ eq $MAGIC;
- /^Date:\s+(.*)/ and $date = $1, next;
- /^User:\s+(.*)/ and $user = $1, next;
- /^MailTo:\s(.*)/ and $mailto = $1, next;
- last if $_ eq $MAGIC;
-
- $text .= $_ if /\S/ || $text; # somit werden die ersten Leerzeilen übersprungen
- }
+ $text .= $_
+ if /\S/
+ || $text; # somit werden die ersten Leerzeilen übersprungen
+ }
- $text =~ s/\s*$//s; # Leerzeichen am Ende weg
+ $text =~ s/\s*$//s; # Leerzeichen am Ende weg
- truncate $fh, $pos;
- seek $fh, 0, 2;
+ truncate $fh, $pos;
+ seek $fh, 0, 2;
- if ($opt_db) {
- my $sth = $Dbh->prepare("
+ if ($opt_db) {
+ my $sth = $Dbh->prepare("
INSERT INTO log (host, date, user, mailto, text)
VALUES(?, now(), ?, ?, ?)");
- $sth->execute(hostname(), $user, $mailto, $text);
- print STDERR "Database entry inserted\n";
- }
+ $sth->execute(hostname(), $user, $mailto, $text);
+ print STDERR "Database entry inserted\n";
+ }
- if ($opt_mail and $mailto) {
- my $mailer = new Mail::Mailer "sendmail"
- or die "Can't create Mailer: $!\n";
+ if ($opt_mail and $mailto) {
+ my $mailer = new Mail::Mailer "sendmail"
+ or die "Can't create Mailer: $!\n";
- my $subject = (split /\n/, $text)[0];
- $subject =~ s/^\s*\S\s//; # cut the "itemizer"
- $subject = encode_qp("Service [". hostname(). "]: $subject\n");
- $subject =~ s/\n(.)/\n\t$1/g;
+ my $subject = (split /\n/, $text)[0];
+ $subject =~ s/^\s*\S\s//; # cut the "itemizer"
+ $subject = encode_qp("Service [" . hostname() . "]: $subject\n");
+ $subject =~ s/\n(.)/\n\t$1/g;
- $mailer->open({
- "Content-Type" => "text/plain; charset=utf-8",
- "Content-Transfer-Encoding" => "8bit",
- "To" => $mailto,
- "Subject" => $subject});
- print $mailer $head, "\n", $text;
- close $mailer;
- print STDERR "Mail sent (to $mailto).\n";
- }
+ $mailer->open(
+ {
+ "Content-Type" => "text/plain; charset=utf-8",
+ "Content-Transfer-Encoding" => "8bit",
+ "To" => $mailto,
+ "Subject" => $subject
+ }
+ );
+ print $mailer $head, "\n", $text;
+ close $mailer;
+ print STDERR "Mail sent (to $mailto).\n";
+ }
- if (defined @config::notify_dirs) {
- foreach my $dir (@config::notify_dirs) {
- -d $dir or next;
+ if (defined @config::notify_dirs) {
+ foreach my $dir (@config::notify_dirs) {
+ -d $dir or next;
- my $repo = Logbuch::HG->new( repo => $dir );
- $repo->commit();
- }
- }
+ my $repo = Logbuch::HG->new(repo => $dir);
+ $repo->commit();
+ }
+ }
}
# Und jetzt das aus der alten Datei dort anhängen
- open(IN, $_ = $LOG) or die "Can't open $_: $!\n";
+ open(IN, $_ = $opt_file) or die "Can't open $_: $!\n";
print $fh <IN>;
close $fh;
close IN;
- move $file, $LOG;
+ move $file, $opt_file;
}
-sub identity()
-{
+sub identity() {
my $user = `who am i`;
chomp $user;
$user .= " [" . ($ENV{IUS_PROFILE} || $ENV{REMOTE_USER} || "-") . "]";
return $user;
}
-sub hostname()
-{
+sub hostname() {
my $r = `hostname -f`;
chomp($r);
return $r;
}
-sub mailto()
-{
+sub mailto() {
return join(", ", @config::mailto);
}
-
-sub check_hg_bin()
-{
+sub check_hg_bin() {
if (not Logbuch::HG::hg_available()) {
- die <<'EOF';
+ die <<'EOF';
You requested an operation based on hg/mercurial but this tool is
not installed!
@@ -292,6 +315,5 @@
}
}
-
# vim:sts=4 sw=4 aw ai sm: