如何强制用户在提交SVN时填写日志信息?如果用户使用的都是TortoiseSVN客户端,可以给文件夹加上“tsvn:logminsize”属性。
当用户使用TSVN提交此文件夹内的改动时,若日志信息长度不够,提交确定按钮会保持灰色不可用。
不过此法对于非TSVN客户端便无效了。
作为更严格的限制,可以在Subversion服务器端强制必须填写日志信息,这时需用到pre-commit 钩子脚本。
代码如下:文件:pre-commit.bat1svnlook log %1 -t %2 | CScript "%~dp0pre-commit.js"2EXIT %ERRORLEVEL%文件:pre-commit.js3var log = WScript.StdIn.ReadAll();4log = log.replace(/^\s+|\s+$/g, '');5if (log.length < 1) {6 WScript.StdErr.WriteLine('【由于版本库管理员的设定,您必须输入非空的日志信息,用以描述本次提交的内容。
】');7 WScript.Quit(1);8}脚本说明:以上脚本文件都应该使用ANSI编码,将它们保存于版本库存放处的hooks文件夹中即可。
Subversion在提交事务完成之前,会执行钩子脚本“pre-commit”,并根据其返回结果来决定是否提交事务。
在Windows平台中,钩子脚本应该是一个Windows可执行程序,如“pre-commit.exe”或“pre-commit.bat”。
当然可以通过某些程序语言编译生成一个程序,但实施起来过于复杂,实属小题大做。
而批处理由于本身的不足,不借助其它工具来判断非空日志也不那么简单。
网上有些例子就是使用批处理结合第三方程序来处理的,但前提是需要额外安装第三方程序。
不过在Windows下其实有更“绿色”的做法:使用WSH(Windows脚本宿主)脚本——Windows 时代更强大的“批处理”,可以支持JS,VBS等脚本语言。
虽然Windows中可以通过配置PATHEXT环境变量,将某些扩展名当做“可执行文件”的扩展名,直接敲入主文件名即可执行——比如需要执行WSH脚本“pre-commit.js”,在命令提示符下直接敲入“pre-commit”即可;但很遗憾,测试发现Subversion在需要触发pre-commit钩子脚本时,并不会直接触发“pre-commit.js”。
但我们仍然可以通过批处理脚本pre-commit.bat或pre-commit.cmd来间接调用WSH脚本。
批处理的参数:%0代表批处理脚本命令自身(的文件名),%1,%2,%3……依次代表批处理的参数。
批处理参数的扩展:“%~dp0”用来获取批处理脚本所在的文件夹绝对路径。
可以在命令提示符中输入“CALL /?”了解相关语法详情。
传入pre-commit钩子脚本的参数:第1为版本库位置,第2为提交事务的id。
CScript脚本宿主支持标准输入输出及错误流,而WScript脚本宿主则不支持。
Windows的默认脚本宿主为WScript,因此必须明确调用CScript。
(当默认宿主被改为CScript时,这种写法也是可行的“svnlook log %1 -t %2 |"%~dp0pre-commit.js"”)。
被调用的WSH脚本名需要重新围上双引号(%~批处理参数扩展会移除原始参数包围的双引号),以确保版本库路径中包含空格时不会出错。
钩子脚本执行流程:批处理脚本执行svnlook命令输出日志信息,通过管道将日志流输出到WSH脚本;WSH脚本读取流之后,判断日志内容是否为只含空白的字符串;WSH脚本执行完成后,退出码会被写入ERRORLEVEL环境变量,最后批处理脚本也使用此错误码退出。
若钩子脚本的退出码非0,提交事务便会被阻止,同时脚本输出到标准错误流的消息将被传送给SVN客户端进行提示。
上面的做法使用了管道流。
下面是另一种做法,直接将批处理收到的钩子脚本参数转给WSH脚本。
本例不仅阻止了仅含空白字符的日志消息,同时也阻止了一些常见垃圾文件的提交。
文件:pre-commit.bat9CScript "%~dp0pre-commit.js" %1 %210EXIT %ERRORLEVEL%文件:pre-commit.js11var WshShell = new ActiveXObject("WScript.Shell");12var args = WScript.Arguments;13var error = 0;1415// 用于将命令模版中的参数替换为WSH脚本参数,并包上用于兼容含空格路径的双引号16function replaceArgs($0, $1) {17return'"'+ args($1) + '"';18}1920// 检测日志信息21function checkLog() {22var cmd = 'svnlook log %0 -t %1';23 cmd = cmd.replace(/%(\d)/g, replaceArgs);24var log = WshShell.Exec(cmd).StdOut.ReadAll();25 log = log.replace(/^\s+|\s+$/g, '');26if (log.length < 1) {27 WScript.StdErr.WriteLine('【由于版本库管理员的设定,您必须输入非空的日志信息,用以描述本次提交的内容。
】');28return 1;29 }30return 0;31}3233// 检测垃圾文件34function fileFilter() {35var cmd = 'svnlook changed %0 -t %1';36 cmd = cmd.replace(/%(\d)/g, replaceArgs);37var oExec = WshShell.Exec(cmd);38var stdout = oExec.StdOut;39// svnlook changed 命令的输出格式可参考SVN手册。
每行表示一个文件变动,行首字母A表示版本差异中新增的文件。
40// 此正则表达式可匹配新增文件中的“Thumbs.db”“desktop.ini”及部分Office临时文件41var r =/^A.\s\s((?:[^\/]+\/)*(?:Thumbs\.db|desktop\.ini|~\$.*\.(?:docx?|xlsx?|pptx?)))$ /i;42var illegals = [];43var m;44while (!stdout.AtEndOfStream) {45var line = stdout.ReadLine();46if (m = line.match(r)) {47 illegals[illegals.length] = m[1];48 }49 }50if (illegals.length) {51 WScript.StdErr.WriteLine('【下列文件被判定为垃圾文件而禁止提交,请排除后重新提交。
】');52 WScript.StdErr.WriteLine('【如判定有误或有其它问题,请联系版本库管理员。
】');53 WScript.StdErr.WriteLine(illegals.join('\n'));54return 1;55 }56return 0;57}5859error += checkLog();60error += fileFilter();61WScript.Quit(error);WSH的强大已足以应付这些问题。
而pre-commit钩子脚本的不足之处就是,需要等全部改动传输至服务器之后才会被调用。
当改动内容很多时,数据传输了半天,突然来了个提交被阻止岂不是很郁闷。
可以考虑将服务器端钩子脚本作为最终关卡,平时还是尽量优先以客户端的配置来进行操作过滤。
以上测试环境:Windows XP/2003,WSH 5.7,TortoiseSVN-1.7.10(Subversion 1.7.7)11111111111111111111111111111用SVN钩子强制提交日志和限制提交文件类型分类:SoftwareProject2013-01-31 19:38 2625人阅读评论(2) 收藏举报SVN钩子强制提交日志作者:朱金灿来源:/clever101Subversion本身有很好的扩展性,用户可以通过钩子实现一些自定义的功能。
所谓钩子实际上是一种事件机制,当系统执行到某个特殊事件时,会触发我们预定义的动作,这样的特殊事件在Subversion里有很多。
那么SVN的钩子有哪些呢?下面简单介绍下:服务器钩子:锁定的2种pre-lock钩子在每次有人尝试锁定文件时执行。
可以防止完全锁定,或者用来创建控制哪些用户可以锁定哪些路径的复杂策略。
如果钩子发现已存在锁,也可以决定是否允许用户“窃取”这个锁。
post-lock在路径锁定后执行。
通常用来发送锁定事件邮件通知。
解锁的2种pre-unlock钩子在某人企图删除一个文件上的钩子时发生。
可以用来创建哪些用户可以解锁哪些文件的策略。
制定解锁策略非常重要。
如果用户A 锁定了一个文件,允许用户B 打开这个锁?如果这个锁已经一周了呢?这种事情可以通过钩子决定并强制执行。
post-unlock在一个或多个路径已经被解锁后执行。
通常用来发送解锁事件通知邮件。
提交的3种start-commit它在提交事务产生前已运行,通常用来判定一个用户是否有权提交。
版本库传给该程序两个参数:到版本库的路径,和要进行提交的用户名。
如果程序返回一个非零值,会在事务产生前停止该提交操作。
如果钩子程序要在stderr中写入数据,它将排队送至客户端。
pre-commit在事务完成提交之前运行,通常这个钩子是用来保护因为内容或位置(例如,你要求所有到一个特定分支的提交必须包括一个bug追踪的ticket号,或者是要求日志信息不为空)而不允许的提交。
版本库传递两个参数到程序:版本库的路径和正在提交的事务名称,如果程序返回非零值,提交会失败,事务也会删除。
如果钩子程序在stderr中写入了数据,也会传递到客户端。