#!/usr/bin/perl # $Id: commit-email,v 1.11 2006/03/18 22:25:37 hudson Exp $ # # Interface CVS commits into bugzilla. # THIS WILL BREAK IF THE FILENAMES CONTAIN SPACES! # Don't do that! # # In CVSROOT/loginfo, add the following: # DEFAULT $CVSROOT/CVSROOT/bugzilla-email bugs@example.com,dev-list@example.com %{sVvt} # # Commit messages should have: # BUG: 471,421 fixed # SUMMARY: Replaced foo widget with bar # # Then the full commit message # use warnings; use strict; use MIME::Entity; my $usage = <<""; Usage: $0 mailing_dest 'dir files,old,new,tag...' # Command line arguments my $mail_dest = shift or die $usage; my $file_list = shift or die $usage; # Parameters that should be configurable my $return_address = 'bugs@osresearch.net'; my $RCSDIFF = '/usr/bin/rcsdiff'; my $SENDMAIL = '/usr/lib/sendmail'; my $user = `whoami`; my $CVSROOT = $ENV{CVSROOT} or die "$0: No CVS root?\n"; # Read the commit message from stdin my $msg = do { local $/ ; }; # Parse out the bug id and summary my ($bugs) = $msg =~ /^BUG:\s+(.*?)\s*$/mg; my ($summary) = $msg =~ /^SUMMARY:\s+(.*)\s+$/mg; $bugs ||= 'NEW'; $summary ||= $file_list; # Remove any headers from the body and any blank lines at the start $msg =~ s/^(BUG|SUMMARY):.*$//mg; $msg =~ s/^\s*//; # Build the subject line my $subject = "[Bug $bugs] $summary"; my $mime = MIME::Entity->build( Type => 'multipart/mixed', 'Reply-To' => $return_address, From => $user, To => $mail_dest, Subject => $subject, ); my $patch; my @added; my @removed; my @changed; # Check for adding a subdirectory if( $file_list =~ /^(.*) - New directory$/ ) { my $new_dir = $1; push @added, "$new_dir (Directory)"; goto done; } my ($repository,@files) = split / /, $file_list; for(@files) { my ($file,$old,$new,$tag) = split /,/; if( $new eq 'NONE' ) { # This file has been removed. Just note it push @removed, $file; next; } if( $old eq 'NONE' ) { # This is a new file. Note it and add a patch to create it # How to produce the right diff? push @added, $file; next; } push @changed, [ $file, $old, $new, $tag ]; # Generate the diff from old to new. # This is DANGEROUS since a specially crafted file name could get # executed. Why doesn't open() have a system() like argument list? open DIFF, "$RCSDIFF -r$old -r$new -u $CVSROOT/$repository/$file |" or warn "$RCSDIFF $file: Unable to open? $!\n" and next; $patch .= do { undef $/ ; }; close DIFF or warn "$RCSDIFF $file: Close failed? $!\n"; } done: ############### # # Add our commit message to the body. # CVS prepends the message with the added/modified/changed notices # # Generate the parts of the mail and send them $mime->attach( Type => 'text/plain', Data => $msg, ); $mime->attach( Type => 'text/plain', Filename => "$file_list.patch", Data => $patch, ) if $patch; # Send it! $mime->smtpsend; #open MAIL, "| /usr/lib/sendmail -t -oi -oem" # or die "Sendmail: $!\n"; #$mime->print( \*MAIL ); #close MAIL;