Subversion本身有很好的擴(kuò)展性,用戶可以通過(guò)鉤子實(shí)現(xiàn)一些自定義的功能,
Subversion鉤子
。所謂鉤子實(shí)際上是一種事件機(jī)制,當(dāng)系統(tǒng)執(zhí)行到某個(gè)特殊事件時(shí),會(huì)觸發(fā)我們預(yù)定義的動(dòng)作,這樣的特殊事件在Subversion里有很多,默認(rèn)有如下模板可供選擇:
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為例來(lái)說(shuō)明一下如何自定義Subversion鉤子。
假設(shè)有一個(gè)PHP項(xiàng)目使用Subversion做版本控制,使用中發(fā)現(xiàn)了一些問(wèn)題,比如程序員不寫日志,或者提交的文件有BOM,或者提交的文件有語(yǔ)法錯(cuò)誤,或者提交的文件不符合編碼規(guī)范等等,這些問(wèn)題都可以利用pre-commit鉤子來(lái)解決,實(shí)際上已經(jīng)有人寫了解決類似問(wèn)題的工具php-svn-hook,不過(guò)我們這里選擇自己實(shí)現(xiàn):
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檢查編碼規(guī)范,
管理資料
《Subversion鉤子》(http://www.msguai.com)。配置好腳本后,一定要記著給腳本加上可執(zhí)行屬性,不然腳本執(zhí)行后會(huì)顯示不知所云的錯(cuò)誤信息:svn: Commit blocked by pre-commit hook (exit code 255) with no output。
本文以pre-commit為例說(shuō)明了一下鉤子的用法,實(shí)際上其他腳本也很有用,比如說(shuō)如果你想在提交代碼后發(fā)一條微博,就可以利用post-commit來(lái)解決,但是記住不要濫用,比如說(shuō)非常流行的一種做法是利用post-commit來(lái)更新線上程序,但由于整個(gè)操作過(guò)程不能保證原子性,所以有可能出現(xiàn)問(wèn)題,解決方法請(qǐng)參考Rasmus的描述,我就不多說(shuō)了。