📄 commit-email.pl.in
字号:
my $i = 0;
while ($i < @pieces and $i < @commonpieces)
{
if ($pieces[$i] ne $commonpieces[$i])
{
splice(@commonpieces, $i, @commonpieces - $i);
last;
}
$i++;
}
}
unshift(@dirschanged, $firstline);
if (@commonpieces)
{
$commondir = join('/', @commonpieces);
my @new_dirschanged;
foreach my $dir (@dirschanged)
{
if ($dir eq $commondir)
{
$dir = '.';
}
else
{
$dir =~ s#^$commondir/##;
}
push(@new_dirschanged, $dir);
}
@dirschanged = @new_dirschanged;
}
}
my $dirlist = join(' ', @dirschanged);
######################################################################
# Assembly of log message.
# Put together the body of the log message.
my @body;
push(@body, "Author: $author\n");
push(@body, "Date: $date\n");
push(@body, "New Revision: $rev\n");
push(@body, "\n");
if (@adds)
{
@adds = sort @adds;
push(@body, "Added:\n");
push(@body, map { " $_\n" } @adds);
}
if (@dels)
{
@dels = sort @dels;
push(@body, "Removed:\n");
push(@body, map { " $_\n" } @dels);
}
if (@mods)
{
@mods = sort @mods;
push(@body, "Modified:\n");
push(@body, map { " $_\n" } @mods);
}
push(@body, "Log:\n");
push(@body, @log);
push(@body, "\n");
push(@body, map { /[\r\n]+$/ ? $_ : "$_\n" } @difflines);
# Go through each project and see if there are any matches for this
# project. If so, send the log out.
foreach my $project (@project_settings_list)
{
my $match_re = $project->{match_re};
my $match = 0;
foreach my $path (@dirschanged, @adds, @dels, @mods)
{
if ($path =~ $match_re)
{
$match = 1;
last;
}
}
next unless $match;
my @email_addresses = @{$project->{email_addresses}};
my $userlist = join(' ', @email_addresses);
my $to = join(', ', @email_addresses);
my $from_address = $project->{from_address};
my $hostname = $project->{hostname};
my $log_file = $project->{log_file};
my $reply_to = $project->{reply_to};
my $subject_prefix = $project->{subject_prefix};
my $subject;
if ($commondir ne '')
{
$subject = "r$rev - in $commondir: $dirlist";
}
else
{
$subject = "r$rev - $dirlist";
}
if ($subject_prefix =~ /\w/)
{
$subject = "$subject_prefix $subject";
}
my $mail_from = $author;
if ($from_address =~ /\w/)
{
$mail_from = $from_address;
}
elsif ($hostname =~ /\w/)
{
$mail_from = "$mail_from\@$hostname";
}
my @head;
push(@head, "To: $to\n");
push(@head, "From: $mail_from\n");
push(@head, "Subject: $subject\n");
push(@head, "Reply-to: $reply_to\n") if $reply_to;
### Below, we set the content-type etc, but see these comments
### from Greg Stein on why this is not a full solution.
#
# From: Greg Stein <gstein@lyra.org>
# Subject: Re: svn commit: rev 2599 - trunk/tools/cgi
# To: dev@subversion.tigris.org
# Date: Fri, 19 Jul 2002 23:42:32 -0700
#
# Well... that isn't strictly true. The contents of the files
# might not be UTF-8, so the "diff" portion will be hosed.
#
# If you want a truly "proper" commit message, then you'd use
# multipart MIME messages, with each file going into its own part,
# and labeled with an appropriate MIME type and charset. Of
# course, we haven't defined a charset property yet, but no biggy.
#
# Going with multipart will surely throw out the notion of "cut
# out the patch from the email and apply." But then again: the
# commit emailer could see that all portions are in the same
# charset and skip the multipart thang.
#
# etc etc
#
# Basically: adding/tweaking the content-type is nice, but don't
# think that is the proper solution.
push(@head, "Content-Type: text/plain; charset=UTF-8\n");
push(@head, "Content-Transfer-Encoding: 8bit\n");
push(@head, "\n");
if ($sendmail =~ /\w/ and @email_addresses)
{
# Open a pipe to sendmail.
my $command = "$sendmail $userlist";
if (open(SENDMAIL, "| $command"))
{
print SENDMAIL @head, @body;
close SENDMAIL
or warn "$0: error in closing `$command' for writing: $!\n";
}
else
{
warn "$0: cannot open `| $command' for writing: $!\n";
}
}
# Dump the output to logfile (if its name is not empty).
if ($log_file =~ /\w/)
{
if (open(LOGFILE, ">> $log_file"))
{
print LOGFILE @head, @body;
close LOGFILE
or warn "$0: error in closing `$log_file' for appending: $!\n";
}
else
{
warn "$0: cannot open `$log_file' for appending: $!\n";
}
}
}
exit 0;
sub usage
{
warn "@_\n" if @_;
die "usage: $0 REPOS REVNUM [[-m regex] [options] [email_addr ...]] ...\n",
"options are\n",
" --from email_address Email address for 'From:' (overrides -h)\n",
" -h hostname Hostname to append to author for 'From:'\n",
" -l logfile Append mail contents to this log file\n",
" -m regex Regular expression to match committed path\n",
" -r email_address Email address for 'Reply-To:'\n",
" -s subject_prefix Subject line prefix\n",
"\n",
"This script supports a single repository with multiple projects,\n",
"where each project receives email only for commits that modify that\n",
"project. A project is identified by using the -m command line\n",
"with a regular expression argument. If a commit has a path that\n",
"matches the regular expression, then the entire commit matches.\n",
"Any of the following -h, -l, -r and -s command line options and\n",
"following email addresses are associated with this project. The\n",
"next -m resets the -h, -l, -r and -s command line options and the\n",
"list of email addresses.\n",
"\n",
"To support a single project conveniently, the script initializes\n",
"itself with an implicit -m . rule that matches any modifications\n",
"to the repository. Therefore, to use the script for a single\n",
"project repository, just use the other comand line options and\n",
"a list of email addresses on the command line. If you do not want\n",
"a project that matches the entire repository, then use a -m with a\n",
"regular expression before any other command line options or email\n",
"addresses.\n";
}
# Return a new hash data structure for a new empty project that
# matches any modifications to the repository.
sub new_project
{
return {email_addresses => [],
from_address => '',
hostname => '',
log_file => '',
match_regex => '.',
reply_to => '',
subject_prefix => ''};
}
# Start a child process safely without using /bin/sh.
sub safe_read_from_pipe
{
unless (@_)
{
croak "$0: safe_read_from_pipe passed no arguments.\n";
}
my $pid = open(SAFE_READ, '-|');
unless (defined $pid)
{
die "$0: cannot fork: $!\n";
}
unless ($pid)
{
open(STDERR, ">&STDOUT")
or die "$0: cannot dup STDOUT: $!\n";
exec(@_)
or die "$0: cannot exec `@_': $!\n";
}
my @output;
while (<SAFE_READ>)
{
s/[\r\n]+$//;
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;
}
}
# Use safe_read_from_pipe to start a child process safely and return
# the output if it succeeded or an error message followed by the output
# if it failed.
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;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -