head 1.11; access; symbols libdrm-1_0_4:1.11 trunk-20021125:1.8 mesa-4-1-branch:1.8.0.2 mesa-3-5-branch:1.7.0.2; locks; strict; comment @# @; 1.11 date 2005.08.21.22.29.33; author ajax; state Exp; branches; next 1.10; commitid 32b430900354567; 1.10 date 2004.07.25.21.24.58; author anholt; state Exp; branches; next 1.9; 1.9 date 2003.09.16.19.06.28; author anholt; state Exp; branches; next 1.8; 1.8 date 2001.02.15.18.37.27; author dawes; state Exp; branches; next 1.7; 1.7 date 2000.12.28.13.13.40; author faith; state Exp; branches; next 1.6; 1.6 date 2000.12.28.12.53.48; author faith; state Exp; branches; next 1.5; 1.5 date 2000.12.28.12.44.57; author faith; state Exp; branches; next 1.4; 1.4 date 2000.12.28.11.06.59; author faith; state Exp; branches; next 1.3; 1.3 date 2000.11.07.01.24.20; author dawes; state Exp; branches; next 1.2; 1.2 date 2000.11.03.03.35.29; author dawes; state Exp; branches; next 1.1; 1.1 date 2000.11.01.21.31.06; author dawes; state Exp; branches; next ; desc @@ 1.11 log @Update to cope with changes to the 'cvs log' output format. @ text @#! /usr/bin/perl # -*-Perl-*- # # 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 # # hacked greatly by Greg A. Woods # Usage: log_accum.pl [-d] [-s] [-M module] [[-m mailto] ...] [[-R replyto] ...] [-f logfile] # -d - turn on debugging # -m mailto - send mail to "mailto" (multiple) # -R replyto - set the "Reply-To:" to "replyto" (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 # -w - show working directory with log message # -r - put rcsids and delta info in mail message # -F fromdomain - domain to use in email From: line. # -h - turn on X-CVS header lines in mail message # # Configurable options # $MAILER = "/usr/sbin/sendmail"; # # End user configurable options. # # Constants (don't change these!) # $STATE_NONE = 0; $STATE_CHANGED = 1; $STATE_ADDED = 2; $STATE_REMOVED = 3; $STATE_LOG = 4; $LAST_FILE = "/tmp/#cvs.lastdir"; $CHANGED_FILE = "/tmp/#cvs.files.changed"; $ADDED_FILE = "/tmp/#cvs.files.added"; $REMOVED_FILE = "/tmp/#cvs.files.removed"; $LOG_FILE = "/tmp/#cvs.files.log"; $BRANCH_FILE = "/tmp/#cvs.files.branch"; $SUMMARY_FILE = "/tmp/#cvs.files.summary"; $FILE_PREFIX = "#cvs.files"; # # Subroutines # sub cleanup_tmpfiles { local($wd, @@files); $wd = `pwd`; chdir("/tmp") || die("Can't chdir('/tmp')\n"); opendir(DIR, "."); push(@@files, grep(/^$FILE_PREFIX\..*\.$id$/, readdir(DIR))); closedir(DIR); foreach (@@files) { unlink $_; } unlink $LAST_FILE . "." . $id; 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 append_to_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, $tag, @@files) = @@_; local(@@lines, $tagtext, $indent1, $indent2); if ($tag ne "") { $tagtext = "\tTag: $tag" } else { $tagtext = ""; } $indent1 = " "; $indent2 = " "; $lines[0] = "$indent1$dir:$tagtext"; if ($debug) { print STDERR "format_names(): dir = ", $dir, "; files = ", join(":", @@files), ".\n"; } $lines[++$#lines] = "$indent1$indent2"; foreach $file (@@files) { if (length($lines[$#lines]) + length($file) > 65) { $lines[++$#lines] = "$indent1$indent2"; } $lines[$#lines] .= $file . " "; } @@lines; } sub format_lists { local(@@lines) = @@_; local(@@text, @@files, $lastdir, $tag, $gettag); if ($debug) { print STDERR "format_lists(): ", join(":", @@lines), "\n"; } @@text = (); @@files = (); $tag = ""; $gettag = 0; $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 eq "Tag:") { $gettag = 1; next; } elsif ($gettag) { $tag = $line; $gettag = 0; } elsif ($line =~ /.*\/$/) { push(@@text, &format_names($lastdir, $tag, @@files)); $lastdir = $line; $tag = ""; @@files = (); } else { push(@@files, $line); } } push(@@text, &format_names($lastdir, $tag, @@files)); @@text; } 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 read_line { local($line); local($filename) = @@_; open(FILE, "<$filename") || die("Cannot open file $filename.\n"); $line = ; close(FILE); chop($line); $line; } sub append_line { local($filename, $line) = @@_; open(FILE, ">>$filename") || die("Cannot open file $filename.\n"); print(FILE $line, "\n"); close(FILE); } sub read_logfile { local(@@text); local($filename, $leader) = @@_; open(FILE, "<$filename"); while () { chop; push(@@text, $leader.$_); } close(FILE); @@text; } sub find_branches { local(@@lines) = @@_; $tag = ""; $hastag = 0; $gettag = 0; $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 eq "Tag:") { $hastag = 1; $gettag = 1; next; } elsif ($gettag) { $tag = $line; $gettag = 0; } } if ($hastag) { $taglist{$tag} = $tag; } else { $taglist{"trunk"} = "trunk"; } } # # do an 'cvs -Qn status' on each file in the arguments, and extract info. # sub change_summary { local($out, @@filenames) = @@_; local(@@revline); local($file, $rev, $rcsfile, $line); while (@@filenames) { $file = shift @@filenames; if ("$file" eq "") { next; } if ("$file" eq "Tag:") { shift @@filenames; next; } open(RCS, "-|") || exec 'cvs', '-Qn', 'status', $file; $rev = ""; $delta = ""; $rcsfile = ""; while () { if (/^[ \t]*Repository revision/) { chop; @@revline = split(' ', $_); $rev = $revline[2]; $rcsfile = $revline[3]; $rcsfile =~ s,^$cvsroot/,,; $rcsfile =~ s/,v$//; } } close(RCS); if ($rev ne '' && $rcsfile ne '') { open(RCS, "-|") || exec 'cvs', '-Qn', 'log', "-r$rev", $file; while () { if (/^date:/) { chop; $delta = $_; $delta =~ s/^.*lines://; $delta =~ s/;.*$//; } } close(RCS); } &append_line($out, sprintf("%-13s%-12s%s", $rev, $delta, $rcsfile)); } } sub build_header { local($header); delete $ENV{'TZ'}; local($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); $header = sprintf("CVSROOT:\t%s\nModule name:\t%s\nRepository:\t%s\nChanges by:\t%s@@%s\t%02d/%02d/%02d %02d:%02d:%02d", $cvsroot, $modulename, $dir, $login, $hostdomain, $year%100, $mon+1, $mday, $hour, $min, $sec); } sub mail_notification { local(@@text) = @@_; local($fromrealname, $tag, $tagprinted); print "Mailing the commit message to $mailto...\n"; $tagprinted = 0; $fromrealname = (getpwuid($<))[6]; open(MAIL, "| $MAILER $mailto"); print MAIL "From: $fromrealname <$login\@@$fromdomain>\n"; print MAIL "To: " . $mailto . "\n"; if ($replyto ne '') { print MAIL "Reply-To: " . $replyto . "\n"; } print MAIL "Subject: CVS Update: " . $modulename . " (branch: "; foreach $tag (sort keys %taglist) { if ($tagprinted) { print MAIL ", "; } print MAIL $tag; $tagprinted = 1; } print MAIL ")\n"; if ($longmailheader) { print MAIL "X-CVS-Notice: This email was automatically generated by a CVS checkin\n"; if ($replyto ne '') { print MAIL "X-CVS-Problems: Send problems to $replyto\n"; } print MAIL "X-CVS-Version: $cvsvers\n"; print MAIL "X-CVS-Host: $hostname running $osname\n"; } print MAIL "\n"; print MAIL join("\n", @@text), "\n"; close(MAIL); } sub write_commitlog { local($logfile, @@text) = @@_; open(FILE, ">>$logfile"); print FILE join("\n", @@text), "\n"; close(FILE); } # # Main Body # # Initialize basic variables # $debug = 0; $id = getpgrp(); # note, you *must* use a shell which does setpgrp() $state = $STATE_NONE; $login = getlogin || (getpwuid($<))[0] || "nobody"; chop($hostname = `hostname`); chop($domainname = `domainname`); if ($domainname !~ '^\..*') { $domainname = '.' . $domainname; } $hostdomain = $hostname . $domainname; $fromdomain = "$hostdomain"; chop($osname = `uname -sr`); chop($cvsvers = `cvs -v | fgrep client`); $cvsroot = $ENV{'CVSROOT'}; $do_status = 1; # moderately useful $show_wd = 0; # useless in client/server $modulename = ""; $rcsidinfo = 0; $longmailheader = 0; # 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') { if ($mailto eq '') { $mailto = shift @@ARGV; } else { $mailto = $mailto . ", " . shift @@ARGV; } } elsif ($arg eq '-R') { if ($replyto eq '') { $replyto = shift @@ARGV; } else { $replyto = $replyto . ", " . shift @@ARGV; } } elsif ($arg eq '-M') { $modulename = shift @@ARGV; } elsif ($arg eq '-F') { $fromdomain = shift @@ARGV; } elsif ($arg eq '-s') { $do_status = 0; } elsif ($arg eq '-w') { $show_wd = 1; } elsif ($arg eq '-f') { ($commitlog) && die("Too many '-f' args\n"); $commitlog = shift @@ARGV; } elsif ($arg eq '-r') { $rcsidinfo = 1; } elsif ($arg eq '-h') { $longmailheader = 1; } else { ($donefiles) && die("Too many arguments! Check usage.\n"); $donefiles = 1; @@files = split(/ /, $arg); } } ($mailto) || die("No mail recipient specified (use -m)\n"); #if ($replyto eq '') { # $replyto = $login; #} # for now, the first "file" is the repository directory being committed, # relative to the $CVSROOT location # @@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. # XXX # XXX Fortunately it's relatively easy for the user to specify the # XXX module name as appropriate with a '-M' via the directory # XXX matching in loginfo. # if ($modulename eq "") { $modulename = $path[0]; # I.e. the module name == top-level dir } if ($#path == 0) { $dir = "."; } else { $dir = join('/', @@path); } $dir = $dir . "/"; 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"; } # 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()); push(@@text, ""); push(@@text, $files[0]); push(@@text, ""); while () { chop; # Drop the newline push(@@text, $_); } &mail_notification($mailto, @@text); exit 0; } # 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()); push(@@text, ""); push(@@text, $files[0]); push(@@text, ""); while () { chop; # Drop the newline push(@@text, $_); } &mail_notification(@@text); exit 0; } # Iterate over the body of the message collecting information. # while () { chop; # Drop the newline if (/^Revision\/Branch:/) { s,^Revision/Branch:,,; push (@@branch_lines, split); next; } if (/^In directory/) { if ($show_wd) { # useless in client/server mode push(@@log_lines, $_); push(@@log_lines, ""); } next; } 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 ($state != $STATE_LOG) { 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); } } 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.$id"); # the next available one @@text = &read_logfile("$LOG_FILE.$i.$id", ""); 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.$id, now writing tmp files.\n"; } # Spit out the information gathered in this pass. # &append_names_to_file("$CHANGED_FILE.$i.$id", $dir, @@changed_files); &append_names_to_file("$ADDED_FILE.$i.$id", $dir, @@added_files); &append_names_to_file("$REMOVED_FILE.$i.$id", $dir, @@removed_files); &append_names_to_file("$BRANCH_FILE.$i.$id", $dir, @@branch_lines); &write_logfile("$LOG_FILE.$i.$id", @@log_lines); if ($rcsidinfo) { &change_summary("$SUMMARY_FILE.$i.$id", @@changed_files); } # 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.$id"); 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 # into a single message, fire a copy off to the mailing list, and drop # it on the end of the Changes file. # # # Produce the final compilation of the log messages # @@text = (); @@status_txt = (); push(@@text, &build_header()); push(@@text, ""); for ($i = 0; ; $i++) { last if (! -e "$LOG_FILE.$i.$id"); # we're done them all! @@lines = &read_logfile("$LOG_FILE.$i.$id", " "); if ($#lines >= 0) { push(@@text, "Log message:"); push(@@text, @@lines); push(@@text, ""); } @@lines = &read_logfile("BRANCH_FILE.$i.$id", ""); if ($#lines >= 0) { push (@@text, "Branch:"); push(@@text, &format_lists(@@lines)); } @@lines = &read_logfile("$CHANGED_FILE.$i.$id", ""); if ($#lines >= 0) { push(@@text, "Modified files:"); push(@@text, &format_lists(@@lines)); &find_branches(@@lines); } @@lines = &read_logfile("$ADDED_FILE.$i.$id", ""); if ($#lines >= 0) { push(@@text, "Added files:"); push(@@text, &format_lists(@@lines)); &find_branches(@@lines); } @@lines = &read_logfile("$REMOVED_FILE.$i.$id", ""); if ($#lines >= 0) { push(@@text, "Removed files:"); push(@@text, &format_lists(@@lines)); &find_branches(@@lines); } if ($rcsidinfo) { if (-e "$SUMMARY_FILE.$i.$id") { @@lines = &read_logfile("$SUMMARY_FILE.$i.$id", " "); if ($#lines >= 0) { push(@@text, " "); push(@@text, " Revision Changes Path"); push(@@text, @@lines); } } } if ($#text >= 0) { push(@@text, ""); } if ($do_status) { local(@@changed_files); @@changed_files = (); push(@@changed_files, &read_logfile("$CHANGED_FILE.$i.$id", "")); push(@@changed_files, &read_logfile("$ADDED_FILE.$i.$id", "")); push(@@changed_files, &read_logfile("$REMOVED_FILE.$i.$id", "")); if ($debug) { print STDERR "main: pre-sort changed_files = ", join(":", @@changed_files), ".\n"; } sort(@@changed_files); if ($debug) { print STDERR "main: post-sort changed_files = ", join(":", @@changed_files), ".\n"; } foreach $dofile (@@changed_files) { if ($dofile =~ /\/$/) { next; # ignore the silly "dir" entries } if ($debug) { print STDERR "main(): doing 'cvs -nQq status -v $dofile'\n"; } open(STATUS, "-|") || exec 'cvs', '-nQq', 'status', '-v', $dofile; while () { chop; push(@@status_txt, $_); } } } } # Write to the commitlog file # if ($commitlog) { &write_commitlog($commitlog, @@text); } if ($#status_txt >= 0) { push(@@text, @@status_txt); } # Mailout the notification. # &mail_notification(@@text); # cleanup # if (! $debug) { &cleanup_tmpfiles(); } exit 0; @ 1.10 log @Fix the mailer setting. @ text @d271 2 a272 2 $delta =~ s/^.*;//; $delta =~ s/^[\s]+lines://; @ 1.9 log @Set the mailer for freedesktop.org system. @ text @d33 1 a33 1 $MAILER = "/usr/sbin/exim4"; @ 1.8 log @Move the log message higher up in the commit message. @ text @d33 1 a33 1 $MAILER = "/usr/sbin/exim"; @ 1.7 log @Minor change for log testing @ text @d619 6 a658 6 push(@@text, ""); } @@lines = &read_logfile("$LOG_FILE.$i.$id", " "); if ($#lines >= 0) { push(@@text, "Log message:"); push(@@text, @@lines); @ 1.6 log @Minor change for log testing @ text @d33 1 a33 1 $MAILER = "/usr/sbin/exim -v"; d300 1 a300 1 print "Mailing the commit message from $hostname ($osname)...\n"; a305 1 print "From: $fromrealname <$login\@@$fromdomain>\n"; a306 1 print "To: " . $mailto . "\n"; @ 1.5 log @Try exim directly @ text @d33 1 a33 1 $MAILER = "/usr/sbin/exim -v -t"; d306 1 d308 1 @ 1.4 log @Make minor change to test logging. @ text @d33 1 a33 1 $MAILER = "/usr/sbin/sendmail"; @ 1.3 log @- Include the branch name in the Subject: line of the commit message. - Strip $CVSROOT out of the paths printed in the change summary information. @ text @d300 1 a300 1 print "Mailing the commit message...\n"; @ 1.2 log @Don't strip leading blanks from log messages, and indent them with two spaces rather than a tab. @ text @d199 27 d259 1 a259 1 $rcsfile =~ s,^$CVSROOT/,,; d298 3 a300 1 local($fromrealname); d302 1 d310 10 a319 1 print MAIL "Subject: CVS Update: " . $modulename . "\n"; d628 1 d634 1 d640 1 @ 1.1 log @update CVS commit log handling @ text @d487 3 a489 1 s/^[ \t\n]+//; # delete leading whitespace d613 1 a613 1 @@lines = &read_logfile("$LOG_FILE.$i.$id", "\t"); d672 1 @