2009年9月7日星期一

使用svn的“属性”自动填写代码注释

我以前觉得自己对svn的运用还算比较熟练的了,一般的主干、分支和标签的管理,差异、合并、日志等等命令的运用也比较得心应手了。今天在cpyug上看到一个关于使用svn自动填写版本号等信息的帖子才发现自己完全把svn的“属性”遗忘了。svn的property能够干的事情真的大大超乎我的想象。

svn的svn:keywords属性能够自动把代码里的一些关键字替换成svn的一些信息,包括最后修改的版本号、修改人、修改时间、文件在版本库中的位置和文件在版本库中的id。这一下子就解开了我看很多其他项目源代码时的疑问,当时怎么也没想明白他们是怎么把这些填到代码注释中去的。这个在svn的在线电子书的Keyword Substitution一节里讲的很详细。

在文件的开头加上:
#$Author$
#$Date$
#$Rev$
#$URL$
设置svn:keywords属性并提交后这一段会变成:
#$Author: xie $
#$Date: 2009-09-06 18:32:58 +0800 (日, 2009-09-06) $
#$Rev: 15 $
#$URL: file:///home/xie/svnrepo/test.py $

但是这还很不够,因为:
1、需要自动为所有现有的python源代码文件的开头加上这样的注释
2、需要保证所有新增的python源代码文件的开头都有相同的注释
3、需要保证所有新增的python源代码文件都被加上了适当的svn:keywords属性

要解决第一个问题在Linux下并不难,因为我们有sed。脚本很简单,在所有.py文件的第二行加上四行注释:
#!/bin/sh
for x in $(find ./ -type f -name "*.py")
do
    sed '2 i\#\$Author\$\n#\$Date\$\n#\$Rev\$\n#\$URL\$' $x > $x.new
    mv $x.new $x
done

第二个问题有点麻烦。我的第一感觉是如果在提交的时候能有脚本为所有python源代码文件插入这段注释就好了,不过事实上不行。svn有钩子(hook)的概念,可以在特定事件发生的时候执行某个脚本。这个脚本不应该修改提交的任何内容,而应该根据一系列规则检查提交的内容。如果提交的东西不合适,就让提交失败,这样提交者就会根据提示信息去修正并再次提交。svn很厚脸皮的把工作还是扔给了苦命的程序员。这里我们不希望没有这段注释的源代码提交成功,就需要利用pre-commit事件,在提交之前检查提交的内容,如果提交的内容不含有我们需要的关键字那就提示错误信息并使提交失败。

pre-commit事件执行的脚本的环境是shell,也就是说你可以用你喜欢的任何语言,比如perl、python甚至javascript(如果你在服务器上安装了SpiderMonkey的话)来写这段检查脚本。任何一个新建的svn版本库的hooks目录下都有一陀例子脚本,svn的官方网站上也有一些示例脚本,但都不及一位叫Thomas Guest的同学的博文说的明白。我对照着他的脚本稍微修改了一下就很快写出了一个符合我们需要的脚本,来检查版本库的某个特定目录下的所有文件名符合某个模式的文件是否符合一定的规则。

第三个问题无法在服务器端解决,原因和第二个问题一样。合适的做法就是在pre-commit脚本中检查提交的文件是否含有适当的svn:keywords属性。如果属性不正确,就拒绝提交。

以上两个限制强制程序员在提交的时候为需要提交的文件加上svn:keywords属性并在文件开头添加适当的注释,但是人总是不完美的,肯定有忘记的时候。怎么办?这就需要程序员配置自己的svn客户端,打开“自动属性”(auto-prop)选项。通常,配置文件是~/.subversion/config,编辑这个文件,将enable-auto-prop设置成yes,然后在最后那个小节中为某个类型的文件设置svn:keywords属性,这样所有新增到版本控制的文件都会自动拥有这个属性了。

当然,现有的源代码还是没有这个属性,我们得批量的设置一下,一行命令就搞定了(比如我们的目标是当前目录下的所有python源代码文件):
find ./ -type f -name "*.py" | xargs svn propset svn:keywords "Author Date Revision HeadURL"

没有评论:

发表评论