diff options
Diffstat (limited to 'contrib/cvs/contrib/log_accum.in')
-rwxr-xr-x | contrib/cvs/contrib/log_accum.in | 956 |
1 files changed, 550 insertions, 406 deletions
diff --git a/contrib/cvs/contrib/log_accum.in b/contrib/cvs/contrib/log_accum.in index 8591784..f8d624c 100755 --- a/contrib/cvs/contrib/log_accum.in +++ b/contrib/cvs/contrib/log_accum.in @@ -9,419 +9,602 @@ # This file assumes a pre-commit checking program that leaves the # names of the first and last commit directories in a temporary file. # +# IMPORTANT: what the above means is, this script interacts with +# commit_prep, in that they have to agree on the tmpfile name to use. +# See $LAST_FILE below. +# +# How this works: CVS triggers this script once for each directory +# involved in the commit -- in other words, a single commit can invoke +# this script N times. It knows when it's on the last invocation by +# examining the contents of $LAST_FILE. Between invocations, it +# caches information for its future incarnations in various temporary +# files in /tmp, which are named according to the process group and +# the committer (by themselves, neither of these are unique, but +# together they almost always are, unless the same user is doing two +# commits simultaneously). The final invocation is the one that +# actually sends the mail -- it gathers up the cached information, +# combines that with what it found out on this pass, and sends a +# commit message to the appropriate mailing list. +# +# (Ask Karl Fogel <kfogel@collab.net> if questions.) +# # Contributed by David Hampton <hampton@cisco.com> +# Roy Fielding removed useless code and added log/mail of new files +# Ken Coar added special processing (i.e., no diffs) for binary files # -# hacked greatly by Greg A. Woods <woods@planix.com> - -# Usage: log_accum.pl [-d] [-s] [-w] [-M module] [-u user] [[-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 -# -u user - $USER passed from loginfo +############################################################ # -# Configurable options +# Configurable options # - -# set this to something that takes a whole message on stdin -$MAILER = "/usr/lib/sendmail -t"; - +############################################################ +# +# Where do you want the RCS ID and delta info? +# 0 = none, +# 1 = in mail only, +# 2 = in both mail and logs. # -# End user configurable options. +$rcsidinfo = 2; + +#if you are using CVS web then set this to some value... if not set it to "" # +# When set properly, this will cause links to aspects of the project to +# print in the commit emails. +#$CVSWEB_SCHEME = "http"; +#$CVSWEB_DOMAIN = "cvshome.org"; +#$CVSWEB_PORT = "80"; +#$CVSWEB_URI = "source/browse/"; +#$SEND_URL = "true"; +$SEND_DIFF = "true"; + + +# Set this to a domain to have CVS pretend that all users who make +# commits have mail accounts within that domain. +#$EMULATE_LOCAL_MAIL_USER="cvshome.org"; -# Constants (don't change these!) +# Set this to '-c' for context diffs; defaults to '-u' for unidiff format. +$difftype = '-uN'; + +############################################################ +# +# Constants # +############################################################ $STATE_NONE = 0; $STATE_CHANGED = 1; $STATE_ADDED = 2; $STATE_REMOVED = 3; $STATE_LOG = 4; -$LAST_FILE = "/tmp/#cvs.lastdir"; +$TMPDIR = $ENV{'TMPDIR'} || '/tmp'; +$FILE_PREFIX = '#cvs.'; -$CHANGED_FILE = "/tmp/#cvs.files.changed"; -$ADDED_FILE = "/tmp/#cvs.files.added"; -$REMOVED_FILE = "/tmp/#cvs.files.removed"; -$LOG_FILE = "/tmp/#cvs.files.log"; +$LAST_FILE = "$TMPDIR/${FILE_PREFIX}lastdir"; # Created by commit_prep! +$ADDED_FILE = "$TMPDIR/${FILE_PREFIX}files.added"; +$REMOVED_FILE = "$TMPDIR/${FILE_PREFIX}files.removed"; +$LOG_FILE = "$TMPDIR/${FILE_PREFIX}files.log"; +$BRANCH_FILE = "$TMPDIR/${FILE_PREFIX}files.branch"; +$MLIST_FILE = "$TMPDIR/${FILE_PREFIX}files.mlist"; +$SUMMARY_FILE = "$TMPDIR/${FILE_PREFIX}files.summary"; -$FILE_PREFIX = "#cvs.files"; +$CVSROOT = $ENV{'CVSROOT'}; +$MAIL_CMD = "| /usr/lib/sendmail -i -t"; +#$MAIL_CMD = "| /var/qmail/bin/qmail-inject"; +$MAIL_FROM = 'commitlogger'; #not needed if EMULATE_LOCAL_MAIL_USER +$SUBJECT_PRE = 'CVS update:'; + + +############################################################ # -# Subroutines +# Subroutines # +############################################################ + +sub format_names { + local($dir, @files) = @_; + local(@lines); + + $lines[0] = sprintf(" %-08s", $dir); + foreach $file (@files) { + if (length($lines[$#lines]) + length($file) > 60) { + $lines[++$#lines] = sprintf(" %8s", " "); + } + $lines[$#lines] .= " ".$file; + } + @lines; +} sub cleanup_tmpfiles { - local($wd, @files); + local(@files); - $wd = `pwd`; - chdir("/tmp") || die("Can't chdir('/tmp')\n"); - opendir(DIR, "."); - push(@files, grep(/^$FILE_PREFIX\..*\.$id$/, readdir(DIR))); + opendir(DIR, $TMPDIR); + push(@files, grep(/^${FILE_PREFIX}.*\.${id}\.${cvs_user}$/, readdir(DIR))); closedir(DIR); foreach (@files) { - unlink $_; + unlink "$TMPDIR/$_"; } - 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"; + 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) = @_; +sub append_to_file { + local($filename, $dir, @files) = @_; - open(FILE, ">$filename") || die("Cannot open log file $filename.\n"); - print FILE join("\n", @lines), "\n"; - close(FILE); + if (@files) { + local(@lines) = &format_names($dir, @files); + open(FILE, ">>$filename") || die ("Cannot open file $filename: $!\n"); + print(FILE join("\n", @lines), "\n"); + close(FILE); + } } -sub format_names { - local($dir, @files) = @_; - local(@lines); +sub write_line { + local($filename, $line) = @_; - $format = "\t%-" . sprintf("%d", length($dir)) . "s%s "; + open(FILE, ">$filename") || die("Cannot open file $filename: $!\n"); + print(FILE $line, "\n"); + close(FILE); +} - $lines[0] = sprintf($format, $dir, ":"); +sub append_line { + local($filename, $line) = @_; - 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; + open(FILE, ">>$filename") || die("Cannot open file $filename: $!\n"); + print(FILE $line, "\n"); + close(FILE); } -sub format_lists { - local(@lines) = @_; - local(@text, @files, $lastdir); +sub read_line { + local($filename) = @_; + local($line); + + open(FILE, "<$filename") || die("Cannot open file $filename: $!\n"); + $line = <FILE>; + close(FILE); + chomp($line); + $line; +} - 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)); +sub read_line_nodie { + local($filename) = @_; + local($line); + open(FILE, "<$filename") || return (""); - @text; + $line = <FILE>; + close(FILE); + chomp($line); + $line; } -sub append_names_to_file { - local($filename, $dir, @files) = @_; +sub read_file_lines { + local($filename) = @_; + local(@text) = (); - if (@files) { - open(FILE, ">>$filename") || die("Cannot open file $filename.\n"); - print FILE $dir, "\n"; - print FILE join("\n", @files), "\n"; - close(FILE); + open(FILE, "<$filename") || return (); + while (<FILE>) { + chomp; + push(@text, $_); } + close(FILE); + @text; } -sub read_line { - local($line); - local($filename) = @_; +sub read_file { + local($filename, $leader) = @_; + local(@text) = (); - open(FILE, "<$filename") || die("Cannot open file $filename.\n"); - $line = <FILE>; + open(FILE, "<$filename") || return (); + while (<FILE>) { + chomp; + push(@text, sprintf(" %-10s %s", $leader, $_)); + $leader = ""; + } close(FILE); - chop($line); - $line; + @text; } sub read_logfile { - local(@text); local($filename, $leader) = @_; + local(@text) = (); - open(FILE, "<$filename"); + open(FILE, "<$filename") || die ("Cannot open log file $filename: $!\n"); while (<FILE>) { - chop; - push(@text, $leader.$_); + chomp; + push(@text, $leader.$_); } close(FILE); @text; } +# +# 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, $vhost, $cvsweb_base); + + while (@filenames) { + $file = shift @filenames; + + if ("$file" eq "") { + next; + } + + open(RCS, "-|") || exec "$cvsbin/cvs", '-Qn', 'status', '--', $file; + + $rev = ""; + $delta = ""; + $rcsfile = ""; + + + while (<RCS>) { + if (/^[ \t]*Repository revision/) { + chomp; + @revline = split(' ', $_); + $rev = $revline[2]; + $rcsfile = $revline[3]; + $rcsfile =~ s,^$CVSROOT/,,; + $rcsfile =~ s/,v$//; + } + } + close(RCS); + + + if ($rev ne '' && $rcsfile ne '') { + open(RCS, "-|") || exec "$cvsbin/cvs", '-Qn', 'log', "-r$rev", + '--', $file; + while (<RCS>) { + if (/^date:/) { + chomp; + $delta = $_; + $delta =~ s/^.*;//; + $delta =~ s/^[\s]+lines://; + } + } + close(RCS); + } + + $diff = "\n\n"; + $vhost = @path[0]; + if ($CVSWEB_PORT eq "80") { + $cvsweb_base = "$CVSWEB_SCHEME://$vhost.$CVSWEB_DOMAIN/$CVSWEB_URI"; + } + else { + $cvsweb_base = "$CVSWEB_SCHEME://$vhost.$CVSWEB_DOMAIN:$CVSWEB_PORT/$CVSWEB_URI"; + } + if ($SEND_URL eq "true") { + $diff .= $cvsweb_base . join("/", @path) . "/$file"; + } + + # + # If this is a binary file, don't try to report a diff; not only is + # it meaningless, but it also screws up some mailers. We rely on + # Perl's 'is this binary' algorithm; it's pretty good. But not + # perfect. + # + if (($file =~ /\.(?:pdf|gif|jpg|mpg)$/i) || (-B $file)) { + if ($SEND_URL eq "true") { + $diff .= "?rev=$rev&content-type=text/x-cvsweb-markup\n\n"; + } + if ($SEND_DIFF eq "true") { + $diff .= "\t<<Binary file>>\n\n"; + } + } + else { + # + # Get the differences between this and the previous revision, + # being aware that new files always have revision '1.1' and + # new branches always end in '.n.1'. + # + if ($rev =~ /^(.*)\.([0-9]+)$/) { + $prev = $2 - 1; + $prev_rev = $1 . '.' . $prev; + + $prev_rev =~ s/\.[0-9]+\.0$//;# Truncate if first rev on branch + + if ($rev eq '1.1') { + if ($SEND_URL eq "true") { + $diff .= "?rev=$rev&content-type=text/x-cvsweb-markup\n\n"; + } + if ($SEND_DIFF eq "true") { + open(DIFF, "-|") + || exec "$cvsbin/cvs", '-Qn', 'update', '-p', '-r1.1', + '--', $file; + $diff .= "Index: $file\n==================================" + . "=================================\n"; + } + } + else { + if ($SEND_URL eq "true") { + $diff .= ".diff?r1=$prev_rev&r2=$rev\n\n"; + } + if ($SEND_DIFF eq "true") { + $diff .= "(In the diff below, changes in quantity " + . "of whitespace are not shown.)\n\n"; + open(DIFF, "-|") + || exec "$cvsbin/cvs", '-Qn', 'diff', "$difftype", + '-b', "-r$prev_rev", "-r$rev", '--', $file; + } + } + + if ($SEND_DIFF eq "true") { + while (<DIFF>) { + $diff .= $_; + } + close(DIFF); + } + $diff .= "\n\n"; + } + } + + &append_line($out, sprintf("%-9s%-12s%s%s", $rev, $delta, + $rcsfile, $diff)); + } +} + + sub build_header { local($header); - 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); + delete $ENV{'TZ'}; + local($sec,$min,$hour,$mday,$mon,$year) = localtime(time); + + $header = sprintf(" User: %-8s\n Date: %02d/%02d/%02d %02d:%02d:%02d", + $cvs_user, $year%100, $mon+1, $mday, + $hour, $min, $sec); +# $header = sprintf("%-8s %02d/%02d/%02d %02d:%02d:%02d", +# $login, $year%100, $mon+1, $mday, +# $hour, $min, $sec); +} + +# !!! Destination Mailing-list and history file mappings here !!! + +#sub mlist_map +#{ +# local($path) = @_; +# my $domain = "cvshome.org"; +# +# if ($path =~ /^([^\/]+)/) { +# return "cvs\@$1.$domain"; +# } else { +# return "cvs\@$domain"; +# } +#} + +sub derive_subject_from_changes_file () +{ + my $subj = ""; + + for ($i = 0; ; $i++) + { + open (CH, "<$CHANGED_FILE.$i.$id.$cvs_user") or last; + + while (my $change = <CH>) + { + # A changes file looks like this: + # + # src foo.c newfile.html + # www index.html project_nav.html + # + # Each line is " Dir File1 File2 ..." + # We only care about Dir, since the subject line should + # summarize. + + $change =~ s/^[ \t]*//; + $change =~ /^([^ \t]+)[ \t]*/; + my $dir = $1; + # Fold to rightmost directory component + $dir =~ /([^\/]+)$/; + $dir = $1; + if ($subj eq "") { + $subj = $dir; + } else { + $subj .= ", $dir"; + } + } + close (CH); + } + + if ($subj ne "") { + $subj = "MODIFIED: $subj ..."; + } + else { + # NPM: See if there's any file-addition notifications. + my $added = &read_line_nodie("$ADDED_FILE.$i.$id.$cvs_user"); + if ($added ne "") { + $subj .= "ADDED: $added "; + } + +# print "derive_subject_from_changes_file().. added== $added \n"; + + ## NPM: See if there's any file-removal notications. + my $removed = &read_line_nodie("$REMOVED_FILE.$i.$id.$cvs_user"); + if ($removed ne "") { + $subj .= "REMOVED: $removed "; + } + +# print "derive_subject_from_changes_file().. removed== $removed \n"; + + ## NPM: See if there's any branch notifications. + my $branched = &read_line_nodie("$BRANCH_FILE.$i.$id.$cvs_user"); + if ($branched ne "") { + $subj .= "BRANCHED: $branched"; + } + +# print "derive_subject_from_changes_file().. branched== $branched \n"; + + ## NPM: DEFAULT: DIRECTORY CREATION (c.f. "Check for a new directory first" in main mody) + if ($subj eq "") { + my $subject = join("/", @path); + $subj = "NEW: $subject"; + } + } + + return $subj; } -sub mail_notification { - local(@text) = @_; - - # if only we had strftime()... stuff stolen from perl's ctime.pl: - local($[) = 0; - - @DoW = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat'); - @MoY = ('Jan','Feb','Mar','Apr','May','Jun', - 'Jul','Aug','Sep','Oct','Nov','Dec'); - - # Determine what time zone is in effect. - # Use GMT if TZ is defined as null, local time if TZ undefined. - # There's no portable way to find the system default timezone. - # - $TZ = defined($ENV{'TZ'}) ? ( $ENV{'TZ'} ? $ENV{'TZ'} : 'GMT' ) : ''; - - # Hack to deal with 'PST8PDT' format of TZ - # Note that this can't deal with all the esoteric forms, but it - # does recognize the most common: [:]STDoff[DST[off][,rule]] - # - if ($TZ =~ /^([^:\d+\-,]{3,})([+-]?\d{1,2}(:\d{1,2}){0,2})([^\d+\-,]{3,})?/) { - $TZ = $isdst ? $4 : $1; - $tzoff = sprintf("%05d", -($2) * 100); +sub mail_notification +{ + local($addr_list, @text) = @_; + local($mail_to); + + my $subj = &derive_subject_from_changes_file (); + + if ($EMULATE_LOCAL_MAIL_USER NE "") { + $MAIL_FROM = "$cvs_user\@$EMULATE_LOCAL_MAIL_USER"; } - # perl-4.036 doesn't have the $zone or $gmtoff... - ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst, $zone, $gmtoff) = - ($TZ eq 'GMT') ? gmtime(time) : localtime(time); + $mail_to = join(", ", @{$addr_list}); - $year += ($year < 70) ? 2000 : 1900; + print "Mailing the commit message to $mail_to (from $MAIL_FROM)\n"; - if ($gmtoff != 0) { - $tzoff = sprintf("%05d", ($gmtoff / 60) * 100); - } - if ($zone ne '') { - $TZ = $zone; - } + $ENV{'MAILUSER'} = $MAIL_FROM; + # Commented out on hocus, so comment it out here. -kff + # $ENV{'QMAILINJECT'} = 'f'; - # ok, let's try.... - $rfc822date = sprintf("%s, %2d %s %4d %2d:%02d:%02d %s (%s)", - $DoW[$wday], $mday, $MoY[$mon], $year, - $hour, $min, $sec, $tzoff, $TZ); - - open(MAIL, "| $MAILER"); - print MAIL "Date: " . $rfc822date . "\n"; - print MAIL "Subject: CVS Update: " . $modulename . "\n"; - print MAIL "To: " . $mailto . "\n"; - print MAIL "Reply-To: " . $replyto . "\n"; - print MAIL "\n"; - print MAIL join("\n", @text), "\n"; + open(MAIL, "$MAIL_CMD -f$MAIL_FROM"); + print MAIL "From: $MAIL_FROM\n"; + print MAIL "To: $mail_to\n"; + print MAIL "Subject: $SUBJECT_PRE $subj\n\n"; + print(MAIL join("\n", @text)); close(MAIL); +# print "Mailing the commit message to $MAIL_TO...\n"; +# +# #added by jrobbins@collab.net 1999/12/15 +# # attempt to get rid of anonymous +# $ENV{'MAILUSER'} = 'commitlogger'; +# $ENV{'QMAILINJECT'} = 'f'; +# +# open(MAIL, "| /var/qmail/bin/qmail-inject"); +# print(MAIL "To: $MAIL_TO\n"); +# print(MAIL "Subject: cvs commit: $ARGV[0]\n"); +# print(MAIL join("\n", @text)); +# close(MAIL); +} + +## process the command line arguments sent to this script +## it returns an array of files, %s, sent from the loginfo +## command +sub process_argv +{ + local(@argv) = @_; + local(@files); + local($arg); + print "Processing log script arguments...\n"; + + while (@argv) { + $arg = shift @argv; + + if ($arg eq '-u') { + $cvs_user = shift @argv; + } else { + ($donefiles) && die "Too many arguments!\n"; + $donefiles = 1; + $ARGV[0] = $arg; + @files = split(' ', $arg); + } + } + return @files; } -sub write_commitlog { - local($logfile, @text) = @_; - - open(FILE, ">>$logfile"); - print FILE join("\n", @text), "\n"; - close(FILE); -} +############################################################# +# +# Main Body # -# Main Body +############################################################ # +# Setup environment +# +umask (002); + +# Connect to the database +$cvsbin = "/usr/bin"; +# # Initialize basic variables # -$debug = 0; -$id = getpgrp(); # note, you *must* use a shell which does setpgrp() +$id = getpgrp(); $state = $STATE_NONE; -chop($hostname = `hostname`); -chop($domainname = `domainname`); -if ($domainname !~ '^\..*') { - $domainname = '.' . $domainname; -} -$hostdomain = $hostname . $domainname; -$cvsroot = $ENV{'CVSROOT'}; -$do_status = 1; # moderately useful -$show_wd = 0; # useless in client/server -$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') { - 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 '-u') { - $login = 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; - } else { - ($donefiles) && die("Too many arguments! Check usage.\n"); - $donefiles = 1; - @files = split(/ /, $arg); - } -} -if ($login eq '') { - $login = getlogin || (getpwuid($<))[0] || "nobody"; -} -($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 -# +$cvs_user = $ENV{'USER'} || getlogin || (getpwuid($<))[0] || sprintf("uid#%d",$<); +@files = process_argv(@ARGV); @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 -} +$repository = $path[0]; 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"; + $dir = join('/', @path[1..$#path]); } +#print("ARGV - ", join(":", @ARGV), "\n"); +#print("files - ", join(":", @files), "\n"); +#print("path - ", join(":", @path), "\n"); +#print("dir - ", $dir, "\n"); +#print("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" +# Map the repository directory to an email address for commitlogs to be sent +# to. # -if ($files[2] =~ /New/ && $files[3] =~ /directory/) { - local(@text); +#$mlist = &mlist_map($files[0]); - @text = (); - push(@text, &build_header()); - push(@text, ""); - push(@text, $files[0]); - push(@text, ""); - - while (<STDIN>) { - 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" +# Check for a new directory first. This will always appear as a +# single item in the argument list, and an empty log message. # -if ($files[2] =~ /Imported/ && $files[3] =~ /sources/) { - local(@text); - +if ($ARGV[0] =~ /New directory/) { + $header = &build_header; @text = (); - push(@text, &build_header()); + push(@text, $header); push(@text, ""); - push(@text, $files[0]); - push(@text, ""); - - while (<STDIN>) { - chop; # Drop the newline - push(@text, $_); - } - - &mail_notification(@text); - + push(@text, " ".$ARGV[0]); + &mail_notification([ $mlist ], @text); exit 0; } +# # Iterate over the body of the message collecting information. # while (<STDIN>) { - chop; # Drop the newline - - if (/^In directory/) { - if ($show_wd) { # useless in client/server mode - push(@log_lines, $_); - push(@log_lines, ""); - } - next; + chomp; # Drop the newline + if (/^Revision\/Branch:/) { + s,^Revision/Branch:,,; + push (@branch_lines, split); + next; } - +# next if (/^[ \t]+Tag:/ && $state != $STATE_LOG); 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; } - - s/^[ \t\n]+//; # delete leading whitespace - s/[ \t\n]+$//; # delete trailing whitespace + s/[ \t\n]+$//; # delete trailing space - 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, $_); } + push (@changed_files, split) if ($state == $STATE_CHANGED); + push (@added_files, split) if ($state == $STATE_ADDED); + push (@removed_files, split) if ($state == $STATE_REMOVED); + if ($state == $STATE_LOG) { + if (/^PR:$/i || + /^Reviewed by:$/i || + /^Submitted by:$/i || + /^Obtained from:$/i) { + next; + } + 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. +# (Note, this only does the mail and changes log, not the rcs log). # while ($#log_lines > -1) { last if ($log_lines[0] ne ""); @@ -433,144 +616,105 @@ while ($#log_lines > -1) { } for ($i = $#log_lines; $i > 0; $i--) { if (($log_lines[$i - 1] eq "") && ($log_lines[$i] eq "")) { - splice(@log_lines, $i, 1); + 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 +# +# Find the 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"; + last if (! -e "$LOG_FILE.$i.$id.$cvs_user"); + @text = &read_logfile("$LOG_FILE.$i.$id.$cvs_user", ""); + last if ($#text == -1); + last if (join(" ", @log_lines) eq join(" ", @text)); } +# # 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); -&write_logfile("$LOG_FILE.$i.$id", @log_lines); +&write_logfile("$LOG_FILE.$i.$id.$cvs_user", @log_lines); +&append_to_file("$BRANCH_FILE.$i.$id.$cvs_user", $dir, @branch_lines); +&append_to_file("$ADDED_FILE.$i.$id.$cvs_user", $dir, @added_files); +&append_to_file("$CHANGED_FILE.$i.$id.$cvs_user", $dir, @changed_files); +&append_to_file("$REMOVED_FILE.$i.$id.$cvs_user", $dir, @removed_files); +&append_line("$MLIST_FILE.$i.$id.$cvs_user", $mlist); +if ($rcsidinfo) { + &change_summary("$SUMMARY_FILE.$i.$id.$cvs_user", (@changed_files, @added_files)); +} +# # Check whether this is the last directory. If not, quit. # -if ($debug) { - print STDERR "Checking current dir against last dir.\n"; +if (-e "$LAST_FILE.$id.$cvs_user") { + $_ = &read_line("$LAST_FILE.$id.$cvs_user"); + $tmpfiles = $files[0]; + $tmpfiles =~ s,([^a-zA-Z0-9_/]),\\$1,g; + if (! grep(/$tmpfiles$/, $_)) { + print "More commits to come...\n"; + exit 0 + } } -$_ = &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. # +$header = &build_header; # # Produce the final compilation of the log messages # @text = (); -@status_txt = (); -push(@text, &build_header()); +@mlist_list = (); +push(@text, $header); push(@text, ""); - for ($i = 0; ; $i++) { - last if (! -e "$LOG_FILE.$i.$id"); # we're done them all! - @lines = &read_logfile("$CHANGED_FILE.$i.$id", ""); - if ($#lines >= 0) { - push(@text, "Modified files:"); - push(@text, &format_lists(@lines)); - } - @lines = &read_logfile("$ADDED_FILE.$i.$id", ""); - if ($#lines >= 0) { - push(@text, "Added files:"); - push(@text, &format_lists(@lines)); - } - @lines = &read_logfile("$REMOVED_FILE.$i.$id", ""); - if ($#lines >= 0) { - push(@text, "Removed files:"); - push(@text, &format_lists(@lines)); - } - if ($#text >= 0) { - push(@text, ""); - } - @lines = &read_logfile("$LOG_FILE.$i.$id", "\t"); - if ($#lines >= 0) { - push(@text, "Log message:"); - push(@text, @lines); - 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 (<STATUS>) { - chop; - push(@status_txt, $_); - } - } + last if (! -e "$LOG_FILE.$i.$id.$cvs_user"); + push(@text, &read_file("$BRANCH_FILE.$i.$id.$cvs_user", "Branch:")); + push(@text, &read_file("$CHANGED_FILE.$i.$id.$cvs_user", "Modified:")); + push(@text, &read_file("$ADDED_FILE.$i.$id.$cvs_user", "Added:")); + push(@text, &read_file("$REMOVED_FILE.$i.$id.$cvs_user", "Removed:")); + push(@text, " Log:"); + push(@text, &read_logfile("$LOG_FILE.$i.$id.$cvs_user", " ")); + push(@mlist_list, &read_file_lines("$MLIST_FILE.$i.$id.$cvs_user")); + if ($rcsidinfo == 2) { + if (-e "$SUMMARY_FILE.$i.$id.$cvs_user") { + push(@text, " "); + push(@text, " Revision Changes Path"); + push(@text, &read_logfile("$SUMMARY_FILE.$i.$id.$cvs_user", " ")); + } } + push(@text, ""); } -# Write to the commitlog file # -if ($commitlog) { - &write_commitlog($commitlog, @text); +# Now generate the extra info for the mail message.. +# +if ($rcsidinfo == 1) { + $revhdr = 0; + for ($i = 0; ; $i++) { + last if (! -e "$LOG_FILE.$i.$id.$cvs_user"); + if (-e "$SUMMARY_FILE.$i.$id.$cvs_user") { + if (!$revhdr++) { + push(@text, "Revision Changes Path"); + } + push(@text, &read_logfile("$SUMMARY_FILE.$i.$id.$cvs_user", "")); + } + } + if ($revhdr) { + push(@text, ""); # consistancy... + } } -if ($#status_txt >= 0) { - push(@text, @status_txt); -} +%mlist_hash = (); -# Mailout the notification. -# -&mail_notification(@text); +foreach (@mlist_list) { $mlist_hash{ $_ } = 1; } -# cleanup # -if (! $debug) { - &cleanup_tmpfiles(); -} - +# Mail out the notification. +# +&mail_notification([ keys(%mlist_hash) ], @text); +&cleanup_tmpfiles; exit 0; |