Subversion本身有很好的扩展性,用户可以通过钩子实现一些自定义的功能,
Subversion钩子
。所谓钩子实际上是一种事件机制,当系统执行到某个特殊事件时,会触发我们预定义的动作,这样的特殊事件在Subversion里有很多,默认有如下模板可供选择:
shell> ls /path/to/repository/hookspost-commit.tmplpost-lock.tmplpost-revprop-change.tmplpost-unlock.tmplpre-commit.tmplpre-lock.tmplpre-revprop-change.tmplpre-unlock.tmplstart-commit.tmpl
其中最常用的是pre-commit和post-commit,也就是提交前后的钩子,下面以pre-commit为例来说明一下如何自定义Subversion钩子。
假设有一个PHP项目使用Subversion做版本控制,使用中发现了一些问题,比如程序员不写日志,或者提交的文件有BOM,或者提交的文件有语法错误,或者提交的文件不符合编码规范等等,这些问题都可以利用pre-commit钩子来解决,实际上已经有人写了解决类似问题的工具php-svn-hook,不过我们这里选择自己实现:
shell> cat /path/to/repository/hooks/pre-commit#!/bin/bashREPOS="$1"TXN="$2"SVNLOOK="/usr/bin/svnlook"PHP="/usr/bin/php"LOG=$($SVNLOOK log -t "$TXN" "$REPOS")if [ "$LOG" = "" ]; then echo "Please input log" 1>&2 exit 1fiFILES=$($SVNLOOK changed -t "$TXN" "$REPOS" | awk '/^[AU]/ {print $NF}')for FILE in $FILES; do CONTENT=$($SVNLOOK cat -t "$TXN" "$REPOS" "$FILE") if echo "$CONTENT" | grep -q $'xEFxBBxBF'; then echo "Please remove BOM from $FILE" 1>&2 exit 1 fi if [[ "$FILE" =~ .(php|html)$ ]]; then MESSAGE=$(echo "$CONTENT" | $PHP -l 2>&1) if [ $? -ne 0 ]; then echo "$MESSAGE" | sed "s/ -/ $FILE/g" 1>&2 exit 1 fi fidone/path/to/PHP_CodeSniffer/scripts/phpcs-svn-pre-commit "$REPOS" -t "$TXN" 1>&2 || exit 1exit 0
注:代码里使用PHP_CodeSniffer检查编码规范,
管理资料
《Subversion钩子》(https://www.unjs.com)。配置好脚本后,一定要记着给脚本加上可执行属性,不然脚本执行后会显示不知所云的错误信息:svn: Commit blocked by pre-commit hook (exit code 255) with no output。
本文以pre-commit为例说明了一下钩子的用法,实际上其他脚本也很有用,比如说如果你想在提交代码后发一条微博,就可以利用post-commit来解决,但是记住不要滥用,比如说非常流行的一种做法是利用post-commit来更新线上程序,但由于整个操作过程不能保证原子性,所以有可能出现问题,解决方法请参考Rasmus的描述,我就不多说了。