From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: "Stephen J. Turnbull" Newsgroups: gmane.emacs.devel Subject: Re: Reviewing changes Date: Thu, 20 Nov 2008 17:31:03 +0900 Message-ID: <87y6zelry0.fsf@xemacs.org> References: <87y6zggnmz.fsf@red-bean.com> <87d4grbcc0.fsf@red-bean.com> <877i6zmdlv.fsf@xemacs.org> <87k5aydhsq.fsf@red-bean.com> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: ger.gmane.org 1227169644 12298 80.91.229.12 (20 Nov 2008 08:27:24 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 20 Nov 2008 08:27:24 +0000 (UTC) Cc: emacs-devel@gnu.org To: Karl Fogel Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Thu Nov 20 09:28:25 2008 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1L34th-0008PQ-P0 for ged-emacs-devel@m.gmane.org; Thu, 20 Nov 2008 09:28:25 +0100 Original-Received: from localhost ([127.0.0.1]:52746 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1L34sY-0005bG-FP for ged-emacs-devel@m.gmane.org; Thu, 20 Nov 2008 03:27:10 -0500 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1L34sR-0005b2-Pd for emacs-devel@gnu.org; Thu, 20 Nov 2008 03:27:03 -0500 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1L34sP-0005am-H9 for emacs-devel@gnu.org; Thu, 20 Nov 2008 03:27:03 -0500 Original-Received: from [199.232.76.173] (port=60287 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1L34sP-0005ai-Ag for emacs-devel@gnu.org; Thu, 20 Nov 2008 03:27:01 -0500 Original-Received: from mtps02.sk.tsukuba.ac.jp ([130.158.97.224]:39135) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1L34sO-0004Fs-0M for emacs-devel@gnu.org; Thu, 20 Nov 2008 03:27:01 -0500 Original-Received: from uwakimon.sk.tsukuba.ac.jp (uwakimon.sk.tsukuba.ac.jp [130.158.99.156]) by mtps02.sk.tsukuba.ac.jp (Postfix) with ESMTP id 71EF8820D; Thu, 20 Nov 2008 17:26:52 +0900 (JST) Original-Received: by uwakimon.sk.tsukuba.ac.jp (Postfix, from userid 1000) id 5B0AA1A2D03; Thu, 20 Nov 2008 17:31:03 +0900 (JST) In-Reply-To: <87k5aydhsq.fsf@red-bean.com> X-Mailer: VM 8.0.12-devo-585 under 21.5 (beta28) "fuki" 83e35df20028+ XEmacs Lucid (x86_64-unknown-linux) X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:105849 Archived-At: Karl Fogel writes: > > # (Ask Karl Fogel if questions.) > > -- from CVSROOT/log_accum, l.29 > > Er, heh. Um. Hey, you don't need any excuse. Nobody has bothered you 'cause log_accum is in "Zarro Boogs found" state! But you might want to stop forwarding on that email address just in case a boog should appear. ;-) > Please investigate -- let's see if we can make it happen here! OK, they're not so long, so I'll just include the needed files here (removing some historical XEmacs cruft, but leaving in any log_accum cruft, eg, the unused read_line subroutine in commit_prep). I don't know if there are newer versions, but these work for us. YMMV. The first file is loginfo, which is a config file whose content is a regexp -> action map. The regexp should match the name of the file to commit, relative to $CVSROOT. It can be quite simple, as you see. The second is commit_prep, which is a prehook that does some preparatory work to allow log_accum to figure out when it's done. AFAIK these two files must be given exactly those names, or CVS won't find them. The third is log_accum itself. That file's name needs to match the action in loginfo. commit_prep and log_accum need to be executable. All of them live in $CVSROOT. And that seems to be it. If there are any questions I'll see what I can do, but I'm not the person who wrangled all this stuff (I'm not entirely sure who did, actually). -------------------------------- loginfo -------------------------------- # 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. # # 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. # # 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) # # For example: #DEFAULT (echo ""; id; echo %s; date; cat) >> $CVSROOT/CVSROOT/commitlog # or #DEFAULT (echo ""; id; echo %{sVv}; date; cat) >> $CVSROOT/CVSROOT/commitlog # perhaps useful for testing # create a random module named logtest and commit there; see if the # mail comes! ^logtest $CVSROOT/CVSROOT/log_accum %s # handles commit messages for packages (core dev has moved to Mercurial) # log_accum expects the log on stdin; the %s is the file name (see # above), I guess you could do something like "%s (new version %v)", # too, but I haven't tried that. ^XEmacs/packages\(/[^/]+\)*$ $CVSROOT/CVSROOT/log_accum %s ------------------------------ commit_prep ------------------------------ #! /coll/local/bin/perl # -*-Perl-*- # # Perl filter to handle pre-commit checking of files. This program # records the last directory where commits will be taking place for # use by the log_accum.pl script. # # IMPORTANT: this script interacts with log_accum, they have to agree # on the tmpfile name to use. See $LAST_FILE below. # # Contributed by David Hampton # Stripped to minimum by Roy Fielding # ############################################################ $TMPDIR = $ENV{'TMPDIR'} || '/tmp'; $FILE_PREFIX = '#cvs.'; $CVS_USERNAME = $ENV{'USER'} || getlogin || (getpwuid($<))[0] || sprintf("uid#%d",$<); # This needs to match the corresponding var in log_accum.pl, including # the appending of the pgrp and username suffixes (see uses of this # var farther down). $LAST_FILE = "$TMPDIR/${FILE_PREFIX}lastdir"; sub write_line { my ($filename, $line) = @_; # A check of some kind is needed here, but the rules aren't apparent # at the moment: # foreach($filename, $line){ # $_ =~ m#^([-\@\w.\#]+)$#; # $_ = $1; # } open(FILE, ">$filename") || die("Cannot open $filename: $!\n"); print(FILE $line, "\n"); close(FILE); } # # Record this directory as the last one checked. This will be used # by the log_accumulate script to determine when it is processing # the final directory of a multi-directory commit. # $id = getpgrp(); &write_line("$LAST_FILE.$id.$CVS_USERNAME", $ARGV[0]); sub read_line { local($filename) = @_; local($line); open(FILE, "<$filename") || die("Cannot open file $filename: $!\n"); $line = ; close(FILE); chomp($line); $line; } exit(0); ------------------------------- log_accum ------------------------------- #! /coll/local/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. # # 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 if questions.) # # Contributed by David Hampton # Roy Fielding removed useless code and added log/mail of new files # Ken Coar added special processing (i.e., no diffs) for binary files # ############################################################ # # Configurable options # ############################################################ # # Where do you want the RCS ID and delta info? # 0 = none, # 1 = in mail only, # 2 = in both mail and logs. # $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"; # Set this to '-c' for context diffs; defaults to '-u' for unidiff format. $difftype = '-uNp'; ############################################################ # # Constants # ############################################################ $STATE_NONE = 0; $STATE_CHANGED = 1; $STATE_ADDED = 2; $STATE_REMOVED = 3; $STATE_LOG = 4; $TMPDIR = $ENV{'TMPDIR'} || '/tmp'; $FILE_PREFIX = '#cvs.'; $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"; $CVSROOT = $ENV{'CVSROOT'}; $MAIL_CMD = "| /coll/local/bin/sendmail -i -t"; #$MAIL_CMD = "| /var/qmail/bin/qmail-inject"; $MAIL_FROM = 'xemacs-cvs@xemacs.org'; #not needed if EMULATE_LOCAL_MAIL_USER $SUBJECT_PRE = 'CVS update'; ############################################################ # # 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(@files); opendir(DIR, $TMPDIR); push(@files, grep(/^${FILE_PREFIX}.*\.${id}\.${cvs_user}$/, readdir(DIR))); closedir(DIR); foreach (@files) { unlink "$TMPDIR/$_"; } } 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_file { local($filename, $dir, @files) = @_; 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 write_line { local($filename, $line) = @_; open(FILE, ">$filename") || die("Cannot open file $filename: $!\n"); print(FILE $line, "\n"); close(FILE); } sub append_line { local($filename, $line) = @_; open(FILE, ">>$filename") || die("Cannot open file $filename: $!\n"); print(FILE $line, "\n"); close(FILE); } sub read_line { local($filename) = @_; local($line); open(FILE, "<$filename") || die("Cannot open file $filename: $!\n"); $line = ; close(FILE); chomp($line); $line; } sub read_line_nodie { local($filename) = @_; local($line); open(FILE, "<$filename") || return (""); $line = ; close(FILE); chomp($line); $line; } sub read_file_lines { local($filename) = @_; local(@text) = (); open(FILE, "<$filename") || return (); while () { chomp; push(@text, $_); } close(FILE); @text; } sub read_file { local($filename, $leader) = @_; local(@text) = (); open(FILE, "<$filename") || return (); while () { chomp; push(@text, sprintf(" %-10s %s", $leader, $_)); $leader = ""; } close(FILE); @text; } sub read_logfile { local($filename, $leader) = @_; local(@text) = (); open(FILE, "<$filename") || die ("Cannot open log file $filename: $!\n"); while () { 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 () { 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 () { 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<>\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") { open(DIFF, "-|") || exec "$cvsbin/cvs", '-Qn', 'diff', "$difftype", "-r$prev_rev", "-r$rev", '--', $file; } } if ($SEND_DIFF eq "true") { while () { $diff .= $_; } close(DIFF); } $diff .= "\n\n"; } } &append_line($out, sprintf("%-9s%-12s%s%s", $rev, $delta, $rcsfile, $diff)); } } sub build_header { local($header); 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) = @_; return "xemacs-cvs\@xemacs.org"; # 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 = ) { # 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 = "$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 "; } # 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 "; } # 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"; } # 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 = "$subject"; } } return $subj; } sub mail_notification { local($addr_list, $log_subject, @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"; } $mail_to = join(", ", @{$addr_list}); if ($log_subject eq '') { print "Mailing the commit message to $mail_to (from $MAIL_FROM)\n"; } else { print "Mailing the commit message ($log_subject) to $mail_to (from $MAIL_FROM)\n"; } $ENV{'MAILUSER'} = $MAIL_FROM; # Commented out on hocus, so comment it out here. -kff # $ENV{'QMAILINJECT'} = 'f'; open(MAIL, "$MAIL_CMD -f$MAIL_FROM"); print MAIL "From: $MAIL_FROM\n"; print MAIL "To: $mail_to\n"; if ($log_subject eq '') { print MAIL "Subject: $SUBJECT_PRE by $cvs_user $subj\n\n"; } else { print MAIL "Subject: $SUBJECT_PRE by $cvs_user ($log_subject) $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; } ############################################################# # # Main Body # ############################################################ # # Setup environment # umask (002); # Connect to the database $cvsbin = "/coll/local/bin"; # # Initialize basic variables # $id = getpgrp(); $state = $STATE_NONE; $cvs_user = $ENV{'USER'} || getlogin || (getpwuid($<))[0] || sprintf("uid#%d",$<); @files = process_argv(@ARGV); @path = split('/', $files[0]); if ($#path == 0) { $dir = "."; } else { $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"); # # Map the repository directory to an email address for commitlogs to be sent # to. # $mlist = &mlist_map($files[0]); ########################## # # Check for a new directory first. This will always appear as a # single item in the argument list, and an empty log message. # if ($ARGV[0] =~ /New directory/) { $header = &build_header; @text = (); push(@text, $header); push(@text, ""); push(@text, " ".$ARGV[0]); &mail_notification([ $mlist ], @text); exit 0; } # # Iterate over the body of the message collecting information. # while () { chomp; # Drop the newline if (/^Revision\/Branch:/) { s,^Revision/Branch:,,; push (@branch_lines, split); next; } if (/^[ \t]+Tag: /) { s,^[ \t]+Tag: ,,; push (@branch_lines, split); next; } if (/^[ \t]+No tag$/) { 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 trailing space 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 ""); 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); } } # # Find the log file that matches this log message # for ($i = 0; ; $i++) { 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. # &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 (-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 } } # # 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 = (); @mlist_list = (); push(@text, $header); push(@text, ""); for ($i = 0; ; $i++) { 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, ""); } # # 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... } } # # See if the log has a Subject: line # my $log_subject = ""; foreach (@log_lines) { if (index($_, "Subject: ") == 0) { $log_subject = substr($_, 9); last; } } %mlist_hash = (); foreach (@mlist_list) { $mlist_hash{ $_ } = 1; } # # Mail out the notification. # &mail_notification([ keys(%mlist_hash) ], $log_subject, @text); &cleanup_tmpfiles; exit 0; --------------------------- end of inclusions ---------------------------