From: Neil S. <sir...@us...> - 2005-01-08 01:59:58
|
CVSROOT : /cvsroot/publicdnsadmin Module : CVSROOT Commit time: 2005-01-08 01:59:46 UTC Modified files: checkoutlist commitinfo loginfo new_commit_prep new_log_accum rcsinfo Added files: maillist Log message: Thought this would need an update. CVS mailing scripts updated. ---------------------- diff included ---------------------- Index: CVSROOT/checkoutlist diff -u CVSROOT/checkoutlist:1.2 CVSROOT/checkoutlist:1.3 --- CVSROOT/checkoutlist:1.2 Tue Apr 15 19:47:48 2003 +++ CVSROOT/checkoutlist Fri Jan 7 17:59:36 2005 @@ -12,7 +12,7 @@ # # comment lines begin with '#' -syncmail -all.template Unable to check out template. -new_commit_prep Won't be able to do mail logging. -new_log_accum Won't be able to do mail logging. +all.template Unable to check out template. +new_commit_prep Won't be able to do mail logging. +new_log_accum Won't be able to do mail logging. +maillist Won't be able to do mail logging. Index: CVSROOT/commitinfo diff -u CVSROOT/commitinfo:1.2 CVSROOT/commitinfo:1.3 --- CVSROOT/commitinfo:1.2 Tue Apr 15 19:47:49 2003 +++ CVSROOT/commitinfo Fri Jan 7 17:59:36 2005 @@ -14,4 +14,5 @@ # If the name "ALL" appears as a regular expression it is always used # in addition to the first matching regex or "DEFAULT". + DEFAULT $CVSROOT/CVSROOT/new_commit_prep Index: CVSROOT/loginfo diff -u CVSROOT/loginfo:1.3 CVSROOT/loginfo:1.4 --- CVSROOT/loginfo:1.3 Wed Apr 16 00:28:03 2003 +++ CVSROOT/loginfo Fri Jan 7 17:59:36 2005 @@ -1,30 +1,21 @@ -# The "loginfo" file controls where "cvs commit" log information -# is sent. The first entry on a line is a regular expression which must match -# the directory that the change is being made to, relative to the -# $CVSROOT. If a match is found, then the remainder of the line is a filter -# program that should expect log information on its standard input. +# 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 this -# file, the "DEFAULT" line is used, if it is specified. +# 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. +# If the name "ALL" appears as a regular expression it is always used +# in addition to the first matching regex or "DEFAULT". # -# You may specify a format string as part of the -# filter. The string is composed of a `%' followed -# by a single format character, or followed by a set of format -# characters surrounded by `{' and `}' as separators. The format -# characters are: -# -# s = file name -# V = old version number (pre-checkin) -# v = new version number (post-checkin) +# 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 ""; id; echo %s; date; cat) >> $CVSROOT/CVSROOT/commitlog -# or -#DEFAULT (echo ""; id; echo %{sVv}; date; cat) >> $CVSROOT/CVSROOT/commitlog - -DEFAULT $CVSROOT/CVSROOT/new_log_accum -m pub...@li... %{sVv} -#DEFAULT $CVSROOT/CVSROOT/new_log_accum -m sir...@us... %{sVv} +#DEFAULT (echo ""; who am i; echo %s; date; cat) >> $CVSROOT/CVSROOT/commitlog +DEFAULT $CVSROOT/CVSROOT/new_log_accum %{sVv} Index: CVSROOT/maillist diff -u /dev/null CVSROOT/maillist:1.1 --- /dev/null Fri Jan 7 17:59:50 2005 +++ CVSROOT/maillist Fri Jan 7 17:59:36 2005 @@ -0,0 +1,21 @@ +# The "maillist" file is used to control commit log mails. +# The (space-separated) addresses on the right will be added +# to the list of addresses mail will be sent to. Using -m +# on the new_log_accum command line will override the contents +# of this file. +# +# The first entry on a line is a regular expression which is tested +# against the module that the change is being committed to, relative +# to the $CVSROOT. For the each match that is found, the remainder +# of the line is the list of email addresses. Note this regular +# expression is compared only against the *first* component of the +# path! +# +# If the repository name does not match any of the regular expressions in 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". + +DEFAULT pub...@li... + Index: CVSROOT/new_commit_prep diff -u CVSROOT/new_commit_prep:1.1 CVSROOT/new_commit_prep:1.2 --- CVSROOT/new_commit_prep:1.1 Tue Apr 15 19:47:49 2003 +++ CVSROOT/new_commit_prep Fri Jan 7 17:59:36 2005 @@ -1,6 +1,6 @@ #!/usr/bin/perl -w # -# Copyright (C) 2000 by Kevin L. Mitchell <kl...@mi...> +# Copyright (C) 2000,2002 by Kevin L. Mitchell <kl...@mi...> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -19,12 +19,23 @@ # # Script to store the last visited directory for newlogaccum.pl. # -# $Id: new_commit_prep,v 1.1 2003/04/16 02:47:49 sirvulcan Exp $ +# $Id: new_commit_prep,v 1.2 2005/01/08 01:59:36 sirvulcan Exp $ use strict; +use vars qw($debug); + +# Don't touch this; use the -d command line option +$debug = 0; + +# Debugging output +sub debug (@) { + print STDERR "$0: ", @_ + if ($debug); +} + # This routine removes everything in a directory -sub clear_dir ($) { +sub clear_dir { my ($dir) = @_; my ($file); @@ -92,6 +103,8 @@ sub write_line ($$) { my ($fname, $line) = @_; + debug "Writing line \"$line\" to \"$fname\"...\n"; + open(FILE, ">$fname") || die "Cannot open file $fname for writing"; print FILE "$line\n"; close(FILE); @@ -100,5 +113,14 @@ # Create and empty the temporary directory my ($tmpdir) = (tmpdir(1)); +# Set debugging if necessary +if ($ARGV[0] eq "-d") { + shift(@ARGV); + $debug++; +} + +# Log command line +debug "options \"", join("\" \"", @ARGV), "\"\n"; + # Store the directory name write_line("$tmpdir/lastdir", shift(@ARGV)); Index: CVSROOT/new_log_accum diff -u CVSROOT/new_log_accum:1.1 CVSROOT/new_log_accum:1.2 --- CVSROOT/new_log_accum:1.1 Tue Apr 15 19:47:49 2003 +++ CVSROOT/new_log_accum Fri Jan 7 17:59:36 2005 @@ -1,6 +1,6 @@ #!/usr/bin/perl -w # -# Copyright (C) 2000 by Kevin L. Mitchell <kl...@mi...> +# Copyright (C) 2000,2002 by Kevin L. Mitchell <kl...@mi...> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -20,37 +20,59 @@ # Script to accumulate log messages for an entire tree and send them along # with the diffs; deals correctly with all manner of branching (I hope) # -# $Id: new_log_accum,v 1.1 2003/04/16 02:47:49 sirvulcan Exp $ +# $Id: new_log_accum,v 1.2 2005/01/08 01:59:36 sirvulcan Exp $ use strict; -use vars qw($MAILER $CVS $debug); +use vars qw($MAILER $CVS $debug $maillist); # Set this to the full path of a mailer that takes -s <subject> and a list # of email addresses as arguments... $MAILER = "/bin/mail"; # Set this to the path of the CVS binary responsible for this tree... -$CVS = "/usr/local/bin/cvs"; +$CVS = "/usr/bin/cvs"; # Don't touch this; use the -d command line option $debug = 0; +# Don't touch this, just create (or delete) the file +$maillist = "$ENV{CVSROOT}/CVSROOT/maillist"; + use POSIX qw(setsid); +# Debugging output +sub debug (@) { + my (@args) = @_; + + if ($args[0] eq "-np") { + shift(@args); + } else { + unshift(@args, "$0: "); + } + + print STDERR @args + if ($debug); +} + # We have to dissociate from our parent, so that the CVS commit can # complete, before we try to extract the diffs sub daemonize { + debug "Daemonizing..."; defined(my $pid = fork()) || die "Can't fork: $!"; exit(0) if $pid; + unless ($debug) { + open(STDIN, "</dev/null"); + open(STDOUT, ">/dev/null"); + open(STDERR, ">&STDOUT"); + for (my $i = 2; $i < 255; $i++) { + POSIX::close($i); + } + } + chdir("/"); setsid() || die "Can't start a new session: $!"; -} - -# Debugging output -sub debug (@) { - print STDERR @_ - if ($debug); + debug "-np", "Done!\n"; } # Constants used in the FSM below for parsing the log message @@ -62,7 +84,7 @@ sub STATE_LOG2 { 5 } # This routine removes everything in a directory -sub clear_dir ($) { +sub clear_dir { my ($dir) = @_; my ($file); @@ -171,6 +193,77 @@ return @{$array} - 1; } +# Load a list of regular expressions and email addresses +sub load_maillist ($) { + my ($file) = @_; + my ($mmap) = ({ + DEFAULT => [], + ALL => [], + re => {}, + }); + + # Don't load the list if it doesn't exist + return undef + unless (-e $file); + + # Open the map file + open(MAILFILE, "<$file"); + while (<MAILFILE>) { + chomp; + + s/\#.*$//; + next + if (/^\s*$/); + + my ($re, @addrs) = split; + + # DEFAULT and ALL are treated specially + if ($re eq "DEFAULT" || $re eq "ALL") { + push_once(@{$mmap->{$re}}, @addrs); + } else { + $mmap->{re}{$re} = [] + unless (exists($mmap->{re}{$re})); + + # Remember the associated email addresses + push_once(@{$mmap->{re}{$re}}, @addrs); + } + } + close(MAILFILE); + + return $mmap; +} + +# Given the module's name (and a mailmap structure), return the necessary +# email addresses +sub make_maillist ($$@) { + my ($mmap, $module, @inaddrs) = @_; + my ($matches, @addrs) = 0; + + # Return defaults passed in + return @inaddrs + unless (defined($mmap)); + + # Everything in ALL gets a message + push_once(@addrs, @{$mmap->{ALL}}[1..$#{$mmap->{ALL}}]); + # Now check each pattern one by one + foreach my $pat (keys(%{$mmap->{re}})) { + if ($module =~ /$pat/) { + $matches++; + push_once(@addrs, @{$mmap->{re}{$pat}}[1..$#{$mmap->{re}{$pat}}]); + } + } + # If no patterns matched, push on the defaults + push_once(@addrs, @{$mmap->{DEFAULT}}[1..$#{$mmap->{DEFAULT}}]) + unless ($matches > 0); + + # Return the defaults if we came up with nothing + return @inaddrs + unless (@addrs > 0); + + # Return just the addresses + return @addrs[1..$#addrs]; +} + # Filter //, /./, and remove leading ./ or / from filenames sub fname_filter ($) { my ($fname) = @_; @@ -308,13 +401,44 @@ close(FILE); } +# load module list +sub load_modules ($) { + my ($tmpdir) = @_; + my (@modlist); + + debug "Reading modules from $tmpdir/modules...\n"; + + # We may not have, say, recorded any modules yet + return () + if (!-e "$tmpdir/modules"); + + open(MODLIST, "<$tmpdir/modules"); + push_once(@modlist, map { chomp; $_ } <MODLIST>); + close(MODLIST); + + return @modlist; +} + +# save module list +sub save_modules (\@$) { + my ($modlist, $tmpdir) = @_; + + debug "Writing modules out to $tmpdir/modules...\n"; + + open(MODLIST, ">$tmpdir/modules"); + print MODLIST join("\n", @{$modlist}[1..$#{$modlist}]), "\n"; + close(MODLIST); +} + # Build the header of the commit message: CVSROOT, module name, any # branch tags, and the commit time sub build_header ($@) { my ($module, @branch_tags) = @_; my (@text); my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time()); + my ($user) = (getpwuid($<)); + push(@text, "Committer : $user"); push(@text, "CVSROOT : $ENV{CVSROOT}"); push(@text, "Module : $module"); push(@text, "Branch tags: " . join(' ', @branch_tags[1..$#branch_tags])) @@ -329,18 +453,291 @@ sub send_mail (\@$@) { my ($mailto, $subject, @text) = @_; - open(MAIL, "|$MAILER -s \"$subject\" " . join(' ', @{$mailto})); + debug("Sending mail, subject \"$subject\", to ", join(' ', @{$mailto}), + "\n"); + debug("-np", "> ", join("\n> ", @text), "\n"); + + # Execute our mailer... + my $pid = open(MAIL, "|-"); + + exec($MAILER, '-s', $subject, @{$mailto}) + unless ($pid); + print MAIL join("\n", @text), "\n"; close(MAIL); } +# Generates the diffs to include +sub diff_files ($@) { + my ($module, @files) = @_; + my (@text); + + foreach my $file (@files) { + debug "Diffing file $file->{name} (module $module)\n"; + + # Run cvs rdiff, extracting a diff between the old and new versions + my $pid = open(DIFF, "-|"); + + exec($CVS, '-Q', 'rdiff', '-u', '-r', $file->{old}, '-r', $file->{new}, + "$module/$file->{name}") + unless ($pid); + + # Chomp and store all the text... + push(@text, map { chomp; $_ } <DIFF>); + + close(DIFF); + } + + return @text; +} + +# Read in and process log message +sub read_log (\%\@\@\@\@\@) { + my ($fversions, $modified, $added, $removed, $log, $branch_tags) = @_; + my ($state, $tag) = (STATE_NONE, undef); + + while (<STDIN>) { + chomp; + + debug "State $state, line:$_\n"; + + # Ignore empty space at the beginning of the log message + next + if ($state == STATE_LOG1 && /^\s*$/); + + # We're done ignoring empty space + if ($state == STATE_LOG1) { + $state = STATE_LOG2; + } + + if ($state == STATE_LOG2) { + # Don't modify the lines at all if we're processing the log message + push(@{$log}, $_); + next; + } else { + # Strip out leading and trailing space + s/^\s*(.*?)\s*$/$1/; + } + + if (/^Modified Files/) { + # Collect list of modified files + debug "State switching to STATE_MODIFIED\n"; + + $state = STATE_MODIFIED; + $tag = undef; + + next; + + } elsif (/^Added Files/) { + # Collect list of added files + debug "State switching to STATE_ADDED\n"; + + $state = STATE_ADDED; + $tag = undef; + + next; + + } elsif (/^Removed Files/) { + # Collect list of removed files + debug "State switching to STATE_REMOVED\n"; + + $state = STATE_REMOVED; + $tag = undef; + + next; + + } elsif (/^Log Message/) { + # Collect log message + debug "State switching to STATE_LOG1\n"; + + $state = STATE_LOG1; + $tag = undef; + + next; + + } elsif (/^Revision\/Branch/) { + # Parse old-style Revision/Branch field + debug "Found a branch tag\n"; + + /^[^:]+:\s*(.*)/; + + push_once(@{$branch_tags}, $1); + + warn "Tag == $tag" + if (defined($tag)); + + next; + } + + # Ignore the stuff at the top of the commit report + next + if ($state == STATE_NONE); + + if (/^Tag:\s*(.*)$/) { + # Remember the tag + debug "Setting tag to $1\n"; + $tag = $1; + next; + } + + my (@tfiles) = (); + + # Find the file in our command line list of files + foreach my $file (split) { + die "Nothing known about file $file!" + unless (exists($fversions->{$file})); + + push @tfiles, { + file => $file, + tag => $tag, + old => $fversions->{$file}{old}, + new => $fversions->{$file}{new}, + }; + } + + # Store the file list in the correct array + push(@{$modified}, @tfiles) + if ($state == STATE_MODIFIED); + + push(@{$added}, @tfiles) + if ($state == STATE_ADDED); + + push(@{$removed}, @tfiles) + if ($state == STATE_REMOVED); + } + + # Remove trailing blank lines from the log message + while (@{$log} > 0 && $log->[$#{$log}] =~ /^\s*$/) { + pop(@{$log}); + } +} + +# Build and send message for a new directory +sub send_newdir ($$\@\@@) { + my ($module, $dir, $log, $branch_tags, @mailto) = @_; + my (@text) = (); + + # If there was a sticky tag for the directory, make it a branch tag + if ($log->[$#{$log}] =~ /^--> Using per-directory sticky tag \`(.*)\'$/) { + push_once(@{$branch_tags}, $1); + pop(@{$log}); + } + + # Build the message... + push(@text, build_header($module, @{$branch_tags})); + push(@text, "Log message:", "", @{$log}); + + # and send it (synchronously) + send_mail(@mailto, "[CVS] Module $module: New directory $dir", @text); +} + +# Build and send message for an import +sub send_import ($$\@\@@) { + my ($module, $dir, $log, $branch_tags, @mailto) = @_; + my (@text) = (); + + # Build the message... + push(@text, build_header($module, @{$branch_tags})); + push(@text, "Log message:", "", @{$log}); + + # and send it (synchronously) + send_mail(@mailto, "[CVS] Module $module: Imported $dir", @text); +} + +# Find log file matching our log +sub find_logfile ($$\@) { + my ($module, $tmpdir, $log) = @_; + my ($i); + + debug "Searching for log file index..."; + + for ($i = 0; ; $i++) { + my (@text); + + # found one that doesn't exist... + last + if (!-e "$tmpdir/mod.$module/logfile.$i"); + + # read in the log file + open(FILE, "<$tmpdir/mod.$module/logfile.$i"); + push(@text, map { chomp; $_ } <FILE>); + close(FILE); + + # If the log file was empty, use it + last + if (@text == 0); + + # If the log messages are identical, use that + last + if (join(' ', @{$log}) eq join(' ', @text)); + } + + debug "-np", "$tmpdir/mod.$module/logfile.$i\n"; + + return $i; +} + +sub send_commit ($$@) { + my ($module, $tmpdir, @mailto) = @_; + my ($i, @text, @modified, @added, @removed, @files, @branch_tags); + + for ($i = 0; ; $i++) { + # No more log files + last + if (!-e "$tmpdir/mod.$module/logfile.$i"); + + # read modified list and list all modified files if non-empty + @modified = file_to_names(@branch_tags, + "$tmpdir/mod.$module/modified.$i"); + push(@text, "Modified files:", name_to_list(@branch_tags, @modified), + "") + if (@modified > 0); + + # read added list and list all added files if non-empty + @added = file_to_names(@branch_tags, "$tmpdir/mod.$module/added.$i"); + push(@text, "Added files:", name_to_list(@branch_tags, @added), "") + if (@added > 0); + + # read removed list and list all removed files if non-empty + @removed = file_to_names(@branch_tags, + "$tmpdir/mod.$module/removed.$i"); + push(@text, "Removed files:", name_to_list(@branch_tags, @removed), "") + if (@removed > 0); + + # read and insert the log message + open(FILE, "<$tmpdir/mod.$module/logfile.$i"); + push(@text, "Log message:", ""); + push(@text, map { chomp; $_ } <FILE>); + push(@text, ""); + close(FILE); + + # remember all the files we looked at + push(@files, @modified, @added, @removed); + } + + # Now that name_to_list has rebuilt our list of branch tags, we can build + # the header and prepend it to the message + unshift(@text, build_header($module, @branch_tags)); + + # sort the files out for our diff + @files = sort { $a->{name} cmp $b->{name} } @files; + + # add the diff... + push(@text, "---------------------- diff included ----------------------"); + push(@text, diff_files($module, @files)); + push(@text, "----------------------- End of diff -----------------------"); + + # Now send the mail + send_mail(@mailto, "[CVS] Module $module: Change committed", @text); +} + # Find the tmp directory my ($tmpdir) = (tmpdir()); my (@mailto) = (); my (@files) = (); my (@path) = (); -my ($modname, $repdir, $dir) = (undef, undef, undef); +my ($module, $repdir, $dir, $mailmap) = (undef, undef, undef, undef); # Process command line arguments while (@ARGV > 0) { @@ -349,12 +746,6 @@ if ($arg eq '-d') { # Turn on debugging $debug++; - } elsif ($arg eq '-M') { - # Module name explicitly set -- XXX Not tested, use at your own risk - die "Argument for -M missing" - unless (@ARGV > 0); - - $modname = shift(@ARGV); } elsif ($arg eq '-m') { # An address to mail the notification to die "Argument for -m missing" @@ -370,9 +761,12 @@ } } -die "Nobody to mail to" +$mailmap = load_maillist($maillist) unless (@mailto > 0); +die "Nobody to mail to" + unless (@mailto > 0 || defined($mailmap)); + die "No files to process" unless (@files > 1); @@ -383,8 +777,7 @@ @path = split("/", $repdir); # Now we know the module name, if it wasn't explicitly set -$modname = $path[0] - unless (defined($modname)); +$module = $path[0]; # Figure out what our directory is if (@path == 1) { @@ -396,7 +789,7 @@ # append a / to it... $dir .= "/"; -debug "module = $modname\n"; +debug "module = $module\n"; debug "dir = $dir\n"; debug "path = ", join(":", @path), "\n"; debug "files = ", join(":", @files), "\n"; @@ -421,284 +814,62 @@ } } -# process log message -my ($state, $tag) = (STATE_NONE, undef); - -my (@modified, @added, @removed, @log, @branch_tags) = (); - -while (<STDIN>) { - chomp; - - debug "State $state, line:$_\n"; - - # Ignore empty space at the beginning of the log message - next - if ($state == STATE_LOG1 && /^\s*$/); - - # We're done ignoring empty space - if ($state == STATE_LOG1) { - $state = STATE_LOG2; - } - - if ($state == STATE_LOG2) { - # Don't modify the lines at all if we're processing the log message - push(@log, $_); - next; - } else { - # Strip out leading and trailing space - s/^\s*(.*?)\s*$/$1/; - } - - if (/^Modified Files/) { - # Collect list of modified files - debug "State switching to STATE_MODIFIED\n"; - - $state = STATE_MODIFIED; - $tag = undef; - - next; - - } elsif (/^Added Files/) { - # Collect list of added files - debug "State switching to STATE_ADDED\n"; - - $state = STATE_ADDED; - $tag = undef; - - next; - - } elsif (/^Removed Files/) { - # Collect list of removed files - debug "State switching to STATE_REMOVED\n"; - - $state = STATE_REMOVED; - $tag = undef; - - next; - - } elsif (/^Log Message/) { - # Collect log message - debug "State switching to STATE_LOG1\n"; - - $state = STATE_LOG1; - $tag = undef; +my (@modules) = load_modules($tmpdir); +push_once(@modules, $module); +save_modules(@modules, $tmpdir); - next; +die "Can't create per-module directory $tmpdir/mod.$module: $!" + unless (-e "$tmpdir/mod.$module" || mkdir("$tmpdir/mod.$module", 0700)); - } elsif (/^Revision\/Branch/) { - # Parse old-style Revision/Branch field - debug "Found a branch tag\n"; +die "Per-module directory $tmpdir/mod.$module is not a directory" + unless (-d "$tmpdir/mod.$module"); - /^[^:]+:\s*(.*)/; +my (@modified, @added, @removed, @log, @branch_tags); - push_once(@branch_tags, $1); - - warn "Tag == $tag" - if (defined($tag)); - - next; - } - - # Ignore the stuff at the top of the commit report - next - if ($state == STATE_NONE); - - if (/^Tag:\s*(.*)$/) { - # Remember the tag - debug "Setting tag to $1\n"; - $tag = $1; - next; - } - - my (@tfiles) = (); - - # Find the file in our command line list of files - foreach my $file (split) { - die "Nothing known about file $file!" - unless (exists($fversions{$file})); - - push @tfiles, { - file => $file, - tag => $tag, - old => $fversions{$file}{old}, - new => $fversions{$file}{new}, - }; - } - - # Store the file list in the correct array - push(@modified, @tfiles) - if ($state == STATE_MODIFIED); - - push(@added, @tfiles) - if ($state == STATE_ADDED); - - push(@removed, @tfiles) - if ($state == STATE_REMOVED); -} - -# Remove trailing blank lines from the log message -while (@log > 0 && $log[$#log] =~ /^\s*$/) { - pop(@log); -} +read_log(%fversions, @modified, @added, @removed, @log, @branch_tags); # If a new directory was added, we're done... if (defined($files[1]) && defined($files[2]) && $files[1] eq "New" && $files[2] eq "directory") { + debug "Sending log message for new directory $dir\n"; + send_newdir($module, $dir, @log, @branch_tags, + make_maillist($mailmap, $module, @mailto)); +} elsif (defined($files[1]) && defined($files[2]) && + $files[1] eq "Imported" && $files[2] eq "sources") { + debug "Sending log message for new import $dir\n"; + send_import($module, $dir, @log, @branch_tags, + make_maillist($mailmap, $module, @mailto)); +} else { + my $i = find_logfile($module, $tmpdir, @log); - my (@text) = (); - - # If there was a sticky tag for the directory, make it a branch tag - if ($log[$#log] =~ /^--> Using per-directory sticky tag \`(.*)\'$/) { - push_once(@branch_tags, $1); - pop(@log); - } - - # Build the message... - push(@text, build_header($modname, @branch_tags)); - push(@text, "Log message:", "", @log); - - # and send it (synchronously) - send_mail(@mailto, "[CVS] Module $modname: New directory $dir", @text); - - # Clean up after ourselves and exit. - cleanup_dir($tmpdir); - exit(0); -} - -# If an import was done, we're done... -if (defined($files[1]) && defined($files[2]) && - $files[1] eq "Imported" && $files[2] eq "sources") { - - my (@text) = (); - - # Build the message... - push(@text, build_header($modname, @branch_tags)); - push(@text, "Log message:", "", @log); - - # and send it (synchronously) - send_mail(@mailto, "[CVS] Module $modname: Imported $dir", @text); - - # Clean up after ourselves and exit. - cleanup_dir($tmpdir); - exit(0); -} - -debug "Searching for log file index..."; - -my ($i); - -# Look for an empty log file or one that matches our current log message -for ($i = 0; ; $i++) { - my (@text); - - # found one that doesn't exist... - last - if (!-e "$tmpdir/logfile.$i"); - - # read in the log file - open(FILE, "<$tmpdir/logfile.$i"); - while (<FILE>) { - chomp; - push(@text, $_); - } - close(FILE); + # Store modified, added, and removed file lists, along with the log message + names_to_file("$tmpdir/mod.$module/modified.$i", $dir, @modified); + names_to_file("$tmpdir/mod.$module/added.$i", $dir, @added); + names_to_file("$tmpdir/mod.$module/removed.$i", $dir, @removed); + write_log("$tmpdir/mod.$module/logfile.$i", @log); - # If the log file was empty, use it - last - if (@text == 0); - - # If the log messages are identical, use that - last - if (join(' ', @log) eq join(' ', @text)); -} - -debug "$tmpdir/logfile.$i\n"; - -# Store modified, added, and removed file lists, along with the log message -names_to_file("$tmpdir/modified.$i", $dir, @modified); -names_to_file("$tmpdir/added.$i", $dir, @added); -names_to_file("$tmpdir/removed.$i", $dir, @removed); -write_log("$tmpdir/logfile.$i", @log); - -# Now check to see if we're at the end of our rope -my ($lastdir) = (get_line("$tmpdir/lastdir")); - -debug "Checking $ENV{CVSROOT}/$repdir against lastdir $lastdir\n"; - -# Nope, exit instead of sending a message -exit(0) - if ($lastdir ne "$ENV{CVSROOT}/$repdir"); - -debug "At last, we've reached the end\n"; - -# We have to daemonize and sleep so that there isn't any lock hanging -# around when we get to the cvs rdiff below... -daemonize(); -sleep(10); - -# Build the mail message... -my (@text) = (); -@files = (); -@branch_tags = (); - -for ($i = 0; ; $i++) { - # No more log files - last - if (!-e "$tmpdir/logfile.$i"); - - # read modified list and list all modified files if non-empty - @modified = file_to_names(@branch_tags, "$tmpdir/modified.$i"); - push(@text, "Modified files:", name_to_list(@branch_tags, @modified), "") - if (@modified > 0); - - # read added list and list all added files if non-empty - @added = file_to_names(@branch_tags, "$tmpdir/added.$i"); - push(@text, "Added files:", name_to_list(@branch_tags, @added), "") - if (@added > 0); - - # read removed list and list all removed files if non-empty - @removed = file_to_names(@branch_tags, "$tmpdir/removed.$i"); - push(@text, "Removed files:", name_to_list(@branch_tags, @removed), "") - if (@removed > 0); - - # read and insert the log message - open(FILE, "<$tmpdir/logfile.$i"); - push(@text, "Log message:", ""); - while (<FILE>) { - chomp; - push(@text, $_); - } - push(@text, ""); - close(FILE); - - # remember all the files we looked at - push(@files, @modified, @added, @removed); -} + # Now check to see if we're at the end of our rope + my ($lastdir) = (get_line("$tmpdir/lastdir")); -# Now that name_to_list has rebuilt our list of branch tags, we can build the -# header and prepend it to the message -unshift(@text, build_header($modname, @branch_tags)); + debug "Checking $ENV{CVSROOT}/$repdir against lastdir $lastdir\n"; -# sort the files out for our diff -@files = sort { $a->{name} cmp $b->{name} } @files; + # Nope, exit instead of sending a message + exit(0) + if ($lastdir ne "$ENV{CVSROOT}/$repdir"); -push(@text, "---------------------- diff included ----------------------"); -foreach my $file (@files) { - debug "Diffing file $file->{name}...\n"; + debug "At last, we've reached the end\n"; - # Run cvs rdiff, extracting a diff between the old version and the new - open(DIFF, "$CVS -Q rdiff -u -r $file->{old} -r $file->{new} " . - "$modname/$file->{name}|"); - while (<DIFF>) { - chomp; - push(@text, $_); + # We have to daemonize and sleep so that there isn't any lock hanging + # around when we get to the cvs rdiff below... + daemonize(); + sleep(10); + + # Send a mail for each module involved + foreach my $mod (@modules[1..$#modules]) { + debug "Sending log message for module $mod\n"; + send_commit($mod, $tmpdir, make_maillist($mailmap, $mod, @mailto)); } - close(DIFF); } -push(@text, "----------------------- End of diff -----------------------"); - -# send the mail... -send_mail(@mailto, "[CVS] Module $modname: Change committed", @text); # and clean up after ourselves cleanup_dir($tmpdir); Index: CVSROOT/rcsinfo diff -u CVSROOT/rcsinfo:1.2 CVSROOT/rcsinfo:1.3 --- CVSROOT/rcsinfo:1.2 Tue Apr 15 19:47:49 2003 +++ CVSROOT/rcsinfo Fri Jan 7 17:59:36 2005 @@ -13,4 +13,3 @@ # in addition to the first matching regex or "DEFAULT". DEFAULT $CVSROOT/CVSROOT/all.template - ----------------------- End of diff ----------------------- |