[关闭]
@42withyou 2015-03-10T08:02:33.000000Z 字数 6846 阅读 622

svn post-commit hook

未分类


lingxi/hooks/post-commit

  1. # commit 发送邮件通知
  2. REPOS="$1"
  3. REV="$2"
  4. # 可以把 log 编码搞定,但是 diff 中文乱码还没辙
  5. export LANG=zh_CN.GB2312
  6. /home/svn/hook-scripts/commit-email.pl "$REPOS" "$REV" -s "[SVN Commit]" -h justering.com techer@justering.com
  1. # 其它项目复制一份就ok
  2. cd /home/svn
  3. cp lingxi/hooks/post-commit xxx/hooks/post-commit
  1. #!/usr/bin/perl -w
  2. # Justering Customization Version
  3. # 2015/3/10
  4. # v1 将变量/格式 调整为svn服务器上的值
  5. # ====================================================================
  6. # commit-email.pl: send a commit email for commit REVISION in
  7. # repository REPOS to some email addresses.
  8. #
  9. # Usage: commit-email.pl REPOS REVISION [OPTIONS] [EMAIL-ADDR ...]
  10. #
  11. # Options:
  12. # -h hostname : Hostname to append to author for 'From:'
  13. # -l logfile : File to which mail contents should be appended
  14. # -r email_address : Set email Reply-To header to this email address
  15. # -s subject_prefix : Subject line prefix
  16. #
  17. # ====================================================================
  18. # Copyright (c) 2000-2002 CollabNet. All rights reserved.
  19. #
  20. # This software is licensed as described in the file COPYING, which
  21. # you should have received as part of this distribution. The terms
  22. # are also available at http://subversion.tigris.org/license-1.html.
  23. # If newer versions of this license are posted there, you may use a
  24. # newer version instead, at your option.
  25. #
  26. # This software consists of voluntary contributions made by many
  27. # individuals. For exact contribution history, see the revision
  28. # history and logs, available at http://subversion.tigris.org/.
  29. # ====================================================================
  30. use Encode;
  31. use strict;
  32. use Carp;
  33. use Getopt::Long;
  34. ######################################################################
  35. # CONFIGURATION SECTION
  36. ######################################################################
  37. # sendmail path
  38. my $sendmail = "/usr/sbin/sendmail";
  39. # svnlook path
  40. my $svnlook = "/usr/bin/svnlook";
  41. ######################################################################
  42. # Initial setup/command-line handling
  43. # now, we see if there are any options included in the argument list
  44. my $logfile = '';
  45. my $hostname = '';
  46. my $reply_to = '';
  47. my $subject_prefix = '';
  48. GetOptions('hostname=s' => \$hostname,
  49. 'logfile=s' => \$logfile,
  50. 'reply_to=s' => \$reply_to,
  51. 'subject=s' => \$subject_prefix)
  52. or &usage;
  53. # check that there are enough remaining command line options
  54. &usage("$0: too few arguments") unless @ARGV > 2;
  55. # get the REPOS from the arguments
  56. my $repos = shift @ARGV;
  57. my @temp = split "/", $repos;
  58. my $repos_name = $temp[3];
  59. # get the REVISION from the arguments
  60. my $rev = shift @ARGV;
  61. # initialize the EMAIL_ADDRS to the remaining arguments
  62. my @email_addrs = @ARGV;
  63. ######################################################################
  64. # Harvest data using svnlook
  65. # change into /tmp so that svnlook diff can create its .svnlook directory
  66. my $tmp_dir = '/tmp';
  67. chdir($tmp_dir)
  68. or die "$0: cannot chdir `$tmp_dir': $!\n";
  69. # get the auther, date, and log from svnlook
  70. my @svnlooklines = &read_from_process($svnlook, 'info', '-r', $rev, $repos);
  71. my $author = shift @svnlooklines;
  72. my $date = shift @svnlooklines;
  73. shift @svnlooklines;
  74. my @log = map { "$_\n" } @svnlooklines;
  75. # figure out what directories have changed (using svnlook)
  76. my @dirschanged = &read_from_process($svnlook, 'dirs-changed', '-r', $rev, $repos);
  77. my $rootchanged = 0;
  78. grep
  79. {
  80. # lose the trailing slash if one exists (except in the case of '/')
  81. $rootchanged = 1 if ($_ eq '/');
  82. $_ =~ s/(.+)[\/\\]$/$1/;
  83. }
  84. @dirschanged;
  85. # figure out what's changed (using svnlook)
  86. @svnlooklines = &read_from_process($svnlook, 'changed', '-r', $rev, $repos);
  87. # parse the changed nodes
  88. my @adds = ();
  89. my @dels = ();
  90. my @mods = ();
  91. foreach my $line (@svnlooklines)
  92. {
  93. my $path = '';
  94. my $code = '';
  95. # split the line up into the modification code (ignore propmods) and path
  96. if ($line =~ /^(.). (.*)$/)
  97. {
  98. $code = $1;
  99. $path = $2;
  100. }
  101. if ($code eq 'A') {
  102. push (@adds, " $path\n");
  103. }
  104. elsif ($code eq 'D') {
  105. push (@dels, " $path\n");
  106. }
  107. else {
  108. push (@mods, " $path\n");
  109. }
  110. }
  111. # get the diff from svnlook
  112. my @difflines = &read_from_process($svnlook, 'diff', '-r', $rev, $repos);
  113. ######################################################################
  114. # Mail headers
  115. # collapse the list of changed directories
  116. my @commonpieces = ();
  117. my $commondir = '';
  118. if (($rootchanged == 0) and (scalar @commonpieces > 1))
  119. {
  120. my $firstline = shift (@dirschanged);
  121. push (@commonpieces, split ('/', $firstline));
  122. foreach my $line (@dirschanged)
  123. {
  124. my @pieces = ();
  125. my $i = 0;
  126. push (@pieces, split ('/', $line));
  127. while (($i < scalar @pieces) and ($i < scalar @commonpieces))
  128. {
  129. if ($pieces[$i] ne $commonpieces[$i])
  130. {
  131. splice (@commonpieces, $i, (scalar @commonpieces - $i));
  132. last;
  133. }
  134. $i++;
  135. }
  136. }
  137. unshift (@dirschanged, $firstline);
  138. if (scalar @commonpieces)
  139. {
  140. $commondir = join ('/', @commonpieces);
  141. grep
  142. {
  143. s/^$commondir\/(.*)/$1/eg;
  144. }
  145. @dirschanged;
  146. }
  147. }
  148. my $dirlist = join (' ', @dirschanged);
  149. my $userlist = join (' ', @email_addrs);
  150. my $subject = '';
  151. if ($commondir ne '')
  152. {
  153. $subject = "rev $rev - in $commondir: $dirlist";
  154. }
  155. else
  156. {
  157. $subject = "$author r$rev\@$repos_name - $dirlist";
  158. }
  159. if ($subject_prefix =~ /\w/)
  160. {
  161. $subject = "$subject_prefix $subject";
  162. }
  163. my $mail_from = $author;
  164. if ($hostname =~ /\w/)
  165. {
  166. $mail_from = "$mail_from\@$hostname";
  167. }
  168. my @output;
  169. push (@output, "To: $userlist\n");
  170. push (@output, "From: $mail_from\n");
  171. push (@output, "Subject: $subject\n");
  172. push (@output, "Reply-to: $reply_to\n") if $reply_to;
  173. push (@output, "\n");
  174. # mail body
  175. push (@output, "Author: <b>$author</b>\n");
  176. push (@output, "Date: <b>$date</b>\n");
  177. push (@output, "Repos: <b>$repos</b>\n");
  178. push (@output, "New Revision: <b>$rev</b>\n");
  179. push (@output, "\n");
  180. push (@output, "###################################\n");
  181. push (@output, "Log:\n");
  182. push (@output, @log);
  183. push (@output, "\n");
  184. push (@output, "\n###################################\n");
  185. if (scalar @adds)
  186. {
  187. @adds = sort @adds;
  188. push (@output, "Added:\n");
  189. push (@output, @adds);
  190. }
  191. if (scalar @dels)
  192. {
  193. @dels = sort @dels;
  194. push (@output, "Removed:\n");
  195. push (@output, @dels);
  196. }
  197. if (scalar @mods)
  198. {
  199. @mods = sort @mods;
  200. push (@output, "Modified:\n");
  201. push (@output, @mods);
  202. }
  203. push (@output, "\n###################################\n");
  204. push (@output, map { "$_\n" } @difflines);
  205. # dump output to logfile (if its name is not empty)
  206. if ($logfile =~ /\w/)
  207. {
  208. open (LOGFILE, ">> $logfile")
  209. or die ("Error opening '$logfile' for append");
  210. print LOGFILE @output;
  211. close LOGFILE;
  212. }
  213. # open a pipe to 'sendmail'
  214. if (($sendmail =~ /\w/) and ($userlist =~ /\w/))
  215. {
  216. open (SENDMAIL, "| $sendmail $userlist")
  217. or die ("Error opening a pipe to sendmail");
  218. print SENDMAIL @output;
  219. close SENDMAIL;
  220. }
  221. exit 0;
  222. sub usage {
  223. warn "@_\n" if @_;
  224. die "usage: $0 [options] REPOS REVNUM email_address1 [email_address2 ... ]]\n",
  225. "options are\n",
  226. " -h hostname Hostname to append to author for 'From:'\n",
  227. " -l logfile File to which mail contents should be appended\n",
  228. " -r email_address Set email Reply-To header to this email address\n",
  229. " -s subject_prefix Subject line prefix\n";
  230. }
  231. sub safe_read_from_pipe {
  232. unless (@_) {
  233. croak "$0: safe_read_from_pipe passed no arguments.\n";
  234. }
  235. print "Running @_\n";
  236. my $pid = open(SAFE_READ, '-|');
  237. unless (defined $pid) {
  238. die "$0: cannot fork: $!\n";
  239. }
  240. unless ($pid) {
  241. open(STDERR, ">&STDOUT") or
  242. die "$0: cannot dup STDOUT: $!\n";
  243. exec(@_) or
  244. die "$0: cannot exec `@_': $!\n";
  245. }
  246. my @output;
  247. while (<SAFE_READ>) {
  248. chomp;
  249. push(@output, $_);
  250. }
  251. close(SAFE_READ);
  252. my $result = $?;
  253. my $exit = $result >> 8;
  254. my $signal = $result & 127;
  255. my $cd = $result & 128 ? "with core dump" : "";
  256. if ($signal or $cd) {
  257. warn "$0: pipe from `@_' failed $cd: exit=$exit signal=$signal\n";
  258. }
  259. if (wantarray) {
  260. return ($result, @output);
  261. } else {
  262. return $result;
  263. }
  264. }
  265. sub read_from_process {
  266. unless (@_) {
  267. croak "$0: read_from_process passed no arguments.\n";
  268. }
  269. my ($status, @output) = &safe_read_from_pipe(@_);
  270. if ($status) {
  271. return ("$0: @_ failed with this output:", @output);
  272. } else {
  273. return @output;
  274. }
  275. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注