{"thread":{"id":"22943","subject":"Doubts about hot to properly write post-receive hook to send an email with a newly added patch","startedAt":"2010-03-06T15:55:35Z","lastAt":"2010-03-06T15:55:35Z","messageCount":1,"participants":["Mauro Carvalho Chehab"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"136337","messageId":"4B927AF7.2060708@redhat.com","threadId":"22943","inReplyTo":null,"subject":"Doubts about hot to properly write post-receive hook to send an email with a newly added patch","fromName":"Mauro Carvalho Chehab","fromEmail":"mchehab@redhat.com","sentAt":"2010-03-06T15:55:35Z","receivedAt":"2010-03-06T15:55:35Z","isPatch":false,"sender":{"key":"mchehab@redhat.com","avatar":null},"body":"I'm needing a post-receive hook that would send a copy to the patch author,\nto the C/C recipients and to the ones that signed/acked/tested a patch.\n\nThe idea is to announce to the patch author and to the relevant parts that\na new patch were accepted on my -git tree, showing the patch/comments\nafter its addition at the tree.\n\nSo, I wrote a perl script for this (see enclosed) for it.\n\nUnfortunately, I just found a serious bug: when I merge back from upstream, \nit sends a message also for all patch authors from upstream!\n\nWhat's the better way to identify what patches came from a merge tree,\nin order to remove them from the mailbomb queue?\n\nCheers,\nMauro\n\n\n---\n\n#!/usr/bin/perl\n#\n# License: GPLv2\n#\nuse warnings;\nuse strict;\nuse Sys::Hostname;\n\n$ENV{PATH} = '/usr/local/bin:/usr/bin:/bin';\n\nmy $debug = 0;\nmy $mail_cmd = \"/usr/sbin/sendmail\";\n#\n# Retrieve all info from git config\n#\nmy $project_name = qx(git config mailnotify.project) || \"untitled\";\nmy $smtp_server  = qx(git config mailnotify.smtpserver) || \"localhost\";\nmy $from         = qx(git config mailnotify.from) || sprintf('%s@%s', $project_name, hostname());\nmy $to           = qx(git config mailnotify.to) || die(\"No mail To:\");\nmy $cfgcc        = qx(git config mailnotify.cc) || \"\";\nmy $replyto      = qx(git config mailnotify.replyto) || \"\";\nmy $maxsize      = qx(git config mailnotify.maxsize) || \"\";\nmy $url          = qx(git config mailnotify.url) || \"\";\n\n$project_name =~ s/\\s+$//;\n$smtp_server =~ s/\\s+$//;\n$from =~ s/\\s+$//;\n$to =~ s/\\s+$//;\n$cfgcc =~ s/\\s+$//;\n$replyto =~ s/\\s+$//;\n$maxsize =~ s/\\s+$//;\n$url =~ s/\\s+$//;\n\n#\n# Get old revision, new revision and branch/tag name\n#\nmy ($oldrev, $newrev, $refname);\nif (scalar(@ARGV)) {\n\t($oldrev, $newrev, $refname) = @ARGV[ 0 .. 2 ];\n} else {\n\tmy $args = <STDIN>;\n\t($oldrev, $newrev, $refname) = split(\" \", $args);\n}\nprintf(STDERR \"args:%s %s %s\\n\", $oldrev, $newrev, $refname) if ($debug);\n\n#\n# Get the complete revision name\n#\n$oldrev = qx(git rev-parse $oldrev);\n$newrev = qx(git rev-parse $newrev);\n\nchomp($oldrev);\nchomp($newrev);\nchomp($refname);\n\nif ($debug) {\n    printf(STDERR \"oldrev:%s\\n\", $oldrev);\n    printf(STDERR \"newrev:%s\\n\", $newrev);\n    printf(STDERR \"refname:%s\\n\", $refname);\n}\n\n#\n# Get branch name\n#\nmy $branch = (split(\"/\", $refname))[-1];\n\n#\n# get revisions\n#\nopen REF, \"git rev-list $oldrev..$newrev|\";\nwhile (<REF>) {\n\tmy $ref= $_;\n\n\tmy $author = qx(git log -1 --pretty=format:\"%aN\" $ref);\n\tmy $data = qx(git log -1 --pretty=format:\"%aD\" $ref);\n\tmy $subject = qx(git log -1 --pretty=format:\"%s\" $ref);\n\t$subject = sprintf(\"[git:%s/%s] %s\", $project_name, $branch, $subject);\n\n\tmy %copy;\n\tmy $log = \"\";\n\topen IN, \"git log -1 --pretty=email --stat $ref|\";\n\n\t# Discard initial From line\n\tmy $dumb=<IN>;\n\n\twhile (<IN>) {\n\t\tnext if (m/^Subject: /);\n\t\tnext if (m/^Date: /);\n\t\t$log .= $_;\n\n\t\tif (m/(signed-off-by|author|from|accepted-by|tested-by|thanks-to|reviewed-by|cc|acked-by):\\s*(.*)\\s*\\n$/i) {\n\t\t\tmy $sob=$2;\n\t\t\tif ($sob =~ m/\\s*(.*)\\s*<(.*)>/) {\n\t\t\t\tmy $name = $1;\n\t\t\t\tmy $email = $2;\n\t\t\t\t$name =~ s/^\\s+//;\n\t\t\t\t$name =~ s/\\s+$//;\n\t\t\t\t$name =~ s/^\\\"(.*)\\\"$/$1/;\n\t\t\t\t$name=\"\" if ($name =~ m/\\@/);\n\t\t\t\t$copy{\"$email\"} = $name;\n\t\t\t} elsif ($sob =~ m/([^\\s]+\\@[^\\s+]+)/) {\n\t\t\t\tmy $email = $1;\n\t\t\t\t$copy{\"$email\"} = \"\" if (!exists($copy{\"$email\"}));\n\t\t\t}\n\t\t}\n\t}\n\tclose IN;\n\n\tmy $cc = $cfgcc;\n\twhile (my ($key,$value) = each(%copy) ) {\n\t\tnext if ($key =~ m/stable\\@kernel.org/);\n\t\tif ($value ne \"\") {\n\t\t\t$cc .= \", $value <$key>\";\n\t\t} else {\n\t\t\t$cc .= \", $key\";\n\t\t}\n\t}\n\t$cc =~ s/^, //;\n\t$cc =~ s/\\s+/ /g;\n\n\tmy $diff = qx(git show --pretty=format:\"\" $ref);\n\n\tmy $header = \"Subject: $subject\\nFrom: Patch from $author <$from>\\nTo: $to\\nData: $data\\n\";\n\t$header .= \"Cc: $cc\\n\" if ($cc);\n\n\tif ($replyto) {\n\t\t$header .= \"Mail-followup-to: $replyto\\n\";\n\t\t$header .= \"Forward-to: $replyto\\n\";\n\t\t$header .= \"Reply-to: $replyto\\n\";\n\t}\n\n\tmy $email = \"$header\\n$log\\n---\\n\\n\";\n\t$email   .= \"$url?a=commitdiff;h=$ref\" if ($url);\n\tif ($maxsize && length($diff) > $maxsize) {\n\t\t$diff = \"<diff discarded since it is too big>\\n\"\n\t}\n\t$email .= $diff;\n\n\tif (!$debug) {\n\t\topen(MAIL, \"| $mail_cmd -t\");\n\t\tprint MAIL $email;\n\t\tclose MAIL;\n\t} else {\n\t\tprint $email;\n\t}\n}\n\nclose REF;\n"}]}