关于SVN Hooks(钩子)的使用 (1) .

tags:svn,hooks,svn钩子,Tortoisesvn钩子

由于工作需要,在svn中经常需要使用到svn hooks,把一些常用的记录在这里。

1.什么是svn hooks?

服务器钩子:

经常提到的svn hooks是一组“外挂”脚本程序,是svn提供的一组由svn事件触发的特别有用的程序。这些程序在服务器端执行,可以提供svn之外的一些附加功能。钩子可以调用批处理文件、可执行文件或者一些类似于perl、python等的脚本。


客户端钩子:

如果使用tortoise svn(海龟svn,常用的svn客户端),它也提供钩子机制,这些和svn hooks有本质区别,它是在本地(客户端)执行的。


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

编写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,否则脚本无法运行。

3.依次设定pre-commit和post-commit脚本

4.执行一次提交,结果如下


发现先执行start-commit,然后是pre-commit,最后是post-commit

另外如果感兴趣可以再进行深入一步的分析,你可以发现:

start-commit是在通过菜单触发“提交”活动后,弹出“提交”对话框前执行;

pre-commit是在点击“提交”对话框上的“确定”时执行,即真正的提交活动时执行;

post-commit是在提交活动结束时执行。

在第一篇中提到过,服务器钩子有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.客户端和服务器端触发序列如何?

如下图。

说句实话,对于服务器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

利用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,logExec

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

原文地址:https://www.cnblogs.com/aaa6818162/p/2612606.html