From bf53562445aaeb7e85681f6a53e331c795cbb439 Mon Sep 17 00:00:00 2001 From: build Date: Mon, 12 Mar 2007 15:05:42 +0000 Subject: [PATCH] incorporated --size-limit feature --- tunings-myplc-devel/commit-email.pl | 181 ++++++++++++++++++++-------- 1 file changed, 128 insertions(+), 53 deletions(-) diff --git a/tunings-myplc-devel/commit-email.pl b/tunings-myplc-devel/commit-email.pl index 03e3b61..9d0ef92 100755 --- a/tunings-myplc-devel/commit-email.pl +++ b/tunings-myplc-devel/commit-email.pl @@ -26,6 +26,9 @@ # history and logs, available at http://subversion.tigris.org/. # ==================================================================== +# Modified by Branden Robinson, Peter Samuelson, and Mark Hymers +# September 2004 to add $size_limit support. + # Turn on warnings the best way depending on the Perl version. BEGIN { if ( $] >= 5.006_000) @@ -40,6 +43,9 @@ use Carp; ###################################################################### # Configuration section. +# Body of the message to be sent +my @body; + # Sendmail path. my $sendmail = "/usr/sbin/sendmail"; @@ -50,12 +56,12 @@ my $svnlook = "/usr/bin/svnlook"; # prints the entire contents of the file. If you want to save space # in the log and email messages by not printing the file, then set # $no_diff_deleted to 1. -my $no_diff_deleted = 0; +my $no_diff_deleted = 1; # By default, when a file is added to the repository, svnlook diff # prints the entire contents of the file. If you want to save space # in the log and email messages by not printing the file, then set # $no_diff_added to 1. -my $no_diff_added = 0; +my $no_diff_added = 1; # End of Configuration section. ###################################################################### @@ -102,6 +108,7 @@ my $rev; # Use the reference to the first project to populate. my $current_project = $project_settings_list[0]; +my $size_limit = 0; # This hash matches the command line option to the hash key in the # project. If a key exists but has a false value (''), then the @@ -111,7 +118,8 @@ my %opt_to_hash_key = ('--from' => 'from_address', '-l' => 'log_file', '-m' => '', '-r' => 'reply_to', - '-s' => 'subject_prefix'); + '-s' => 'subject_prefix', + '--size-limit' => ''); while (@ARGV) { @@ -136,14 +144,28 @@ while (@ARGV) } else { - # Here handle -m. - unless ($arg eq '-m') + # Handle -m and --size-limit here. + if ($arg eq '-m') + { + $current_project = &new_project; + $current_project->{match_regex} = $value; + push(@project_settings_list, $current_project); + } + elsif ($arg eq '--size-limit') { - die "$0: internal error: should only handle -m here.\n"; + $size_limit = $value; + # Validate the specified diff size limit. + if ($size_limit ne '' and $size_limit ne -1 and $size_limit !~ /^\d+$/) + { + die "$0: --size-limit takes only a positive integer or -1" + . " argument; \"$size_limit\" is neither\n"; + } + } + else + { + die "$0: internal error: should only handle -m and --size-limit" + . "here.\n"; } - $current_project = &new_project; - $current_project->{match_regex} = $value; - push(@project_settings_list, $current_project); } } elsif ($arg =~ /^-/) @@ -226,15 +248,22 @@ chdir($tmp_dir) or die "$0: cannot chdir `$tmp_dir': $!\n"; # Get the author, date, and log from svnlook. -my @svnlooklines = &read_from_process($svnlook, 'info', $repos, '-r', $rev); +my ($lines_size, @svnlooklines) = &read_from_process(0, $svnlook, 'info', + $repos, '-r', $rev); my $author = shift @svnlooklines; my $date = shift @svnlooklines; shift @svnlooklines; my @log = map { "$_\n" } @svnlooklines; +# Add header to body +push(@body, "Author: $author\n"); +push(@body, "Date: $date\n"); +push(@body, "New Revision: $rev\n"); +push(@body, "\n"); + # Figure out what directories have changed using svnlook. -my @dirschanged = &read_from_process($svnlook, 'dirs-changed', $repos, - '-r', $rev); +my ($dirs_size, @dirschanged) = &read_from_process(0, $svnlook, 'dirs-changed', + $repos, '-r', $rev); # Lose the trailing slash in the directory names if one exists, except # in the case of '/'. @@ -252,7 +281,9 @@ for (my $i=0; $i<@dirschanged; ++$i) } # Figure out what files have changed using svnlook. -@svnlooklines = &read_from_process($svnlook, 'changed', $repos, '-r', $rev); +my $look_size; +($look_size, @svnlooklines) = &read_from_process(0, $svnlook, 'changed', $repos, + '-r', $rev); # Parse the changed nodes. my @adds; @@ -285,13 +316,69 @@ foreach my $line (@svnlooklines) } } -# Get the diff from svnlook. -my @no_diff_deleted = $no_diff_deleted ? ('--no-diff-deleted') : (); -my @no_diff_added = $no_diff_added ? ('--no-diff-added') : (); -my @difflines = &read_from_process($svnlook, 'diff', $repos, - '-r', $rev, @no_diff_deleted, - @no_diff_added); +# Add the adds, dels and mods to the body of the message. +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); + } + +my @difflines; +my $diff_howto = "Use \"svn diff" . " -r " . ($rev - 1) . ":$rev\" to view" + . " diff.\n"; + +# Work out how many bytes we have available for the diff. +my $size_avail = 0; +if ($size_limit > 0) + { + my $bodylen = 0; + for (@body) { $bodylen += length($_); } + $size_avail = $size_limit - $bodylen; + + warn "sl= $size_limit -- sa = $size_avail"; + + if ($size_avail <= 0) + { + @difflines = ( "Diff skipped; message reached limit of $size_limit" + . " bytes with list of changed paths.\n$diff_howto" ); + } +} +# A $size_limit of -1 means we do not include a diff. +if ($size_limit ne -1) + { + # Get the diff from svnlook. + my @no_diff_deleted = $no_diff_deleted ? ('--no-diff-deleted') : (); + my @no_diff_added = $no_diff_added ? ('--no-diff-added') : (); + my $numbytes; + ($numbytes, @difflines) = &read_from_process($size_avail, $svnlook, 'diff', + $repos, '-r', $rev, + @no_diff_deleted, @no_diff_added); + # If the diff is larger than the remaining size limit, we must discard + # it. + if ($numbytes == -1) { + @difflines = ( "Including diff would make mail exceed size limit of" + . " $size_limit bytes.\n$diff_howto" ); + } + } +else + { + @difflines = ( $diff_howto ); + } + ###################################################################### # Modified directory name collapsing. @@ -342,33 +429,6 @@ if (!$rootchanged and @dirschanged > 1) } 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"); @@ -393,7 +453,6 @@ foreach my $project (@project_settings_list) 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}; @@ -425,7 +484,7 @@ foreach my $project (@project_settings_list) } my @head; - push(@head, "To: $to\n"); + push(@head, "To: $userlist\n"); push(@head, "From: $mail_from\n"); push(@head, "Subject: $subject\n"); push(@head, "Reply-to: $reply_to\n") if $reply_to; @@ -505,6 +564,9 @@ sub usage " -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", + " --size-limit limit Message size limit in bytes (positive\n", + " integer); if message exceeds limit, diff is\n", + " omitted; if set to -1, diff is never sent\n", "\n", "This script supports a single repository with multiple projects,\n", "where each project receives email only for commits that modify that\n", @@ -540,6 +602,10 @@ sub new_project } # Start a child process safely without using /bin/sh. +# +# We take a parameter, $limit, which if greater than zero will limit the +# amount we read -- this is a hack to avoid OOM errors. If we return +# $read_size == -1, we exceeded the limit. sub safe_read_from_pipe { unless (@_) @@ -547,6 +613,7 @@ sub safe_read_from_pipe croak "$0: safe_read_from_pipe passed no arguments.\n"; } + my $limit = shift @_; my $pid = open(SAFE_READ, '-|'); unless (defined $pid) { @@ -560,9 +627,17 @@ sub safe_read_from_pipe or die "$0: cannot exec `@_': $!\n"; } my @output; + my $read_size = 0; while () { s/[\r\n]+$//; + $read_size += length; + if (($limit > 0) and ($read_size > $limit)) + { + $read_size = -1; + @output = ("output size exceeds specified limit of " . $limit); + last; + } push(@output, $_); } close(SAFE_READ); @@ -576,7 +651,7 @@ sub safe_read_from_pipe } if (wantarray) { - return ($result, @output); + return ($result, $read_size, @output); } else { @@ -586,20 +661,20 @@ sub safe_read_from_pipe # 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. +# if it failed. Returns number of bytes read and the output. sub read_from_process { unless (@_) { croak "$0: read_from_process passed no arguments.\n"; } - my ($status, @output) = &safe_read_from_pipe(@_); - if ($status) + my ($status, $read_size, @output) = &safe_read_from_pipe(@_); + if ($read_size >= 0 and $status) { return ("$0: `@_' failed with this output:", @output); } else { - return @output; + return ($read_size, @output); } } -- 2.43.0