在SVN上实现代码风格自动检查
在程序开发的过程中,我们希望团队成员的代码风格保持一致。
但是,如果只是口头或者书面协定的话,结果往往不太好,甚至更糟,可能会导致多种代码风格混杂在同一个源文件中的局面出现。
一个改进的方法是,每个人都使用自己的代码风格,但是在修改其他人代码的时候,尊重他人的代码风格;这个方法实际实行起来也是非常困难的,大多数时候也只是一厢情愿而已;很多人在自己的源文件中都做不到代码风格统一,原因是Eclipse支持自动代码生成,而风格又与他自己的不一致。
一个更进一步的解决方案是,在SVN提交的时候,强制检查代码风格,拒绝那些不符合规范的代码。
在这里,我只针对Java代码工程,且SVN作为版本工具的情况,具体的方案是:SVN PreCommitChecks + CheckStyle + svnchecker。
先说一下我个人的机器环境:Ubuntu 12.04,svn 1.6.17,版本库建立在本地文件系统的个人目录之下。
具体的步骤如下(假定你已经安装过svn):
1.下载并安装CheckStyle
项目主页:http://checkstyle.sourceforge.net/
下载页面:http://sourceforge.net/projects/checkstyle/files/
下载之后,解压,然后将里面的jar包加上可执行权限,我个人是将它放在目录$HOME/bin/svn-tools/checkstyle-5.6/之下
2.下载并安装svnchecker
项目主页:http://svnchecker.sourceforge.net/ 和 http://svnchecker.tigris.org/
下载页面:http://svnchecker.sourceforge.net/download.php
下载之后,解压,然后将里面的py文件加上可执行权限,我个人是将它放在目录$HOME/bin/svn-tools/svnchecker-0.3/之下
3.建立本地版本库(主要用于调试配置与脚本,在实际环境下,应该使用真正的版本库)
我建立的个人本地版本库是在目录$HOME/demosvn/之下,注意它里面的hooks目录
4.确定checkstyle.xml文件
确定一个适合本团队的checkstyle.xml是非常重要的,它直接决定了事情的效果。
对于新起项目,一开始就应该确定一个比较完善的风格规则。
对于遗留项目,应该先简单,然后逐渐丰富,留好过渡期。
checkstyle.xml的具体书写规则以及它的能力与限制,请参考:
http://checkstyle.sourceforge.net/checks.html
一个示例checkstyle.xml,它来自Google:
http://code.google.com/p/google-api-java-client/source/browse/checkstyle.xml?repo=samples
网上有一些知名公司的代码规范,你可以下载他们的checkstyle.xml然后再做修改。
在使用第三方checkstyle.xml的时候,有时候会出现CheckStyle运行时错误,一般是因为checkstyle.xml中使用了不被识别的规则,去掉就好了。
我将checkstyle.xml放在目录$HOME/demosvn/hooks/之下,你可以自行选择其它地方。
5.确定svncheckerconfig.ini配置文件
svncheckerconfig.ini文件的具体格式是Python的ConfigParser类定义的标准配置文件格式,非常容易出错,因此要小心书写。
svncheckerconfig.ini既可以放在svnchecker的安装目录之下($HOME/bin/svn-tools/svnchecker-0.3/),也可以放在hooks目录之下($HOME/demosvn/hooks/);前者起全局作用,后者则只对该版本库起作用。
我选择将它放在目录$HOME/demosvn/hooks/之下,只对版本库demosvn起作用。
如果svncheckerconfig.ini没有出现在这两个位置之一,运行的时候就会报错,提示找不到配置文件。
如果你确信svncheckerconfig.ini放在了正确的位置,但是运行时仍然提示找不到配置文件,一般是因为svncheckerconfig.ini的内容不符合格式规范。
一个示例配置:
1 [Default] 2 3 #This property tells Subversionchecker about all checks 4 #(UnitTests, AccessRights, XMLValidator etc) it should execute. 5 #Separated with comma (",") 6 Main.PreCommitChecks=Checkstyle 7 8 #Path of java executable to run Checkstyle command 9 Checkstyle.Java=/usr/bin/java 10 11 #Classpath for executing Checkstyle rules 12 Checkstyle.Classpath=$HOME/bin/svn-tools/checkstyle-5.6/checkstyle-5.6-all.jar 13 14 #Configuration file for Checkstyle to run its rules. 15 Checkstyle.ConfigFile=$HOME/demosvn/hooks/checkstyle.xml 16 17 #In case of failures, where should Subversionchecker redirect the errors 18 Checkstyle.FailureHandlers=Console
注意将里面的路径换成适合你自己的路径,请使用全路径;注意给脚本文件加上可执行权限。
6.编写svn pre-commit脚本
在hooks目录下定义一个名字为pre-commit的脚本文件,具体内容如下:
1 #!/bin/sh 2 3 REPOS="$1" 4 TXN="$2" 5 6 # Make sure that the log message contains some text. 7 SVNLOOK=/usr/bin/svnlook 8 $SVNLOOK log -t "$TXN" "$REPOS" | \ 9 grep "[a-zA-Z0-9]" > /dev/null || exit 1 10 11 # Exit on all errors. 12 set -e 13 14 # Do the check 15 $HOME/bin/svn-tools/svnchecker-0.3/Main.py PreCommit $REPOS $TXN || exit 1 16 17 # All checks passed, so allow the commit. 18 exit 0
注意将里面的路径换成适合你自己的路径,请使用全路径。
以上这种方案实现起来,也是有一些缺点的:
1.定义的一些规则可能太死板,导致大面积已有代码不符合规范(尽早实施,还是定义一组宽松且合适的规范?)
2.如何处理第三方代码(是否可以定义例外规则?)
3.如何定义强制提交后门(没有后门是否更好?)
4.如何做到只检查修改的部分(全文件检查不宜实施,考虑修改其他人源文件的情况)
最后,最具决定性的一点,我认为还是团队管理者对代码风格的重视程度。