使用python編寫svn鉤子

同上一篇trac中安裝插件的文章的出發點同樣,感受用文檔和口頭制定規則在執行上會有誤差而且須要常常引導新人去熟悉規則。python

因此,又費了幾個小時去琢磨怎麼改進svn提交代碼的鉤子,現有的鉤子的功能比較簡單,只是驗證提交時的日誌字數有沒有超過5個,而我想將其改進爲驗證是否是符合「問題修復:#1234 xxxx」的這種格式,這裏處理的是 版本庫/hooks/pre-commit.bat  這個鉤子。正則表達式

話很少說,svn鉤子原理和規則不表,先上原鉤子代碼ide

@echo off
rem SVN強制寫註釋的hooks腳本(Windows)
rem 文件名是: pre-commit.bat,放到repository/hooks目錄下
setlocal
set SVN_BINDIR="D:\service\Subversion\bin"
set REPOS=%1
set TXN=%2
rem check that logmessage contains at least 10 characters
%SVN_BINDIR%\svnlook log "%REPOS%" -t "%TXN%" | findstr "......" > nul
if %errorlevel% gtr 0 goto err
exit 0
:err
echo 提交時必須填寫說明(Message)! 1>&2
echo "%REPOS%" -t "%TXN%" 1>&2
exit 1

一開始嘗試使用直接修改bat,改進findstr來支持更復雜的正則表達式,可是遇到各類問題。svn

  1. 首先是不太熟悉批處理的各類規則。
  2. 而後有些特殊字符在命令行上的不能使用。
  3. 再者就是使用在線工具驗證過的正則表達式findstr匹配失敗。

在測試過程當中保留了下面這個奇葩的中間版本(不能正常工做的)。工具

 1 @echo off
 2 rem SVN強制寫註釋的hooks腳本(Windows)
 3 rem 文件名是: pre-commit.bat,放到repository/hooks目錄下
 4 setlocal
 5 set SVN_BINDIR=C:\Program Files\TortoiseSVN\bin
 6 set REPOS=%1
 7 set TXN=%2
 8 
 9 rem check that logmessage contains at least 10 characters
10 "%SVN_BINDIR%\svnlook" log "%REPOS%" -t "%TXN%" > t.log
11 
12 :set disable=:;'^<^>,。‘*【】{}??《》
13 rem (#[0-9]+ )?[^#  容許帶或不帶ticket號開頭,不支持非中文符號
14 
15 findstr "^問題修復:(#[0-9]+ )*..." t.log
16 @echo %errorlevel% 1>&2
17 if not %errorlevel% gtr 0 goto success
18 findstr "^功能開發:(#[0-9]+ )*[^#%disable%]*$" t.log > nul
19 if not %errorlevel% gtr 0 goto success
20 findstr "^功能改進:(#[0-9]+ )*[^#%disable%]*$" t.log > nul
21 if not %errorlevel% gtr 0 goto success
22 findstr "^功能優化:(#[0-9]+ )*[^#%disable%]*$" t.log > nul
23 if not %errorlevel% gtr 0 goto success
24 findstr "^代碼優化:(#[0-9]+ )*[^#%disable%]*$" t.log > nul
25 if not %errorlevel% gtr 0 goto success
26 
27 :err
28 echo 未遵循svn提交規範 1>&2
29 :echo "%REPOS%" -t "%TXN%" 1>&2
30 :rm t.log
31 exit 1
32 
33 :success
34 :rm t.log
35 exit 1
不成功的中間版本

能夠看到,我無奈地將一個正則表達式一分爲五,而且拆分紅5個以後不會使用管道同時將參數傳遞(也不能吧?)給findstr,關鍵是我那麼一大串在日誌中禁用標點符號不知爲什麼不能工做,反正斷斷續續(常常被人打斷工做,去處理其它事)耗費了我3個小時去寫測試的批處理和這個鉤子批處理,仍是搞不定。一念下,想起python這種神器,花了幾分鐘找到了正則表達式的match示例,又查閱了對於stdin輸入的獲取方法,而後直接寫了個check.py去代替findstr來匹配正則表達式(其實這思路是上午查看trac的TracTicketValidatorPlugin插件時看代碼獲得的),而後再花2分鐘驗證之,搞定,上代碼:測試

  • pre-commit.bat
 1 @echo off
 2 rem SVN強制寫註釋的hooks腳本(Windows)
 3 rem 文件名是: pre-commit.bat,放到repository/hooks目錄下
 4 setlocal
 5 set SVN_BINDIR="C:\Program Files\TortoiseSVN\bin"
 6 set REPOS=%1
 7 set TXN=%2
 8 
 9 rem check that logmessage contains at least 10 characters
10 %SVN_BINDIR%\svnlook log "%REPOS%" -t "%TXN%" | python check.py "......" 1>&2
11 if %errorlevel% gtr 0 goto err
12 exit 0
13 
14 :err
15 echo 未遵循svn提交規範! 1>&2
16 echo "%REPOS%" -t "%TXN%" 1>&2
17 exit 1
  • check.py (2014/04/10修正,使用unicode字符串以對全角符號進行正確匹配)
 1 # coding=gbk
 2 import re
 3 import sys
 4 
 5 input_file = sys.stdin
 6 
 7 # 若是不用unicode模式則在有全角字符的狀況下匹配不成功
 8 restr=u'^((問題修復)|(功能開發)|(功能改進)|(功能優化)|(代碼優化)):(#[0-9]+ )?[^#:;\'<>,。‘*【】{}??《》\n\r]+$'
 9 for s in input_file:
10     #先解碼爲unicode字符串
11     u = s.decode('GBK')
12     print(u"驗證字符串:" + u)
13     if re.match(restr, u) != None:    
14         print("匹配成功")
15         exit(0)
16     else:
17         exit(1)

 

ps:優化

哎,用幾年批處理,依然被諸如:啓動進程進獲取打印信息,字符串截取,字符串拼裝等一些簡單操做給難倒,感受每次寫批處理都是在 拼湊->試一下 的無限循環,不學點新東西就落後了。spa

相關文章
相關標籤/搜索