svn email code review的简单Perl脚本
?
?? ?对于很多没有使用code review工具的软件公司来说,code review是个头疼的事,很多是定期开会review,这种方式本人一直非常反对,一个项目每个人改自己的那部分,几千行代码开个一小时会就能发现问题? 所以还是应该每次commit code时review一下,以保证代码的质量。
?
?? ?本人写了一个200行的Perl脚本,运行与Linux下,用于svn commit code的post review(post review 不同于pre review, 意思是code已经提交到svn后review),使用简单,在本地代码目录下直接输入codeviewing.pl,然后上一次code的commit log和diff会发通过email发到同组的开发人员邮箱中,code diff以patch的形式发送(+++和---以不同颜色加亮)。当然也支持指定revision版本review,加个revision参数就行了。
?
?
[w3zhang@ling08 src]$ codeviewing.plMail have been sent successfullyFrom: wei-jovi.zhang@***.comTo: wei-jovi.zhang@***.com Subject: [code review invitation] SS_Test: change H02 error log to info
?
?
为了简单起见,已经把收件地址只改为本人的邮箱了,下面看看你的邮箱,将会收到这样一份邮件:
?
?
Hi All,Please be freely to review the code below, any comments are Welcome!------------------------------------r462 | w3zhang | 2011-09-13 14:55:46 +0800 (Tue, 13 Sep 2011) | 1 lineChanged paths: M /trunk/SS_Test/src/semper_h02.sdlchange H02 error log to info------------------------------------Index: semper_h02.sdl===================================================================--- semper_h02.sdl(revision 461)+++ semper_h02.sdl(revision 462)@@ -349,29 +349,29 @@ TASK abnm_parm.cause := semper_cause__t_ipif_up__c; ELSE: TASK abnm_parm.cause := semper_cause__t_ipif_dn__c; ENDDECISION; WHILE ( index < ip_if_info_t_max_ip_addr_c ); DECISION ( if_data.if_addr(index).ip_address.version ); ( ip_addr_t_not_def_c ): OUT; ENDDECISION; CALL ip_string( if_data.if_addr( index ), ip_str );- TASK pr_err( @'SEMPER_H02: ip_state_ind_s.if_data'- 'index: %d'- 'if_status: %d'- 'if_addr: %s',- index, if_data.if_status, ip_str );+ TASK pr_info( @'SEMPER_H02: ip_state_ind_s.if_data'+ 'index: %d'+ 'if_status: %d'+ 'if_addr: %s',+ index, if_data.if_status, ip_str );
?
?
简单吧!此脚本适合于Linux下的快速组内email review, Have fun! 下面是200行的Perl脚本:
?
?
#!/usr/bin/perl -w# Author: Jovi Zhang <wei-jovi.zhang@***.com># this script is used for mail notification for svn code changeuse strict;my $mail_sender = "wei-jovi.zhang\@***.com";my $mail_receiver = "wei-jovi.zhang\@***.com ";my $svninfo;my $subsystem;my $revision;if ($#ARGV > 0) { print "too many parameters\n"; exit(-1);}if (defined $ARGV[0] && ($ARGV[0] eq "--help")) { help(); exit(0);}$revision = $ARGV[0];$svninfo = get_svninfo();$subsystem = get_subsystem($svninfo);if ($subsystem eq "") { print "Current directory is not a valid svn repository\n"; exit(0);}if (!defined $revision) { $revision = get_lastest_revision($svninfo);}my ($changlog, $diff, $ret) = get_commit_detail($revision);if ($ret != 0) { exit(-1);}if ($diff eq "") { print "non diff in the revision $revision, mail not sent\n"; exit(-1);}my $commit_message = get_commit_message($changlog);send_mail($subsystem, $commit_message, $changlog, $diff, $mail_receiver);exit(0);sub help { print "codreviewing.pl: mail notification for svn code change\n\n"; print "Usage:\n"; print "1): codreviewing.pl\n"; print " use latest change as default revision\n"; print "2): codreviewing.pl <rev>\n"; print " use <rev> revision\n";}sub get_svninfo { `svn up > /dev/null`; my $info = `svn info 2>&1`; return $info;}sub get_subsystem { my ($info) = @_; my $subsystem = ""; if ($info =~ /Repository Root:.*svnroot\/(.*)/) { $subsystem = $1; } return $subsystem;}sub get_lastest_revision { my ($info) = @_; my $rev = -1; if ($info =~ /Last Changed Rev: ([0-9]+)/) { $rev = $1; } return $rev;}sub get_commit_detail { my ($rev) = @_; my $log; my $diff; $log = `svn log -g -v -c $rev`; if ($? != 0) { return ($log, $diff, -1); } $diff = `svn diff -c $rev --diff-cmd diff -x "-U 12"`; if ($? != 0) { return ($log, $diff, -1); } return ($log, $diff, 0);}sub get_commit_message { my ($log) = @_; my $cimsg = ""; if ($log =~ m/\n\n(.*)\n---/ms) { $cimsg = $1; } if ($cimsg eq "") { $cimsg = "<no description message on this change>" } return $cimsg;}sub send_mail { my ($subsystem, $commit_message, $changelog, $diff, $mail_receiver) = @_; $changelog =~ s/\&/\&/g; $changelog =~ s/</\</g; $changelog =~ s/>/\>/g; #$changelog =~ s/\n/<br>/g; #$changelog =~ s/ / /g; my $html_diff = diff2html($diff); my $mail_text = "Subject: [code review invitation] $subsystem: $commit_message\n" . "Content-Type: text/html; charset="us-ascii\\n" . "<html>\n" . "<style>\n" . ".diffdiv { border: solid 1px black; }\n" . ".comment { color: gray; }\n" . ".diff { color: #8A2BE2; }\n" . ".minus3 { color: blue; }\n" . ".plus3 { color: maroon; }\n" . ".at2 { color: lime; }\n" . #".plus { color: green; background: #E7E7E7; }\n" . #".minus { color: red; background: #D7D7D7; }\n" . ".plus { color: green; }\n" . ".minus { color: red; }\n" . ".only { color: purple; }\n" . "</style>\n" . "<body>\n" . "<pre>\n" . "<span class="only">\n" . "Hi All,\n\n" . "Please be freely to review the code below, any comments are Welcome!\n\n" . "$changelog\n" . "</span>\n" . "$html_diff\n" . "</pre>\n" . "</body>\n" . "</html>"; open (my $mail_handle, "| /usr/sbin/sendmail $mail_receiver"); print $mail_handle $mail_text; close($mail_handle); print "Mail have been sent successfully\n\n"; my $date = `date -R`; print "From: $mail_sender\n" . "To: $mail_receiver\n" . "Subject: [code review invitation] $subsystem: $commit_message\n";}sub diff2html { my ($diff) = @_; my $html_text; $html_text = "<span class="comment">"; while ($diff =~ /(.*)\n/g) { my $line = $1; my $class = ""; if (substr($line, 0, 3) eq "+++") { $class = "plus3"; } elsif (substr($line, 0, 3) eq "---") { $class = "minus3"; } elsif (substr($line, 0, 2) eq "@@") { $class = "at2"; } elsif (substr($line, 0, 1) eq "+") { $class = "plus"; } elsif (substr($line, 0, 1) eq "-") { $class = "minus"; } $line =~ s/\&/\&/g; $line =~ s/</\</g; $line =~ s/>/\>/g; if ($class ne "") { $html_text .= "<span class="$class">$line</span>\n"; } else { $html_text .= "$line\n"; } } $html_text .= "</span>"; return $html_text;}?
?
?
?
1 楼 banxi1988 2011-10-09 有一个小问题啊,我的经验是上面以<style></style>形式写入的css,一般会被mail服务器过滤掉的. 2 楼 bookjovi 2011-10-09 banxi1988 写道有一个小问题啊,我的经验是上面以<style></style>形式写入的css,一般会被mail服务器过滤掉的.