[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