blob: 2d640d2aee13efed0d1febf6182dcc05e7358b60 [file] [log] [blame]
#!/usr/bin/perl -w
# ====================================================================
# commit-email.pl: send a commit email for commit REVISION in
# repository REPOS to some email addresses.
#
# Usage: commit-email.pl REPOS REVISION [OPTIONS] [EMAIL-ADDR ...]
#
# Options:
# -h hostname : Hostname to append to author for 'From:'
# -l logfile : File to while mail contents should be
# appended
# -s subject_prefix : Subject line prefix
#
# ====================================================================
# Copyright (c) 2000-2001 CollabNet. All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at http://subversion.tigris.org/license-1.html.
# If newer versions of this license are posted there, you may use a
# newer version instead, at your option.
#
# This software consists of voluntary contributions made by many
# individuals. For exact contribution history, see the revision
# history and logs, available at http://subversion.tigris.org/.
# ====================================================================
use strict;
######################################################################
# CONFIGURATION SECTION
######################################################################
# sendmail path
my $sendmail = "/usr/sbin/sendmail";
# svnlook path
my $svnlook = "/usr/local/bin/svnlook";
######################################################################
# Initial setup/command-line handling
# get the REPOS from the arguments
my $repos = shift @ARGV;
# get the REVISION from the arguments
my $rev = shift @ARGV;
# initialize the EMAIL_ADDRS to the remaining arguments
my @email_addrs = @ARGV;
# now, we see if there are any options included in the argument list
my $logfile = '';
my $hostname = '';
my $subject_prefix = '';
while (scalar @email_addrs)
{
my $option = shift @email_addrs;
if ($option eq '-h')
{
# found a hostname option
$hostname = shift @email_addrs;
}
elsif ($option eq '-l')
{
# found a logfile option
$logfile = shift @email_addrs;
}
elsif ($option eq '-s')
{
# found a subject prefix option
$subject_prefix = shift @email_addrs;
}
else
{
# not an option, put it back!
unshift @email_addrs, ($option);
last;
}
}
######################################################################
# Harvest data using svnlook
my @svnlooklines = ();
my @output = ();
my $line;
# get the auther, date, and log from svnlook
open (INPUT, "$svnlook $repos rev $rev info |")
or die ("Error running svnlook (info)");
@svnlooklines = <INPUT>;
close (INPUT);
my $author = shift @svnlooklines;
my $date = shift @svnlooklines;
shift @svnlooklines;
my @log = @svnlooklines;
chomp $author;
chomp $date;
# figure out what directories have changed (using svnlook)
open (INPUT, "$svnlook $repos rev $rev dirs-changed |")
or die ("Error running svnlook (changed)");
my @dirschanged = <INPUT>;
my $rootchanged = 0;
close (INPUT);
chomp @dirschanged;
grep
{
# lose the trailing slash if one exists (except in the case of '/')
$rootchanged = 1 if ($_ eq '/');
$_ =~ s/(.+)[\/\\]$/$1/;
}
@dirschanged;
# figure out what's changed (using svnlook)
open (INPUT, "$svnlook $repos rev $rev changed |")
or die ("Error running svnlook (changed)");
@svnlooklines = <INPUT>;
close (INPUT);
# parse the changed nodes
my @adds = ();
my @dels = ();
my @mods = ();
foreach $line (@svnlooklines)
{
my ($code, $path) = split (' ', $line);
if ($code eq 'A') {
push (@adds, " $path");
}
elsif ($code eq 'D') {
push (@dels, " $path");
}
else {
push (@mods, " $path");
}
}
# get the diff from svnlook
open (INPUT, "$svnlook $repos rev $rev diff |")
or die ("Error running svnlook (diff)");
my @difflines = <INPUT>;
close (INPUT);
######################################################################
# Mail headers
# collapse the list of changed directories
my @commonpieces = ();
my $commondir = '';
if (($rootchanged == 0) and (scalar @commonpieces > 1))
{
my $firstline = shift (@dirschanged);
push (@commonpieces, split ('/', $firstline));
foreach $line (@dirschanged)
{
my @pieces = ();
my $i = 0;
push (@pieces, split ('/', $line));
while (($i < scalar @pieces) and ($i < scalar @commonpieces))
{
if ($pieces[$i] ne $commonpieces[$i])
{
splice (@commonpieces, $i, (scalar @commonpieces - $i));
last;
}
$i++;
}
}
unshift (@dirschanged, $firstline);
if (scalar @commonpieces)
{
$commondir = join ('/', @commonpieces);
grep
{
s/^$commondir\/(.*)/$1/eg;
}
@dirschanged;
}
}
my $dirlist = join (' ', @dirschanged);
my $userlist = join (' ', @email_addrs);
my $subject;
if ($commondir ne '')
{
$subject = "rev $rev - in $commondir: $dirlist";
}
else
{
$subject = "rev $rev - $dirlist";
}
if ($subject_prefix =~ /\w/)
{
$subject = "$subject_prefix $subject";
}
my $mail_from = $author;
if ($hostname =~ /\w/)
{
$mail_from = "$mail_from\@$hostname";
}
push (@output, ("To: $userlist\n"));
push (@output, ("From: $mail_from\n"));
push (@output, ("Subject: $subject\n"));
push (@output, ("Reply-to: dev\@subversion.tigris.org\n"));
push (@output, ("\n"));
# mail body
push (@output, ("Author: $author\n"));
push (@output, ("Date: $date\n"));
push (@output, ("New Revision: $rev\n"));
push (@output, ("\n"));
if (scalar @adds)
{
@adds = sort @adds;
push (@output, ("Added:\n"));
push (@output, (@adds));
}
if (scalar @dels)
{
@dels = sort @dels;
push (@output, ("Removed:\n"));
push (@output, (@dels));
}
if (scalar @mods)
{
@mods = sort @mods;
push (@output, ("Modified:\n"));
push (@output, (@mods));
}
push (@output, ("Log:\n"));
push (@output, (@log));
push (@output, ("\n"));
push (@output, (@difflines));
# dump output to logfile (if its name is not empty)
if ($logfile =~ /\w/)
{
open (LOGFILE, ">> $logfile")
or die ("Error opening '$logfile' for append");
print LOGFILE @output;
close LOGFILE;
}
# open a pipe to 'sendmail'
if (($sendmail =~ /\w/) and ($userlist =~ /\w/))
{
open (SENDMAIL, "| $sendmail $userlist")
or die ("Error opening a pipe to sendmail");
print SENDMAIL @output;
close SENDMAIL;
}