目录:
关于SVN
Hooks(钩子)的使用 (1)
关于SVN Hooks(钩子)的使用 (2)
关于SVN Hooks(钩子)的使用 (3)
关于SVN Hooks(钩子)的使用 (4)
关于SVN Hooks(钩子)的使用 (5)
关于SVN Hooks(钩子)的使用 (1)
由于工作需要,在svn中经常需要使用到svn hooks,把一些常用的记录在这里。
1.什么是svn hooks?
服务器钩子:
经常提到的svn hooks是一组“外挂”脚本程序,是svn提供的一组由svn事件触发的特别有用的程序。这些程序在服务器端执行,可以提供svn之外的一些附加功能。钩子可以调用批处理文件、可执行文件或者一些类似于perl、python等的脚本。
![](images/2012042621.png)
客户端钩子:
如果使用tortoise svn(海龟svn,常用的svn客户端),它也提供钩子机制,这些和svn
hooks有本质区别,它是在本地(客户端)执行的。
![](images/2012042622.png)
2.svn hooks有哪些?
服务器钩子:
svn服务端有9种钩子,分别是:
A.关于锁定的2种
a1.pre-lock
a2.post-lock
B.关于解锁的2种
b1.pre-unlock
b2.post-unlock
C.关于提交的3种
c1.start-commit
c2.pre-commit
c3.post-commit
D.关于属性的2种
d1.pre-revprop-change
d2.post-revprop-change
客户端钩子:
tortoise svn客户端有6中钩子,分别是:
A.关于提交的
a1.start commit hook
a2.pre-commit hook
a3.post-commit hook
B.关于更新的
b1.start update hook
b2.pre-update hook
b3.post-update hook
关于SVN Hooks(钩子)的使用 (2)
编写hooks可以使用多种语言和脚本,我对vb比较熟悉,所以选择VBscript,即简单又功能强大。
对于上一次说到的多个客户端和服务器钩子,不熟悉的可能已经晕了,在这篇里面我们先关注几个问题:
1.对于客户端hooks来说,关于commit的(其实关于update的一样)三个钩子时序是如何的?
2.对于客户端hooks,如何让他运行VBSctript脚本。
现在开始回答问题:
对于pre-commit和post-commit的时序来说还是比较明显的。但是start-commit发生在什么时间?它和pre-commit的发生关系到底如何?这几个问题可能很困惑。我们不妨添加一些脚本来让tortoisesvn自己来告诉我们。
1.我在D盘新建了三个脚本文件,分别是:
start-commit-hook.vbs
pre-commit-hook.vbs
post-commit-hook.vbs
其中的内容为如下所示,其主要目的是在D盘生成三个以事件时间为名称的文件夹,三个脚本中唯一的不同是红色标志出的内容,主要区别事件:
dim fs,s,t
set fs=wscript.createobject("scripting.filesystemobject")
t="StartCommit "+cstr(hour(time))+"-"+cstr(minute(time))+"-"+cstr(second(time))
set s=fs.createfolder("d:/"+t)
set fs=nothing
2.鼠标右键--->TortoiseSVN--->设置,打开的对话框中选择Hook脚本,设置如下:
特别提醒:对于vbs脚本,调用命令中必须使用wsctript,否则脚本无法运行。
![](images/2012042623.png)
3.依次设定pre-commit和post-commit脚本
4.执行一次提交,结果如下
![](images/2012042624.png)
发现先执行start-commit,然后是pre-commit,最后是post-commit
另外如果感兴趣可以再进行深入一步的分析,你可以发现:
start-commit是在通过菜单触发“提交”活动后,弹出“提交”对话框前执行;
pre-commit是在点击“提交”对话框上的“确定”时执行,即真正的提交活动时执行;
post-commit是在提交活动结束时执行。
关于SVN Hooks(钩子)的使用 (3)
在第一篇中提到过,服务器钩子有9种,客户端钩子有6中,但是细心的人会发现其中服务器和客户端都有关于commit的钩子,那就会引出几个问题:
1.他们一样吗?
2.他们之间有什么关系?
3.客户端和服务器端触发序列如何?
为了回答清楚这些问题,必须先看看服务器端的钩子如何运作的,然后再想办法进行研究。
服务器端的钩子需要运行的话,需要将原有的×.tmpl改成对应的.bat或者.exe或者其他可执行文件,这个时候svn会识别出可运行的钩子,自动运行。
每个tmpl文件其实都是一个文本文件,使用记事本或者notepad++等打开后,可以看到里面的注释和详细的说明,这些是我们可以使用的第一手的帮助文件,当然网上也有大量关于hook的说明和用法,大家可以认真研究。
在这里只是为了研究时序,所以我对于大部分的内容先忽略,只是简单的使用来进行信息沟通。
1.在hooks目录下,新建三个文本文件,改名为:
start-commit.bat
pre-commit.bat
post-commit.bat
2.分别在这三个文件中输入:
echo "Start-Commit!" 1>&2
exit 1
每个文件中只有红色字体不同,
使用echo将提示信息返回给客户端,在Windows平台下,必须使用“1>&2”作为结尾,
exit 0表示结果正确,exit 1或者其他非零数值,表示结果错误,svn只将错误结果返回给客户端
3.保存
4.按照start,pre和post的顺序依次将exit 1改为exit
0进行提交实验,可以发现服务器和客户端的信息交互大概顺序为如下图片所示
1.他们一样吗?
很显然,客户端和服务端的这些钩子不一样,只是名称一样而已。
2.他们之间有什么关系?
他们之间没有特别大的关系,但是依靠消息的传递互相协作工作。
3.客户端和服务器端触发序列如何?
如下图。
![](images/2012042625.png)
关于SVN Hooks(钩子)的使用 (4)
说句实话,对于服务器svn钩子,Windows平台下选择vbs并不是最佳解决方案,但是我对vbs的熟悉程度远大于其他脚本语言,如python,perl等,所以选择并不多:要么是vbs,要么是bat,bat实现钩子的例子网上有很多,但是对于vbs实现的,却很少,决定使用vbs试试看。
对于vbs有几个问题,需要特别注意:
1.对于svn 钩子而言,最好的钩子程序是.bat、.exe、.cmd这样的可执行程序。
2.Windows平台上,由于vbs本身就是解释性语言,由于Windows版本和vbs版本问题,存在一些调用问题,比如Windows
xp和vista调用就可能存在不一致的问题。我办公使用的是xp,其解释器的路径为:C:/WINDOWS/system32/cscript.exe.
但事情都是辩证的,vbs存在很多问题,但是他简单方便,而且基本上Windows标配有其解释器,不需要其他的编译器和解释器。但是它只能在Windows平台上运行,运行平台比较单一。
python和perl流行,但是需要附加的编译器等以及另外的学习成本,但是其具有跨平台的特性。
3.对于vbs,无法在hooks目录中直接同名调用,而需要借助同名的.bat进行调用。
举例:
如果pre-lock hook,需要在hooks目录中建立pre-lock.bat文件,其内容类似于:
cscript.exe d:/pre-lock.vbs %1 %2 %3
%4 %5
其中:
cscript.exe 为解释器名称,最好是全路径,不行的话,也可以增加其路径到环境变量中;
d:/pre-lock.vbs 为vbs脚本文件所在路径
%1 %2 %3 %4 %5 为传入的参数,具体的脚本对应的不同参数和含义,后面的文章会介绍到。
对应的pre-lock.vbs中需要强调的是对于传入参数的处理,其内容类似于如下:
Set Args = WScript.Arguments
For I = 0 to Args.Count - 1
t=t+Args(I)
Next
关于SVN Hooks(钩子)的使用 (5)
利用VBS实现pre-commit对提交注释的检查(样例实现的是对长度的检查)。
1.钩子调用脚本内容
cscript.exe d:/pre-commit.vbs %1 %2
2.钩子处理脚本内容
'*******************************************************************************
'* NAME : pre-lock.vbs
'* AUTHOR : 杨瑞(OscarYang)
'* CREATED : 2010-3-19
'*
'* PURPOSE : 实现提交日志检查
'*
'*
'* pre-commit hook arguments:
'* [1] REPOS-PATH (the path to this
repository)
'* [2] TXN-NAME (the name of the txn
about to be committed)
'*******************************************************************************
'必须显式声明变量
Option Explicit
Private Args
Public wshShell,logExe
Set wshShell = WScript.CreateObject("WScript.Shell")
Set Args = WScript.Arguments
Dim MaxArgs
MaxArgs = 2
'调用主要处理流程
Call Main
'*******************************************************************************
'Main()过程定义
'*******************************************************************************
Private Sub Main()
Call ArgsErr
Call CheckLog
End Sub 'Main()
'*******************************************************************************
'出错退出函数,统一进行资源释放
'*******************************************************************************
private sub ErrExit()
Set Args = Nothing
Set wshShell = Nothing
Set logExec =Nothing
'错误返回
WScript.Quit (1)
end sub 'ErrExit()
'*******************************************************************************
'参数出错处理
'*******************************************************************************
Private Sub ArgsErr()
If (Args.Count
< MaxArgs) Then
'在系统信息中记录此错误信息(事件查看器)
wshShell.LogEvent 1, "缺少参数个数!"
'错误信息输出到客户端
WScript.StdErr.WriteLine ("缺少参数个数!")
'错误返回
Call ErrExit()
End If
End Sub 'ArgsErr()
'*******************************************************************************
'日志检查
'*******************************************************************************
Private Sub CheckLog()
Dim sReposPath,
sRevision, sCommand, sLog
sReposPath = cstr(Args(0))
sRevision = cstr(Args(1))
'合成svnlook 命令
sCommand = "svnlook log "
+ sReposPath + " -t " + sRevision
Set logExec
= wshShell.Exec(sCommand)
'读取svnlook log命令返回结果
Do While Not logExec.StdOut.AtEndOfStream
sLog = logExec.StdOut.ReadAll()
loop
if len(sLog)<=10 then
WScript.StdErr.WriteLine ("日志信息不足!")
Call ErrExit()
end if
End Sub
|