【1.業(yè)務(wù)需求】
為部門的SVN服務(wù)器添加一項(xiàng)commit控制:即用戶在提交改變時(shí)必須寫注釋,且不得低于10個(gè)字符。
【2.基本思路】SVN本身并不提供這種強(qiáng)制寫log的功能,而是通過一系列的鉤子程序(我們稱為hook腳本),在提交之前(pre-commit),提交過程中(start-commit),提交之后(post-commit),調(diào)用預(yù)定的鉤子程序來完成一些附加的功能。
本次我們要實(shí)現(xiàn)的是在提交到版本庫(kù)之前檢查用戶是否已經(jīng)寫了注釋,當(dāng)然要使用pre-commit這個(gè)鉤子程序。我們打開SVN的repository下的hook目錄,可以發(fā)現(xiàn)有好幾個(gè)文件,其中一個(gè)是“pre-commit.tmpl”。這個(gè)文件是一個(gè)模板文件,它告訴了我們?nèi)绾螌?shí)現(xiàn)提交前控制。打開該模板文件,我們看到如下一段說明:
# The pre-commit hook is invoked before a Subversion txn is
# committed. Subversion runs this hook by invoking a program
# (script, executable, binary, etc.) named 'pre-commit' (for which
# this file is a template), with the following ordered arguments:
#
# [1] REPOS-PATH (the path to this repository)
# [2] TXN-NAME (the name of the txn about to be committed)
#
# The default working directory for the invocation is undefined, so
# the program should set one explicitly if it cares.
#
# If the hook program exits with success, the txn is committed; but
# if it exits with failure (non-zero), the txn is aborted, no commit
# takes place, and STDERR is returned to the client. The hook
# program can use the 'svnlook' utility to help it examine the txn.
我們看到在一個(gè)提交事務(wù)執(zhí)行之前,該hook腳本會(huì)被調(diào)用。然后向該腳本傳遞兩個(gè)參數(shù):REPOS-PATH和TXN-NAME,一個(gè)是用戶要提交的URL,一個(gè)是本次事務(wù)的一個(gè)事務(wù)號(hào)。如果提交成功則返回0,否則返回其它非0結(jié)果。那么我們的鉤子程序是要在事務(wù)提交之前,攔截這些請(qǐng)求,然后通過svnlook命令來檢查是否已經(jīng)寫了log。
【3.示例代碼】下面這段代碼是網(wǎng)上直接拷貝的一段代碼:
@echo off
setlocal
set REPOS=%1
set TXN=%2
rem check that logmessage contains at least 10 characters
svnlook log "%REPOS%" -t "%TXN%" | findstr "." > nul
if %errorlevel% gtr 0 goto err
exit 0
:err
echo Empty log message not allowed. Commit aborted! 1>&2
exit 1
下面解析一下綠色高亮處代碼的作用:
①set REPOS=%1
set TXN=%2
還記得我們前面提到的但事務(wù)提交時(shí),會(huì)傳遞兩個(gè)參數(shù)嗎?這里是分別用來接收URL和事務(wù)號(hào)的
②svnlook log "%REPOS%" -t "%TXN%" | findstr ".........." > nul
這句是核心程序。首先svnlook log是用來查看某個(gè)版本庫(kù)某次提交的log的,那么我們?cè)趺粗肋@兩個(gè)
參數(shù)呢?答案是我們前面已經(jīng)保存的REPOS和TXN參數(shù)。
它的作用是查看%REPOS%這個(gè)URL第%TXN%次提交的log信息,那么| findstr ".........."呢?細(xì)心
的讀者會(huì)發(fā)現(xiàn)這里有10個(gè)圓點(diǎn)號(hào),即表示10個(gè)字符。
整句的作用是先獲取當(dāng)前提交的log內(nèi)容,然后判斷是否有10個(gè)字符以上
③echo Empty log message not allowed. Commit aborted! 1>&2
這句話的作用是當(dāng)提交檢查失敗時(shí),輸出的提示信息
【4. 運(yùn)行測(cè)試及錯(cuò)誤解決】到這里我們應(yīng)該可以正常運(yùn)行了吧?下面我們把上面這個(gè)程序保存為pre-commit.bat,保存到hook目錄下。啟動(dòng)SVN,隨意修改一個(gè)文件后,不寫注釋提交?纯聪旅娴慕Y(jié)果: 居然提示我們找不到svn repository目錄下的format文件:
Svnlook:不能打開文件”C:pengOther ewRepofom…” The system cannot find The path specified.
真郁悶!這是什么原因。仔細(xì)檢查文件,沒有發(fā)現(xiàn)語法錯(cuò)誤。從SVN的官網(wǎng)上下了一份同樣內(nèi)容的bat文件,測(cè)試通過!那會(huì)不會(huì)是文件的格式原因呢?我試著比較了這兩份文件的字符數(shù),發(fā)現(xiàn)居然不一樣。會(huì)不會(huì)是一些控制字符的原因。
于是打開舊的文件,重新整理格式,發(fā)現(xiàn)每一行后面都多了一個(gè)中文的換行符。刪除這些換行符再測(cè)試,測(cè)試通過!
教訓(xùn):從網(wǎng)頁上直接拷貝代碼有時(shí)會(huì)帶有特殊字符,諸如控制字符會(huì)中文空格等,這些字符有時(shí)會(huì)引起一些不必要的錯(cuò)誤。