[kaffe-siteadmin] CVS kaffe-project-services (jim): Start describing loginfo-cvsps setup (incomplete)
Kaffe CVS
cvs-commits at kaffe.org
Wed Jan 14 09:16:02 PST 2004
PatchSet 2
Date: 2004/01/14 17:15:03
Author: jim
Branch: HEAD
Tag: (none)
Log:
Start describing loginfo-cvsps setup (incomplete)
Members:
loginfo-cvsps/README:INITIAL->1.1
loginfo-cvsps/incoming-mail.pl:INITIAL->1.1
loginfo-cvsps/loginfo:INITIAL->1.1
loginfo-cvsps/martin-log.pl:INITIAL->1.1
===================================================================
Checking out kaffe-project-services/loginfo-cvsps/README
RCS: /home/cvs/kaffe/kaffe-project-services/loginfo-cvsps/README,v
VERS: 1.1
***************
--- /dev/null Sun Aug 4 19:57:58 2002
+++ kaffe-project-services/loginfo-cvsps/README Wed Jan 14 17:15:05 2004
@@ -0,0 +1,35 @@
+Generating "commitlog" messages using CVSps
+===========================================
+
+By Jim Pick
+
+Here's a quick mini-HOWTO describing the scripts I created to get
+generate CVS commit email messages for the kaffe at kaffe.org mailing
+list, using CVSps.
+
+ http://www.cobite.com/cvsps/
+
+CVSps is a tools which will examine CVS history, and try to break
+it up into "patchsets" which roughly correspond to individual checkins.
+Normally, CVS doesn't retain this information at checkin time (it's just
+a bunch of directories with RCS files, really), so it must be deduced.
+
+Warning: What I am about to describe is a bit of "Rude-Goldberg" setup,
+and is somewhat tricky to setup, and it's got some problems, which I
+will try to note.
+
+I started with the "martin-log.pl" Perl script, which I borrowed from the
+gnome.org CVS. I used that on kaffe.org for a while, but I was not
+satisfied with output. In particular, I wanted to be able to see the
+patches for each commit.
+
+I discovered the cvsps tool, and tried to hack that into the martin-log.pl
+script. However, that turned out to be unworkable, as the commitlog
+scripts run during the cvs commit, as the user doing the commit (or as the
+user that the pserver is running as). This was a problem, as cvsps can
+take a rather long time to run sometimes (especially when it is first
+building its cache). It was also very error prone.
+
+
+(to be continued...)
+
===================================================================
Checking out kaffe-project-services/loginfo-cvsps/incoming-mail.pl
RCS: /home/cvs/kaffe/kaffe-project-services/loginfo-cvsps/incoming-mail.pl,v
VERS: 1.1
***************
--- /dev/null Sun Aug 4 19:57:58 2002
+++ kaffe-project-services/loginfo-cvsps/incoming-mail.pl Wed Jan 14 17:15:05 2004
@@ -0,0 +1,275 @@
+#! /usr/bin/perl
+
+$ENV{TZ} = "UTC";
+
+open LOG, ">> /home/resend/log/mail.log" || die "Argh";
+
+print LOG "\n---------------\n";
+print LOG "Date: " . `date` . "\n\n";
+
+while (<>) {
+ print LOG "$_";
+ if (/^From: .*cvs-commits\@kaffe.org/) { $valid = 1; }
+ if (/^Resend-To:\s*(\S+)$/) { $resendTo = $1; }
+ if (/^Module name:\s*(\S+)$/) { $module = $1; }
+ if (/^Changes by:\s*(\S+)\s+/) { $user = $1; }
+
+ if (! $inLogMessage && /^Log Message:/) {
+ $inLogMessage = 1;
+ } elsif ($inLogMessage && /^Directory (.*) added to the repository$/) {
+ $addDir = $1;
+ } elsif ($inLogMessage && /^$/) {
+ $inLogMessage = 0;
+ }
+
+ if (! $inModifiedFiles && /^Modified files:/) {
+ $inModifiedFiles = 1;
+ } elsif ($inModifiedFiles && /^\s+(.*): (.*)$/) {
+ $dir = $1;
+ @files = split / /, $2;
+ $dir =~ s/^\s*(\S+)\s*$/\1/;
+ $lastdir = $dir;
+ for $file (@files) {
+ if ($dir eq ".") {
+ $modFiles{$file} = 1;
+ } else {
+ $modFiles{$dir . "/" . $file} = 1;
+ }
+ }
+ } elsif ($inModifiedFiles && /^\s+(.*)$/) {
+ $dir = $lastdir;
+ @files = split / /, $1;
+ for $file (@files) {
+ if ($dir eq ".") {
+ $modFiles{$file} = 1;
+ } else {
+ $modFiles{$dir . "/" . $file} = 1;
+ }
+ }
+ } elsif ($inModifiedFiles) {
+ $inModifiedFiles = 0;
+ }
+
+ if (! $inAddedFiles && /^Added files:/) {
+ $inAddedFiles = 1;
+ } elsif ($inAddedFiles && /^\s+(.*): (.*)$/) {
+ $dir = $1;
+ @files = split / /, $2;
+ $dir =~ s/^\s*(\S+)\s*$/\1/;
+ $lastdir = $dir;
+ for $file (@files) {
+ if ($dir eq ".") {
+ $addFiles{$file} = 1;
+ } else {
+ $addFiles{$dir . "/" . $file} = 1;
+ }
+ }
+ } elsif ($inAddedFiles && /^\s+(.*)$/) {
+ $dir = $lastdir;
+ @files = split / /, $1;
+ for $file (@files) {
+ if ($dir eq ".") {
+ $addFiles{$file} = 1;
+ } else {
+ $addFiles{$dir . "/" . $file} = 1;
+ }
+ }
+ } elsif ($inAddedFiles) {
+ $inAddedFiles = 0;
+ }
+
+ if (! $inRemovedFiles && /^Removed files:/) {
+ $inRemovedFiles = 1;
+ } elsif ($inRemovedFiles && /^\s+(.*): (.*)$/) {
+ $dir = $1;
+ @files = split / /, $2;
+ $dir =~ s/^\s*(\S+)\s*$/\1/;
+ $lastdir = $dir;
+ for $file (@files) {
+ if ($dir eq ".") {
+ $removeFiles{$file} = 1;
+ } else {
+ $removeFiles{$dir . "/" . $file} = 1;
+ }
+ }
+ } elsif ($inRemovedFiles && /^\s+(.*)$/) {
+ $dir = $lastdir;
+ @files = split / /, $1;
+ for $file (@files) {
+ if ($dir eq ".") {
+ $removeFiles{$file} = 1;
+ } else {
+ $removeFiles{$dir . "/" . $file} = 1;
+ }
+ }
+ } elsif ($inRemovedFiles) {
+ $inRemovedFiles = 0;
+ }
+}
+
+print LOG "\nProcessing...\n\n";
+if ( defined $addDir ) {
+ print LOG "Added dir $addDir - skipping\n";
+} elsif ( ! defined $module ) {
+ print LOG "module not defined\n";
+} elsif (! -d "/home/resend/checked-out/$module" ) {
+ print LOG "Module $module not in /home/resend/checked-out/$module\n";
+} elsif ( ! defined $resendTo ) {
+ print LOG "resentTo not defined\n";
+} else {
+
+ print LOG "DEBUG: Modified Files\n";
+ for $modFile (sort keys %modFiles) {
+ print LOG " $modFile\n";
+ }
+ print LOG "DEBUG: Added Files\n";
+ for $addFile (sort keys %addFiles) {
+ print LOG " $addFile\n";
+ }
+ print LOG "DEBUG: Removed Files\n";
+ for $removeFile (sort keys %removeFiles) {
+ print LOG " $removeFile\n";
+ }
+ print LOG "\n";
+
+ chdir("/home/resend/checked-out/$module");
+
+ $cmd="/usr/local/bin/cvsps -q -u -a $user -d \"`date -d \"1 day ago\" \"+%Y/%m/%d %H:%M:%S\"`\"";
+ print LOG "Running: $cmd\n\n";
+ open CVSPS, "$cmd 2>&1 |" ||
+ print LOG "cvsps failed\n" && die("cvsps failed");
+ $lastPatchSet = 0;
+ $lastCandidate = 0;
+ while (<CVSPS>) {
+ if (/^PatchSet (\d+)\s*$/) {
+ print LOG "DEBUG: Found PatchSet $1\n";
+ $lastPatchSet = $1;
+ $inMembers = 0;
+ }
+
+ if (! $inMembers && /^Members:/) {
+ $inMembers = 1;
+ undef %membersModifiedFrom;
+ undef %membersModifiedTo;
+ undef %membersAdded;
+ undef %membersRemovedFrom;
+ undef %membersRemovedTo;
+ } elsif ($inMembers && /^\s+(\S+):(.*)->(.*)/ ) {
+ $member = $1;
+ $from = $2;
+ $to = $3;
+ if ($from eq "INITIAL") {
+ $membersAdded{$member} = $to;
+ } elsif ($to =~ /DEAD/) {
+ $membersRemovedFrom{$member} = $from;
+ $membersRemovedTo{$member} = $to;
+ } else {
+ $membersModifiedFrom{$member} = $from;
+ $membersModifiedTo{$member} = $to;
+ }
+ } elsif ($inMembers) {
+ $inMembers = 0;
+ $matched = 0;
+ $unmatched = 0;
+ print LOG "DEBUG Members:\n";
+ for $member (sort keys %membersModifiedFrom) {
+ if ($modFiles{$member} || $addFiles{$member}) {
+ print LOG " $member\n";
+ $matched++;
+ } else {
+ print LOG " $member (Unmatched)\n";
+ $unmatched++;
+ }
+ }
+ for $member (sort keys %membersAdded) {
+ if ($addFiles{$member}) {
+ print LOG " $member\n";
+ $matched++;
+ } else {
+ print LOG " $member (Unmatched)\n";
+ $unmatched++;
+ }
+ }
+ for $member (sort keys %membersRemovedFrom) {
+ if ($removeFiles{$member}) {
+ print LOG " $member\n";
+ $matched++;
+ } else {
+ print LOG " $member (Unmatched)\n";
+ $unmatched++;
+ }
+ }
+ if ($matched > 0) {
+ print LOG "DEBUG: Flagged as candidate\n";
+ $candidate{$lastPatchSet} = $unmatched;
+ $lastCandidate = $lastPatchSet;
+ }
+ }
+ }
+ close CVSPS || print LOG "cvsps failed\n";
+
+ if ($lastCandidate == 0) {
+ push(@text, "*** ERROR *** cvsps failed - lastCandidate was 0");
+ } else {
+ $cmd="/usr/local/bin/cvsps -q -g -s $lastCandidate";
+ print LOG "\nRunning: $cmd\n\n";
+ open CVSPS, "$cmd 2>&1 |" ||
+ print LOG "cvsps failed\n" && die("cvsps failed");
+ $lineCount = 0;
+ $firstLine = 'No comment';
+ while (<CVSPS>) {
+ print LOG "$_";
+ chomp;
+ if ($lineCount < 10 && /^-+$/) {
+ } else {
+ push (@text, "$_");
+ }
+ if (/^Log:$/) {
+ $inLog = 1;
+ } elsif ($inLog && /^Members:$/) {
+ $inLog = 0;
+ } elsif ($inLog && $firstLine eq 'No comment' ) {
+ print LOG "Scanning ^^^\n";
+ if (/^\s*$/) {
+ # skip blank lines
+ } elsif ( /20\d\d/ ) {
+ # skip lines with years in them (ChangeLog entries)
+ } else {
+ s/^\s*\*?\s*(\S.*\S)\s*$/\1/;
+ s/^(.{80}).*$/\1/;
+ $firstLine = $_;
+ chomp $firstLine;
+ print LOG "Found firstLine: $firstLine\n";
+ $inLog = 0;
+ }
+ }
+ $lineCount++;
+ if ($lineCount > 1000) {
+ push (@text, "");
+ push (@text, "*** Patch too long, truncated ***");
+ last;
+ }
+ }
+ close CVSPS || print LOG "cvsps failed\n";
+ }
+
+ open SENDMAIL, "| /usr/sbin/sendmail -f cvs-commits\@kaffe.org $resendTo" ||
+ print LOG "sendmail failed\n" && die("sendmail failed");
+
+ print SENDMAIL "From: Kaffe CVS <cvs-commits\@kaffe.org>\n";
+ print SENDMAIL "To: $resendTo\n";
+ print SENDMAIL "Reply-To: Kaffe Mailing List <kaffe\@kaffe.org>\n";
+ print SENDMAIL "Subject: CVS $module ($user): $firstLine\n\n";
+
+ for $t (@text) {
+ print SENDMAIL "$t\n";
+ }
+
+ close SENDMAIL ||
+ print LOG "sendmail failed\n" && die("sendmail failed");
+
+}
+
+print LOG "\nDone. " . `date` . "\n";
+close LOG;
+
===================================================================
Checking out kaffe-project-services/loginfo-cvsps/loginfo
RCS: /home/cvs/kaffe/kaffe-project-services/loginfo-cvsps/loginfo,v
VERS: 1.1
***************
--- /dev/null Sun Aug 4 19:57:58 2002
+++ kaffe-project-services/loginfo-cvsps/loginfo Wed Jan 14 17:15:05 2004
@@ -0,0 +1,21 @@
+# The "loginfo" file is used to control where "cvs commit" log information is
+# sent. The first entry on a line is a regular expression which is tested
+# against the directory that the change is being made to, relative to the
+# $CVSROOT. For the first match that is found, the remainder of the line is a
+# filter program that should expect log information on its standard input
+#
+# If the repository name does not match any of the regular expressions in the
+# first field of this file, the "DEFAULT" line is used, if it is specified.
+#
+# If the name "ALL" appears as a regular expression it is always used
+# in addition to the first matching regex or "DEFAULT".
+#
+# The filter program may use one and only one "%s" modifier (ala printf). If
+# such a "%s" is specified in the filter program, a brief title is included
+# (as one argument, enclosed in single quotes) showing the relative directory
+# name and listing the modified file names.
+#
+# For example:
+#DEFAULT (echo ""; who am i; echo %s; date; cat) >> $CVSROOT/CVSROOT/commitlog
+^testing$ /cvs/kaffe/CVSROOT/martin-log.pl -s -m resend at kaffe.org -m2 test at kaffe.org -f /cvs/kaffe/CVSROOT/commits.log %s
+^testing/ /cvs/kaffe/CVSROOT/martin-log.pl -s -m resend at kaffe.org -m2 test at kaffe.org -f /cvs/kaffe/CVSROOT/commits.log %s
===================================================================
Checking out kaffe-project-services/loginfo-cvsps/martin-log.pl
RCS: /home/cvs/kaffe/kaffe-project-services/loginfo-cvsps/martin-log.pl,v
VERS: 1.1
***************
--- /dev/null Sun Aug 4 19:57:58 2002
+++ kaffe-project-services/loginfo-cvsps/martin-log.pl Wed Jan 14 17:15:05 2004
@@ -0,0 +1,757 @@
+#!/usr/bin/perl
+# -*-Perl-*-
+##
+#
+# This script, taken from the OpenBSD CVS repository.
+#
+# Perl filter to handle the log messages from the checkin of files in
+# a directory. This script will group the lists of files by log
+# message, and mail a single consolidated log message at the end of
+# the commit.
+#
+# This file assumes a pre-commit checking program that leaves the
+# names of the first and last commit directories in a temporary file.
+#
+# Contributed by David Hampton <hampton at cisco.com>
+#
+# hacked greatly by Greg A. Woods <woods at web.net>
+
+# Usage: log_accum.pl [-d] [-s] [-M module] [[-m mailto] ...] [-f logfile]
+# -d - turn on debugging
+# -m mailto - send mail to "mailto" (multiple)
+# -m2 mailto - resend mail to "mailto" (multiple)
+# -M modulename - set module name to "modulename"
+# -f logfile - write commit messages to logfile too
+# -s - *don't* run "cvs status -v" for each file
+
+#
+# Configurable options
+#
+
+
+$hostname = `hostname -f`;
+if (! $HOSTNAME eq 'pogo.kaffe.org') { die "Script $0 not run on pogo.kaffe.org!"; }
+
+
+$MAILER = "/usr/sbin/sendmail"; # something with UCB sendmail syntax
+$MAILFROM = "Kaffe CVS <cvs-commits\@kaffe.org>"; # mail comes from
+$MAILREPLYTO = "kaffe\@kaffe.org"; # redirect replies to
+
+# Constants (don't change these!)
+#
+$STATE_NONE = 0;
+$STATE_CHANGED = 1;
+$STATE_ADDED = 2;
+$STATE_REMOVED = 3;
+$STATE_LOG = 4;
+
+$ID = getppid();
+
+$LAST_FILE = "/tmp/#cvs.lastdir.$ID";
+$FILE_PREFIX = "#cvs.files.$ID";
+
+$CHANGED_FILE = "/tmp/$FILE_PREFIX.changed";
+$ADDED_FILE = "/tmp/$FILE_PREFIX.added";
+$REMOVED_FILE = "/tmp/$FILE_PREFIX.removed";
+$MODULES_FILE = "/tmp/$FILE_PREFIX.modules";
+$LOG_FILE = "/tmp/$FILE_PREFIX.log";
+
+$CVS_SILENT = 0;
+
+#
+# Subroutines
+#
+
+sub cleanup_tmpfiles {
+ local($wd, @files);
+
+ $wd = `pwd`;
+ chdir("/tmp") || die("Can't chdir('/tmp')\n");
+ opendir(DIR, ".");
+ push(@files, grep(/^$FILE_PREFIX\..*$/, readdir(DIR)));
+ closedir(DIR);
+ foreach (@files) {
+ unlink $_;
+ }
+ unlink $LAST_FILE;
+
+ chdir($wd);
+}
+
+sub write_logfile {
+ local($filename, @lines) = @_;
+
+ open(FILE, ">$filename") || die("Cannot open log file $filename.\n");
+ print FILE join("\n", @lines), "\n";
+ close(FILE);
+}
+
+sub format_names {
+ local($dir, @files) = @_;
+ local(@lines);
+
+ if ($dir =~ /^\.\//) {
+ $dir = $';
+ }
+ if ($dir =~ /\/$/) {
+ $dir = $`;
+ }
+ if ($dir eq "") {
+ $dir = ".";
+ }
+
+ $format = "\t%-" . sprintf("%d", length($dir) > 15 ? length($dir) : 15) . "s%s ";
+
+ $lines[0] = sprintf($format, $dir, ":");
+
+ if ($debug) {
+ print STDERR "format_names(): dir = ", $dir, "; files = ", join(":", @files), ".\n";
+ }
+ foreach $file (@files) {
+ if (length($lines[$#lines]) + length($file) > 65) {
+ $lines[++$#lines] = sprintf($format, " ", " ");
+ }
+ $lines[$#lines] .= $file . " ";
+ }
+
+ @lines;
+}
+
+sub format_lists {
+ local(@lines) = @_;
+ local(@text, @files, $lastdir);
+
+ if ($debug) {
+ print STDERR "format_lists(): ", join(":", @lines), "\n";
+ }
+ @text = ();
+ @files = ();
+ $lastdir = shift @lines; # first thing is always a directory
+ if ($lastdir !~ /.*\/$/) {
+ die("Damn, $lastdir doesn't look like a directory!\n");
+ }
+ foreach $line (@lines) {
+ if ($line =~ /.*\/$/) {
+ push(@text, &format_names($lastdir, @files));
+ $lastdir = $line;
+ @files = ();
+ } else {
+ push(@files, $line);
+ }
+ }
+ push(@text, &format_names($lastdir, @files));
+
+ @text;
+}
+
+sub get_lines_for_module {
+ local($module, @lines) = @_;
+ local(@text, @files, $lastdir, $lastmodule);
+
+ return if $#lines == -1;
+
+ if ($debug) {
+ print STDERR "get_lines_for_module($module): ", join(":", @lines), "\n";
+ }
+ @text = ();
+ @files = ();
+ $lastdir = shift @lines; # first thing is always a directory
+ if ($lastdir !~ /^(.*?)\/(.*)\/$/) {
+ die("Damn, $lastdir doesn't look like a directory!\n");
+ }
+ $lastmodule = $1; $lastdir = $2;
+ foreach $line (@lines) {
+ if ($line =~ /.*\/$/) {
+ if ($lastmodule eq $module) {
+ push(@text, &format_names($lastdir, @files));
+ }
+ $lastdir = $line;
+ if ($lastdir !~ /^(.*?)\/(.*)\/$/) {
+ die("Damn, $lastdir doesn't look like a directory!\n");
+ }
+ $lastmodule = $1; $lastdir = $2;
+ @files = ();
+ } else {
+ push(@files, $line);
+ }
+ }
+ if ($lastmodule eq $module) {
+ push(@text, &format_names($lastdir, @files));
+ }
+
+ @text;
+}
+
+sub get_files_for_module {
+ local($module, @lines) = @_;
+ local(@text, @files, $lastdir, $lastmodule);
+
+ return if $#lines == -1;
+
+ if ($debug) {
+ print STDERR "get_lines_for_module($module): ", join(":", @lines), "\n";
+ }
+ @text = ();
+ @files = ();
+ $lastdir = shift @lines; # first thing is always a directory
+ if ($lastdir !~ /^(.*?)\/(.*)\/$/) {
+ die("Damn, $lastdir doesn't look like a directory!\n");
+ }
+ $lastmodule = $1; $lastdir = $2;
+ foreach $line (@lines) {
+ if ($line =~ /.*\/$/) {
+ if ($lastmodule eq $module) {
+ push(@text, @files);
+ }
+ $lastdir = $line;
+ if ($lastdir !~ /^(.*?)\/(.*)\/$/) {
+ die("Damn, $lastdir doesn't look like a directory!\n");
+ }
+ $lastmodule = $1; $lastdir = $2;
+ @files = ();
+ } else {
+ push(@files, $lastdir . "/" . $line);
+ }
+ }
+ if ($lastmodule eq $module) {
+ push(@text, @files);
+ }
+
+ @text;
+}
+
+sub check_cvssilent {
+ local(@files) = @_;
+
+ local (@regexps, $regexp, $file);
+
+ open(FH, $cvsroot . "/CVSROOT/cvssilent");
+ while(<FH>) {
+ chomp;
+ push @regexps, $_;
+ }
+ close(FH);
+
+ #
+ # If there's any file which does not match any of
+ # the regexps, then the commit is not silent.
+ #
+ foreach $file (@files) {
+ local ($silent) = 0;
+
+ foreach $regexp (@regexps) {
+ $silent = 1 if $file =~ $regexp;
+ }
+
+ return 0 unless $silent;
+ }
+
+ return 1;
+}
+
+sub append_names_to_file {
+ local($filename, $dir, @files) = @_;
+
+ if (@files) {
+ open(FILE, ">>$filename") || die("Cannot open file $filename.\n");
+ print FILE $dir, "\n";
+ print FILE join("\n", @files), "\n";
+ close(FILE);
+ }
+}
+
+sub append_modules_file {
+ local($filename, $modulename) = @_;
+
+ open(FILE, ">>$filename") || die("Cannot open file $filename.\n");
+ print FILE $modulename, "\n";
+ close(FILE);
+}
+
+sub read_line {
+ local($line);
+ local($filename) = @_;
+
+ open(FILE, "<$filename") || die("Cannot open file $filename.\n");
+ $line = <FILE>;
+ close(FILE);
+ chop($line);
+ $line;
+}
+
+sub read_logfile {
+ local(@text);
+ local($filename, $leader) = @_;
+
+ open(FILE, "<$filename");
+ while (<FILE>) {
+ chop;
+ push(@text, $leader.$_);
+ }
+ close(FILE);
+ if ($debug) {
+ print STDERR "Read logfile $filename: (".join(":", at text).")\n";
+ }
+ @text;
+}
+
+sub build_header {
+ local($module) = @_;
+ local($header);
+ local($sec,$min,$hour,$mday,$mon,$year) = localtime($^T);
+ $header = sprintf("Resend-To:\t%s\n", $resendmailto);
+ $header .= sprintf("CVSROOT:\t%s\nModule name:\t%s\n",
+ $cvsroot,
+ $module);
+ if (defined($branch)) {
+ $header .= sprintf("Branch: \t%s\n",
+ $branch);
+ }
+ $header .= sprintf("Changes by:\t%s\t%02d/%02d/%02d %02d:%02d:%02d",
+ $login,
+ $year%100, $mon+1, $mday,
+ $hour, $min, $sec);
+}
+
+sub mail_notification {
+ local($module, $name, @text) = @_;
+
+ $extra_headers = "";
+ if ($CVS_SILENT) {
+ $extra_headers .= "X-CVS-Silent: yes\n";
+ $subject = "Kaffe CVS (silent): $module $login";
+ } else {
+ $subject = "Kaffe CVS: $module $login";
+ }
+
+ $extra_headers .= "X-CVS-Module: $module\n";
+ $extra_headers .= "\n";
+
+ open(MAIL, "| $MAILER -t -f \"$MAILFROM\" ");
+ print MAIL <<EOF ;
+From: $MAILFROM
+To: $name
+Reply-To: $MAILREPLYTO
+Bcc: kfsnap\@kaffe\.org
+Subject: $subject
+$extra_headers
+EOF
+ print MAIL join("\n", @text), "\n";
+ close(MAIL);
+}
+
+sub write_commitlog {
+ local($logfile, @text) = @_;
+
+ open(FILE, ">>$logfile");
+ print FILE join("\n", @text), "\n\n";
+ close(FILE);
+}
+
+
+sub compose_url {
+ my ($before_sec,$before_min,$before_hour,$before_mday,$before_mon,$before_year) = localtime($^T - 60);
+ my ($after_sec,$after_min,$after_hour,$after_mday,$after_mon,$after_year) = localtime($^T + 60);
+
+ my $url = "http://cvs.kaffe.org/bonsai/cvsquery.cgi?module=";
+ $url .= $modulename;
+ $url .= "&branch=";
+
+ if (defined($branch)) {
+ $url .= $branch;
+ } else {
+ $url .= "HEAD";
+ }
+
+ $url .= "&branchtype=match&dir=";
+ $url .= $modulename;
+ $url .= "&file=&filetype=match&who=";
+ $url .= $login;
+ $url .= "&whotype=match&sortby=Date&hours=&date=explicit&mindate=";
+
+ $url .= sprintf("%02d%%2F%02d%%2F%02d+", $before_mon+1, $before_mday, $before_year%100);
+ $url .= sprintf("%02d%%3A%02d", $before_hour, $before_min);
+
+ $url .= "&maxdate=";
+
+ $url .= sprintf("%02d%%2F%02d%%2F%02d+", $after_mon+1, $after_mday, $after_year%100);
+ $url .= sprintf("%02d%%3A%02d", $after_hour, $after_min);
+
+ $url.= "&cvsroot=%2Fcvs%2Fgnome";
+
+ return $url;
+}
+
+#
+# Main Body
+#
+
+# Initialize basic variables
+#
+$debug = 0;
+$state = $STATE_NONE;
+
+$login = $ENV{'CVS_USERNAME'} || $ENV{'CVS_USER'} || getlogin || (getpwuid($<))[0] || "nobody";
+
+chop($hostname = `hostname`);
+if ($hostname !~ /\./) {
+ chop($domainname = `domainname`);
+ $hostdomain = $hostname . "." . $domainname;
+} else {
+ $hostdomain = $hostname;
+}
+$cvsroot = $ENV{'CVSROOT'};
+$do_status = 1;
+$modulename = "";
+
+# parse command line arguments (file list is seen as one arg)
+#
+while (@ARGV) {
+ $arg = shift @ARGV;
+
+ if ($arg eq '-d') {
+ $debug = 1;
+ print STDERR "Debug turned on...\n";
+ } elsif ($arg eq '-m') {
+ $mailto = "$mailto " . shift @ARGV;
+ } elsif ($arg eq '-m2') {
+ $resendmailto = "$resendmailto " . shift @ARGV;
+ } elsif ($arg eq '-M') {
+ $modulename = shift @ARGV;
+ } elsif ($arg eq '-s') {
+ $do_status = 0;
+ } elsif ($arg eq '-f') {
+ ($commitlog) && die("Too many '-f' args\n");
+ $commitlog = shift @ARGV;
+ $commitlog_arg = $commitlog;
+ } else {
+ ($donefiles) && die("Too many arguments! Check usage.\n");
+ $donefiles = 1;
+ @files = split(/ /, $arg);
+ }
+}
+
+($mailto) || die("No -m mail recipient specified\n");
+
+# for now, the first "file" is the repository directory being committed,
+# relative to the $CVSROOT location
+#
+ at path = split('/', $files[0]);
+
+# XXX there are some ugly assumptions in here about module names and
+# XXX directories relative to the $CVSROOT location -- really should
+# XXX read $CVSROOT/CVSROOT/modules, but that's not so easy to do, since
+# XXX we have to parse it backwards.
+#
+if ($modulename eq "") {
+ $modulename = $path[0]; # I.e. the module name == top-level dir
+}
+open(FH, "/cvs/kaffe/CVSROOT/modules.silent");
+while(<FH>) {
+ chomp;
+ if($modulename eq $_) {
+ exit 0;
+ }
+}
+close(FH);
+if ($commitlog ne "") {
+ $commitlog = $cvsroot . "/" . $modulename . "/" . $commitlog unless ($commitlog =~ /^\//);
+}
+if ($#path == 0) {
+ $dir = ".";
+} else {
+ $dir = join('/', @path[1..$#path]);
+}
+$dir = $modulename . "/" . $dir . "/";
+
+push (@modules, $modulename);
+
+if ($debug) {
+ print STDERR "module - ", $modulename, "\n";
+ print STDERR "dir - ", $dir, "\n";
+ print STDERR "path - ", join(":", @path), "\n";
+ print STDERR "files - ", join(":", @files), "\n";
+ print STDERR "id - ", $ID, "\n";
+ print STDERR "login - ", $login, "\n";
+ print STDERR "CVS_USERNAME - ", $ENV{'CVS_USERNAME'}, "\n";
+}
+
+# Check for a new directory first. This appears with files set as follows:
+#
+# files[0] - "path/name/newdir"
+# files[1] - "-"
+# files[2] - "New"
+# files[3] - "directory"
+#
+if ($files[2] =~ /New/ && $files[3] =~ /directory/) {
+ local(@text);
+
+ @text = ();
+ push(@text, &build_header($modulename));
+ push(@text, "");
+ push(@text, $files[0]);
+ push(@text, "");
+
+ while (<STDIN>) {
+ chop; # Drop the newline
+ push(@text, $_);
+ }
+
+ &mail_notification($modulename, $mailto, @text);
+
+ if ($commitlog) {
+ &write_commitlog($commitlog, @text);
+ }
+
+ exit 0;
+}
+
+# Iterate over the body of the message collecting information.
+#
+while (<STDIN>) {
+ chop; # Drop the newline
+
+ if (/^Modified Files/) { $state = $STATE_CHANGED; next; }
+ if (/^Added Files/) { $state = $STATE_ADDED; next; }
+ if (/^Removed Files/) { $state = $STATE_REMOVED; next; }
+ if (/^Log Message/) { $state = $STATE_LOG; next; }
+ if (/^Revision\/Branch/) { /^[^:]+:\s*(.*)/; $branch = $+; next; }
+# if (/Tag/) { /:.*: ([^ ]*)/; $branch = $1; next; }
+
+ s/^[ \t\n]+//; # delete leading whitespace
+ s/[ \t\n]+$//; # delete trailing whitespace
+
+ if ($state == $STATE_CHANGED) { push(@changed_files, split); }
+ if ($state == $STATE_ADDED) { push(@added_files, split); }
+ if ($state == $STATE_REMOVED) { push(@removed_files, split); }
+ if ($state == $STATE_LOG) { push(@log_lines, $_); }
+}
+
+# Strip leading and trailing blank lines from the log message. Also
+# compress multiple blank lines in the body of the message down to a
+# single blank line.
+#
+while ($#log_lines > -1) {
+ last if ($log_lines[0] ne "");
+ shift(@log_lines);
+}
+while ($#log_lines > -1) {
+ last if ($log_lines[$#log_lines] ne "");
+ pop(@log_lines);
+}
+for ($i = $#log_lines; $i > 0; $i--) {
+ if (($log_lines[$i - 1] eq "") && ($log_lines[$i] eq "")) {
+ splice(@log_lines, $i, 1);
+ }
+}
+
+# Check for an import command. This appears with files set as follows:
+#
+# files[0] - "path/name"
+# files[1] - "-"
+# files[2] - "Imported"
+# files[3] - "sources"
+#
+if ($files[2] =~ /Imported/ && $files[3] =~ /sources/) {
+ local(@text);
+
+ @text = ();
+ push(@text, &build_header($modulename));
+ push(@text, "");
+
+ push(@text, "Log message:");
+ while ($#log_lines > -1) {
+ push (@text, " " . $log_lines[0]);
+ shift(@log_lines);
+ }
+
+ &mail_notification($modulename, $mailto, @text);
+
+ if ($commitlog) {
+ &write_commitlog($commitlog, @text);
+ }
+
+ exit 0;
+}
+
+if ($debug) {
+ print STDERR "Searching for log file index...";
+}
+# Find an index to a log file that matches this log message
+#
+for ($i = 0; ; $i++) {
+ local(@text);
+
+ last if (! -e "$LOG_FILE.$i"); # the next available one
+ @text = &read_logfile("$LOG_FILE.$i", "");
+ last if ($#text == -1); # nothing in this file, use it
+ last if (join(" ", @log_lines) eq join(" ", @text)); # it's the same log message as another
+}
+if ($debug) {
+ print STDERR " found log file at $i, now writing tmp files.\n";
+}
+
+# Spit out the information gathered in this pass.
+#
+&append_names_to_file("$CHANGED_FILE.$i", $dir, @changed_files);
+&append_names_to_file("$ADDED_FILE.$i", $dir, @added_files);
+&append_names_to_file("$REMOVED_FILE.$i", $dir, @removed_files);
+&append_modules_file("$MODULES_FILE.$i", $modulename);
+&write_logfile("$LOG_FILE.$i", @log_lines);
+
+# Check whether this is the last directory. If not, quit.
+#
+if ($debug) {
+ print STDERR "Checking current dir against last dir.\n";
+}
+$_ = &read_line("$LAST_FILE");
+
+if ($_ ne $cvsroot . "/" . $files[0]) {
+ if ($debug) {
+ print STDERR sprintf("Current directory %s is not last directory %s.\n", $cvsroot . "/" .$files[0], $_);
+ }
+ exit 0;
+}
+if ($debug) {
+ print STDERR sprintf("Current directory %s is last directory %s -- all commits done.\n", $files[0], $_);
+}
+
+#
+# End Of Commits!
+#
+
+# This is it. The commits are all finished. Lump everything together
*** Patch too long, truncated ***
More information about the kaffe-siteadmin
mailing list