Last active
August 29, 2015 14:03
-
-
Save realdadfish/3cd8ca0778eb20026587 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
# | |
# ATTENTION: In addition to Net::Jabber you also need to apply | |
# this patch http://toroid.org/ams/etc/net-xmpp-virtualhost-support | |
# to let this script connect to a jabber server independent from | |
# the domain you gave it. | |
# | |
# Then, symlink this script in each git repository you want to | |
# receive notifications for (i.e. ln -s path/to/post-receive.pl repo.git/hooks/post-receive) | |
# and configure the branches (".*" as catch-all works) and chat ID | |
# like this: | |
# | |
# git config hooks.notify.repo 'some identifier' | |
# git config hooks.notify.branches 'master next' | |
# git config hooks.notify.chat '[email protected]' | |
# | |
# Thats it, have fun. | |
# Thomas. | |
# | |
# Author: Thomas Keller <[email protected]> | |
# Original author: Abhijit Menon-Sen <[email protected]> | |
# | |
use Net::Jabber; | |
my $servername = '<server-name-or-ip>'; | |
my $JID = '<jabber-id>'; | |
my $password = '<password>'; | |
# cut off large commit messages after so many characters | |
my $charlimit = 1000; | |
# only report so and so many commits per ref at once | |
my $commitlimit = 5; | |
my $repo = qx(git config hooks.notify.repo); | |
chomp $repo; | |
my @branches = split /,*\s+/, qx(git config hooks.notify.branches); | |
my $chat = qx(git config hooks.notify.chat); | |
chomp $chat; | |
my $branches = join( "|", @branches ) || "master"; | |
# Read "oldsha1 newsha1 refname" lines from stdin and convert the | |
# relevant ones into summary messages. | |
my @changes; | |
while ( <> ) { | |
chomp; | |
my ( $old, $new, $ref ) = split / /; | |
$ref =~ s!refs/heads/!!; | |
next unless $ref =~ /$branches/; | |
# skip branch deletions | |
next if $new =~ /0{40}/; | |
my $range = "$old..$new"; | |
# new refs are pushed with zero'd $old and that doesn't like git log | |
$range = "-1 $new" if $old =~ /0{40}/; | |
my $s = qx(git log --no-merges --reverse --find-copies-harder --raw $range); | |
$s =~ s/^:.*?(\w+\t)/$1/gsm; | |
push @changes, [ $ref, $s ]; | |
} | |
exit unless @changes; | |
# since we need to send messages slowly to servers like ejabberd | |
# to avoid having parts of them eaten up, we fork and exit here | |
# so the pushing user doesn't have to wait for us. | |
fork and exit; | |
# Send the notification messages to each recipient. | |
my ( $username, $hostname ) = split /@/, $JID; | |
my ( $chatroom, $chatdomain) = split /@/, $chat; | |
my $client = new Net::Jabber::Client (); | |
$client->Connect( hostname => $hostname, servername => $servername, srv => '_xmpp-client._tcp' ) | |
or die "Cannot connect to jabber server for $hostname ($servername): $!\n"; | |
my @r = $client->AuthSend( | |
username => $username, | |
password => $password, | |
resource => "gitguy" | |
); | |
die "Cannot authenticate as $JID (@r)\n" if $r[0] ne "ok"; | |
$client->MUCJoin( | |
room => $chatroom, | |
server => $chatdomain, | |
nick => "gitguy" | |
); | |
foreach my $c ( @changes ) { | |
my ( $ref, $s ) = @$c; | |
sendMessage($client, $chat, "Changes pushed to branch $repo/$ref"); | |
my @commits = split /(?=\n\ncommit)/, $s; | |
for my $i (0 .. $commitlimit - 1) { | |
$cm = $commits[$i]; | |
$cm =~ s/^\s+|\s+$//g; | |
$cm = substr($cm, 0, $charlimit) . "..." if length($cm) > $charlimit; | |
sendMessage($client, $chat, $cm); | |
} | |
$left = $#commits - $commitlimit; | |
if ($left > 0) { | |
sendMessage($client, $chat, "($left more commits not shown)"); | |
} | |
} | |
$client->Disconnect(); | |
sub sendMessage { | |
$client = $_[0]; | |
$chat = $_[1]; | |
$text = $_[2]; | |
my $msg = new Net::Jabber::Message (); | |
$msg->SetMessage( | |
type => 'groupchat', | |
to => $chat, | |
body => $text | |
); | |
$client->Send( $msg ); | |
# wait time after each message send 0.5s | |
# couldn't get more messages through reliably | |
# with a value below this | |
select(undef, undef, undef, 0.5); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment