@42withyou
2015-03-10T08:02:33.000000Z
字数 6846
阅读 622
未分类
lingxi/hooks/post-commit
# commit 发送邮件通知REPOS="$1"REV="$2"# 可以把 log 编码搞定,但是 diff 中文乱码还没辙export LANG=zh_CN.GB2312/home/svn/hook-scripts/commit-email.pl "$REPOS" "$REV" -s "[SVN Commit]" -h justering.com techer@justering.com
# 其它项目复制一份就okcd /home/svncp lingxi/hooks/post-commit xxx/hooks/post-commit
#!/usr/bin/perl -w# Justering Customization Version# 2015/3/10# v1 将变量/格式 调整为svn服务器上的值# ====================================================================# 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 which mail contents should be appended# -r email_address : Set email Reply-To header to this email address# -s subject_prefix : Subject line prefix## ====================================================================# Copyright (c) 2000-2002 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 Encode;use strict;use Carp;use Getopt::Long;####################################################################### CONFIGURATION SECTION####################################################################### sendmail pathmy $sendmail = "/usr/sbin/sendmail";# svnlook pathmy $svnlook = "/usr/bin/svnlook";####################################################################### Initial setup/command-line handling# now, we see if there are any options included in the argument listmy $logfile = '';my $hostname = '';my $reply_to = '';my $subject_prefix = '';GetOptions('hostname=s' => \$hostname,'logfile=s' => \$logfile,'reply_to=s' => \$reply_to,'subject=s' => \$subject_prefix)or &usage;# check that there are enough remaining command line options&usage("$0: too few arguments") unless @ARGV > 2;# get the REPOS from the argumentsmy $repos = shift @ARGV;my @temp = split "/", $repos;my $repos_name = $temp[3];# get the REVISION from the argumentsmy $rev = shift @ARGV;# initialize the EMAIL_ADDRS to the remaining argumentsmy @email_addrs = @ARGV;####################################################################### Harvest data using svnlook# change into /tmp so that svnlook diff can create its .svnlook directorymy $tmp_dir = '/tmp';chdir($tmp_dir)or die "$0: cannot chdir `$tmp_dir': $!\n";# get the auther, date, and log from svnlookmy @svnlooklines = &read_from_process($svnlook, 'info', '-r', $rev, $repos);my $author = shift @svnlooklines;my $date = shift @svnlooklines;shift @svnlooklines;my @log = map { "$_\n" } @svnlooklines;# figure out what directories have changed (using svnlook)my @dirschanged = &read_from_process($svnlook, 'dirs-changed', '-r', $rev, $repos);my $rootchanged = 0;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)@svnlooklines = &read_from_process($svnlook, 'changed', '-r', $rev, $repos);# parse the changed nodesmy @adds = ();my @dels = ();my @mods = ();foreach my $line (@svnlooklines){my $path = '';my $code = '';# split the line up into the modification code (ignore propmods) and pathif ($line =~ /^(.). (.*)$/){$code = $1;$path = $2;}if ($code eq 'A') {push (@adds, " $path\n");}elsif ($code eq 'D') {push (@dels, " $path\n");}else {push (@mods, " $path\n");}}# get the diff from svnlookmy @difflines = &read_from_process($svnlook, 'diff', '-r', $rev, $repos);####################################################################### Mail headers# collapse the list of changed directoriesmy @commonpieces = ();my $commondir = '';if (($rootchanged == 0) and (scalar @commonpieces > 1)){my $firstline = shift (@dirschanged);push (@commonpieces, split ('/', $firstline));foreach my $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 = "$author r$rev\@$repos_name - $dirlist";}if ($subject_prefix =~ /\w/){$subject = "$subject_prefix $subject";}my $mail_from = $author;if ($hostname =~ /\w/){$mail_from = "$mail_from\@$hostname";}my @output;push (@output, "To: $userlist\n");push (@output, "From: $mail_from\n");push (@output, "Subject: $subject\n");push (@output, "Reply-to: $reply_to\n") if $reply_to;push (@output, "\n");# mail bodypush (@output, "Author: <b>$author</b>\n");push (@output, "Date: <b>$date</b>\n");push (@output, "Repos: <b>$repos</b>\n");push (@output, "New Revision: <b>$rev</b>\n");push (@output, "\n");push (@output, "###################################\n");push (@output, "Log:\n");push (@output, @log);push (@output, "\n");push (@output, "\n###################################\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, "\n###################################\n");push (@output, map { "$_\n" } @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;}exit 0;sub usage {warn "@_\n" if @_;die "usage: $0 [options] REPOS REVNUM email_address1 [email_address2 ... ]]\n","options are\n"," -h hostname Hostname to append to author for 'From:'\n"," -l logfile File to which mail contents should be appended\n"," -r email_address Set email Reply-To header to this email address\n"," -s subject_prefix Subject line prefix\n";}sub safe_read_from_pipe {unless (@_) {croak "$0: safe_read_from_pipe passed no arguments.\n";}print "Running @_\n";my $pid = open(SAFE_READ, '-|');unless (defined $pid) {die "$0: cannot fork: $!\n";}unless ($pid) {open(STDERR, ">&STDOUT") ordie "$0: cannot dup STDOUT: $!\n";exec(@_) ordie "$0: cannot exec `@_': $!\n";}my @output;while (<SAFE_READ>) {chomp;push(@output, $_);}close(SAFE_READ);my $result = $?;my $exit = $result >> 8;my $signal = $result & 127;my $cd = $result & 128 ? "with core dump" : "";if ($signal or $cd) {warn "$0: pipe from `@_' failed $cd: exit=$exit signal=$signal\n";}if (wantarray) {return ($result, @output);} else {return $result;}}sub read_from_process {unless (@_) {croak "$0: read_from_process passed no arguments.\n";}my ($status, @output) = &safe_read_from_pipe(@_);if ($status) {return ("$0: @_ failed with this output:", @output);} else {return @output;}}