mirror of
https://github.com/monitoring-plugins/monitoring-plugins.git
synced 2026-06-08 16:26:23 -04:00
git-notify: Don't generate duplicate notifications
Never notify on a given commit more than once, even if it's referenced via multiple branch heads. We make sure this won't happen simply by maintaining a list of commits we notified about. The file path used for saving this list can be specified using the new "-t" option. (The contrib/hooks/post-receive-email script distributed with Git tries hard to avoid such a list, but it doesn't get the necessary magic right.)
This commit is contained in:
parent
a6b3296897
commit
af5e252846
1 changed files with 61 additions and 0 deletions
|
|
@ -3,6 +3,7 @@
|
|||
# Tool to send git commit notifications
|
||||
#
|
||||
# Copyright 2005 Alexandre Julliard
|
||||
# Copyright 2009 Nagios Plugins Development Team
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
|
|
@ -19,6 +20,7 @@
|
|||
# -n max Set max number of individual mails to send
|
||||
# -r name Set the git repository name
|
||||
# -s bytes Set the maximum diff size in bytes (-1 for no limit)
|
||||
# -t file Set the file to use for reading and saving state
|
||||
# -u url Set the URL to the gitweb browser
|
||||
# -i branch If at least one -i is given, report only for specified branches
|
||||
# -x branch Exclude changes to the specified branch from reports
|
||||
|
|
@ -27,6 +29,7 @@
|
|||
|
||||
use strict;
|
||||
use open ':utf8';
|
||||
use Fcntl ':flock';
|
||||
use Encode 'encode';
|
||||
use Cwd 'realpath';
|
||||
|
||||
|
|
@ -76,6 +79,9 @@ my @include_list = split /\s+/, git_config( "notify.include" ) || "";
|
|||
# branches to exclude
|
||||
my @exclude_list = split /\s+/, git_config( "notify.exclude" ) || "";
|
||||
|
||||
# the state file we use (can be changed with the -t option)
|
||||
my $state_file = git_config( "notify.statefile" ) || "/var/tmp/git-notify.state";
|
||||
|
||||
# Extra options to git rev-list
|
||||
my @revlist_options;
|
||||
|
||||
|
|
@ -87,6 +93,7 @@ sub usage()
|
|||
print " -n max Set max number of individual mails to send\n";
|
||||
print " -r name Set the git repository name\n";
|
||||
print " -s bytes Set the maximum diff size in bytes (-1 for no limit)\n";
|
||||
print " -t file Set the file to use for reading and saving state\n";
|
||||
print " -u url Set the URL to the gitweb browser\n";
|
||||
print " -i branch If at least one -i is given, report only for specified branches\n";
|
||||
print " -x branch Exclude changes to the specified branch from reports\n";
|
||||
|
|
@ -127,6 +134,59 @@ sub git_rev_list(@)
|
|||
return $revlist;
|
||||
}
|
||||
|
||||
# append the given commit hashes to the state file
|
||||
sub save_commits($)
|
||||
{
|
||||
my $commits = shift;
|
||||
|
||||
open STATE, ">>", $state_file or die "Cannot open $state_file: $!";
|
||||
flock STATE, LOCK_EX or die "Cannot lock $state_file";
|
||||
print STATE "$_\n" for @$commits;
|
||||
flock STATE, LOCK_UN or die "Cannot unlock $state_file";
|
||||
close STATE or die "Cannot close $state_file: $!";
|
||||
}
|
||||
|
||||
# for the given range, return the new hashes and append them to the state file
|
||||
sub get_new_commits($$)
|
||||
{
|
||||
my ($old_sha1, $new_sha1) = @_;
|
||||
my ($seen, @args);
|
||||
my $newrevs = [];
|
||||
|
||||
@args = ( "^$old_sha1" ) unless $old_sha1 eq '0' x 40;
|
||||
push @args, $new_sha1, @exclude_list;
|
||||
|
||||
my $revlist = git_rev_list(@args);
|
||||
|
||||
if (not -e $state_file) # initialize the state file with all hashes
|
||||
{
|
||||
save_commits(git_rev_list("--all", "--full-history"));
|
||||
return $revlist;
|
||||
}
|
||||
|
||||
open STATE, $state_file or die "Cannot open $state_file: $!";
|
||||
flock STATE, LOCK_SH or die "Cannot lock $state_file";
|
||||
while (<STATE>)
|
||||
{
|
||||
chomp;
|
||||
die "Invalid commit: $_" if not /^[0-9a-f]{40}$/;
|
||||
$seen->{$_} = 1;
|
||||
}
|
||||
flock STATE, LOCK_UN or die "Cannot unlock $state_file";
|
||||
close STATE or die "Cannot close $state_file: $!";
|
||||
|
||||
# FIXME: if another git-notify process reads the $state_file at *this*
|
||||
# point, that process might generate duplicates of our notifications.
|
||||
|
||||
save_commits($revlist);
|
||||
|
||||
foreach my $commit (@$revlist)
|
||||
{
|
||||
push @$newrevs, $commit unless $seen->{$commit};
|
||||
}
|
||||
return $newrevs;
|
||||
}
|
||||
|
||||
# truncate the given string if it exceeds the specified number of characters
|
||||
sub truncate_str($$)
|
||||
{
|
||||
|
|
@ -217,6 +277,7 @@ sub parse_options()
|
|||
elsif ($arg eq '-n') { $max_individual_notices = shift @ARGV; }
|
||||
elsif ($arg eq '-r') { $repos_name = shift @ARGV; }
|
||||
elsif ($arg eq '-s') { $max_diff_size = shift @ARGV; }
|
||||
elsif ($arg eq '-t') { $state_file = shift @ARGV; }
|
||||
elsif ($arg eq '-u') { $gitweb_url = shift @ARGV; }
|
||||
elsif ($arg eq '-i') { push @include_list, shift @ARGV; }
|
||||
elsif ($arg eq '-x') { push @exclude_list, shift @ARGV; }
|
||||
|
|
|
|||
Loading…
Reference in a new issue