taskd/mail.sh: Optional fifth parameter is email sender; set up in ref_change()
[girocco.git] / Girocco / Notify.pm
blob27355949d559591105dcf39d7789120e35187c31
1 package Girocco::Notify;
3 use strict;
4 use warnings;
6 BEGIN {
7 use Girocco::Config;
8 use JSON;
9 use LWP::UserAgent;
13 # This Perl code creates json payload within post-receive hook.
15 sub json_commit {
16 my ($proj, $commit) = @_;
18 my @gcmd = ($Girocco::Config::git_bin, '--git-dir='.$proj->{path});
19 my $fd;
21 open $fd, '-|', @gcmd, 'log', '-1', '--pretty=format:%ae %an%n%ai%n%s%n%n%b', $commit
22 or die "cannot do git log: $! $?";
23 my @l = <$fd>;
24 chomp @l;
25 close $fd;
26 my ($ae, $an) = ($l[0] =~ /^(.*?) (.*)$/);
27 my ($ai) = $l[1];
28 my $msg = join("\n", splice(@l, 2));
29 # Up to three trailing newlines in case of no body.
30 chomp $msg; chomp $msg; chomp $msg;
32 my ($rf, $af, $mf) = ([], [], []);
33 open $fd, '-|', @gcmd, 'diff-tree', '--name-status', '-r', "$commit^", $commit
34 or die "cannot do git diff-tree: $! $?";
35 while (<$fd>) {
36 chomp;
37 my ($s, $file) = split(/\t/, $_);
38 if ($s eq 'M') {
39 push @$mf, $file;
40 } elsif ($s eq 'A') {
41 push @$af, $file;
42 } elsif ($s eq 'R') {
43 push @$rf, $file;
46 close $fd;
48 return {
49 "removed" => $rf,
50 "message" => $msg,
51 "added" => $af,
52 "timestamp" => $ai,
53 "modified" => $mf,
54 "url" => $Girocco::Config::gitweburl."/".$proj->{name}.".git/commit/".$commit,
55 "author" => { "name" => $an, "email" => $ae },
56 "id" => $commit
57 };
60 sub json {
61 my ($url, $proj, $ref, $oldrev, $newrev) = @_;
63 my $commits = [];
65 foreach my $commit (get_commits($proj, $ref, $oldrev, $newrev)) {
66 push @$commits, json_commit($proj, $commit);
69 my $payload = encode_json {
70 "before" => $oldrev,
71 "after" => $newrev,
72 "ref" => $ref,
74 "repository" => {
75 "name" => $proj->{name},
76 # Girocco extension: full_name is full project name,
77 # equivalent to GitHub's "owner[name]/name".
78 "full_name" => $proj->{name}.".git",
80 "url" => $Girocco::Config::gitweburl.'/'.$proj->{name}.".git",
81 # Girocco extension: Pull URL.
82 "pull_url" => $Girocco::Config::gitpullurl.'/'.$proj->{name}.".git",
84 "owner" => { "name" => "", "email" => $proj->{email} }
87 "commits" => $commits
90 my $ua = LWP::UserAgent->new;
91 $ua->timeout(5);
92 $ua->post($url, { payload => $payload });
96 sub get_commits {
97 my ($proj, $ref, $oldrev, $newrev) = @_;
99 my @gcmd = ($Girocco::Config::git_bin, '--git-dir='.$proj->{path});
100 my $fd;
102 open $fd, '-|', @gcmd, 'for-each-ref', '--format=%(refname)', 'refs/heads/'
103 or die "cannot do git for-each-ref: $! $?";
104 my @refs = grep { $_ ne $ref } <$fd>;
105 chomp @refs;
106 close $fd;
108 my @revlims;
109 if (@refs) {
110 print "--not @refs\n";
111 open $fd, '-|', @gcmd, 'rev-list', '--not', @refs
112 or die "cannot do git rev-list for revlims: $! $?";
113 @revlims = <$fd>;
114 chomp @revlims;
115 close $fd;
118 my $revspec = (($oldrev =~ /^0+$/) ? $newrev : "$oldrev..$newrev");
119 open $fd, '-|', @gcmd, 'rev-list', @revlims, $revspec
120 or die "cannot do git rev-list: $! $?";
121 my @revs = <$fd>;
122 chomp @revs;
123 close $fd;
125 return @revs;
129 sub ref_change {
130 my ($proj, $user, $ref, $oldrev, $newrev) = @_;
132 chdir($proj->{path});
134 # First, possibly send out various mails
135 if ($proj->{notifymail}) {
136 my $sender;
137 if ($user) {
138 if ($user->{name} eq 'mob') {
139 $sender = "The Mob User <$proj->{email}>";
140 } else {
141 $sender = "$user->{name} <$user->{email}>";
143 } else {
144 $sender = "$proj->{name} <$proj->{email}>";
146 system($Girocco::Config::basedir.'/taskd/mail.sh',
147 "$ref", "$oldrev", "$newrev", $proj->{name},
148 $sender)
149 and warn "mail.sh failed";
152 # Next, send JSON packet to given URL if enabled.
153 if ($proj->{notifyjson}) {
154 json($proj->{notifyjson}, $proj, $ref, $oldrev, $newrev);