转:Windows下WSH/JS实现SVN服务器钩子脚本阻止提交空日志信息和垃圾文件
http://blog.csdn.net/caikanxp/article/details/8279921
如何强制用户在提交SVN时填写日志信息?
如果用户使用的都是TortoiseSVN客户端,可以给文件夹加上“tsvn:logminsize”属性。当用户使用TSVN提交此文件夹内的改动时,若日志信息长度不够,提交确定按钮会保持灰色不可用。不过此法对于非TSVN客户端便无效了。
作为更严格的限制,可以在Subversion服务器端强制必须填写日志信息,这时需用到pre-commit钩子脚本。
代码如下:
文件:pre-commit.bat
- svnlook log %1 -t %2 | CScript "%~dp0pre-commit.js"
- EXIT %ERRORLEVEL%
文件:pre-commit.js
- var log = WScript.StdIn.ReadAll();
- log = log.replace(/^\s+|\s+$/g, '');
- if (log.length < 1) {
- WScript.StdErr.WriteLine('【由于版本库管理员的设定,您必须输入非空的日志信息,用以描述本次提交的内容。】');
- WScript.Quit(1);
- }
脚本说明:
以上脚本文件都应该使用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.bat
- CScript "%~dp0pre-commit.js" %1 %2
- EXIT %ERRORLEVEL%
文件:pre-commit.js
- var WshShell = new ActiveXObject("WScript.Shell");
- var args = WScript.Arguments;
- var error = 0;
- // 用于将命令模版中的参数替换为WSH脚本参数,并包上用于兼容含空格路径的双引号
- function replaceArgs($0, $1) {
- return '"'+ args($1) + '"';
- }
- // 检测日志信息
- function checkLog() {
- var cmd = 'svnlook log %0 -t %1';
- cmd = cmd.replace(/%(\d)/g, replaceArgs);
- var log = WshShell.Exec(cmd).StdOut.ReadAll();
- log = log.replace(/^\s+|\s+$/g, '');
- if (log.length < 1) {
- WScript.StdErr.WriteLine('【由于版本库管理员的设定,您必须输入非空的日志信息,用以描述本次提交的内容。】');
- return 1;
- }
- return 0;
- }
- // 检测垃圾文件
- function fileFilter() {
- var cmd = 'svnlook changed %0 -t %1';
- cmd = cmd.replace(/%(\d)/g, replaceArgs);
- var oExec = WshShell.Exec(cmd);
- var stdout = oExec.StdOut;
- // svnlook changed 命令的输出格式可参考SVN手册。每行表示一个文件变动,行首字母A表示版本差异中新增的文件。
- // 此正则表达式可匹配新增文件中的“Thumbs.db”“desktop.ini”及部分Office临时文件
- var r = /^A.\s\s((?:[^\/]+\/)*(?:Thumbs\.db|desktop\.ini|~\$.*\.(?:docx?|xlsx?|pptx?)))$/i;
- var illegals = [];
- var m;
- while (!stdout.AtEndOfStream) {
- var line = stdout.ReadLine();
- if (m = line.match(r)) {
- illegals[illegals.length] = m[1];
- }
- }
- if (illegals.length) {
- WScript.StdErr.WriteLine('【下列文件被判定为垃圾文件而禁止提交,请排除后重新提交。】');
- WScript.StdErr.WriteLine('【如判定有误或有其它问题,请联系版本库管理员。】');
- WScript.StdErr.WriteLine(illegals.join('\n'));
- return 1;
- }
- return 0;
- }
- error += checkLog();
- error += fileFilter();
- WScript.Quit(error);
WSH的强大已足以应付这些问题。
而pre-commit钩子脚本的不足之处就是,需要等全部改动传输至服务器之后才会被调用。
当改动内容很多时,数据传输了半天,突然来了个提交被阻止岂不是很郁闷。
可以考虑将服务器端钩子脚本作为最终关卡,平时还是尽量优先以客户端的配置来进行操作过滤。
以上测试环境:Windows XP/2003,WSH 5.7,TortoiseSVN-1.7.10(Subversion 1.7.7)
转:Windows下WSH/JS实现SVN服务器钩子脚本阻止提交空日志信息和垃圾文件的更多相关文章
- Windows下免费、开源邮件服务器hMailServer
Windows下免费.开源邮件服务器hMailServer 一.Windows下搭建免费.开源的邮件服务器hMailServer 二.邮件服务器hMailServer管理工具hMailServer A ...
- windows下vue.js开发环境搭建教程
这篇文章主要为大家详细介绍了windows下vue.js开发环境搭建教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 最近,vue.js越来越火.在这样的大浪潮下,我也开始进入vue的学习行列中 ...
- 本地windows下搭建git的本地服务器
本地windows下搭建git的本地服务器 准备工作: 本地安装java环境,配置环境变量(略) 下载gitblit文件,百度一大堆 开始第一步: 减压gitblit压缩包到某个目录下,比如我在:H: ...
- Windows下基于http的git服务器搭建-gitstack
版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Windows下基于http的git服务器搭建-gitstack 本文地址:http: ...
- [日常] windows下使用vscode配合xebug调试php脚本
windows下使用vscode配合xebug调试php脚本 要下载有php_xebug.dll扩展的版本,最新版可能没有这个扩展,php7.3应该是有的,php7.3.4好像没有默认是不加载这个扩展 ...
- windows 7系统搭建本地SVN服务器的过程
Subversion是优秀的版本控制工具,其具体的的优点和详细介绍,这里就不再多说. 首先来下载和搭建SVN服务器. 现在Subversion已经迁移到apache网站上了,下载地址: http:// ...
- 如何在windows上安装部署设置SVN服务器
1 一.准备工作 1.SVN服务器:解压缩包,可以从官方网站下载最新版本. 2.SVN客户端:TortoiseSVN,即常说的小乌龟,是一个客户端程序,用来与服务器端通讯. 2 二.安装服务器和客 ...
- centos下搭建多项目svn服务器
svn是多人协作开发中的利器,是一个开放源代码的版本控制系统. 相比与git,他的操作更加简单,windows下有优秀的图形界面,并且支持的文件类型比较多. 本文讲述如何在linux下搭建一个svn服 ...
- windows下用php实现svn代码更新
windows下的服务器 没有登录权限,如何从svn更新代码 用php页面,实现更新代码 $cmd = '"C:\Program Files\TortoiseSVN\bin\Tortoise ...
随机推荐
- spring版本不兼容JDK问题
在实验书上Spring项目的时候出现一个问题,导入包和使用注释的时候eclipse出现报错. 导入包报错:The import org cannot be resolved 注释报错:componen ...
- (BruteForce)暴力破解经典题目总结
在算法竞赛中,很多问题是来不及用数学公式推导出来的.或者说根本就找不到数学规律,这时我们就需要使用枚举来暴力破解. 不过枚举也是需要脑子的,一味的暴力只能超时.因此我这里选择了几道mooc上经典的题目 ...
- Jackson对泛型的序列化和反序列化方法汇总
说明:Jackson对于简单泛型是可以正常操作的,但是如果对于太过于复杂的泛型类有时会不成功.目前还在找着更合适的Json库.不过这一点在dotnet原生方案JavaScriptSerializer可 ...
- TIdHTTPServer制作REST中间件
TIdHTTPServer制作REST中间件 使用DELPHI7+INDY9开发 // 陈新光 2017-2-21// LIS数据同步服务器// 浏览器输入:http://127.0.0.1:8000 ...
- 深入理解Activity启动流程(四)–Activity Task的调度算法
本系列博客将详细阐述Activity的启动流程,这些博客基于Cm 10.1源码研究. 深入理解Activity启动流程(一)--Activity启动的概要流程 深入理解Activity启动流程(二)- ...
- The bean 'xxx' could not be injected as a 'xxx'because it is a JDK dynamic proxy that implements
启动springboot项目的时候示以下错误 Error starting ApplicationContext. To display the conditions report re-run yo ...
- nyoj 1077 小博弈 【另类巴什博奕】
分析:分析当整除(a+b)的时候肯定是后者胜利,假设余数不等于0的时候.假设余数大于b肯定是前者胜利,否则后者胜利. 代码: import java.math.*; import java.util. ...
- SPFA 求带负权的单源最短路
int spfa_bfs(int s) { ///s表示起点. queue <int> q; memset(d,0x3f,sizeof(d)); ///d数组中存下的就是最短路径(存在的话 ...
- 解决Eclipse中C++代码显示Symbol 'std' could not be resolved的问题
第一次在Eclipse中写C++代码,写了一个简单的hello world程序,还没有等我编译.就报出了各种错误,但是这么简单的代码.怎么可能这么多错误.于是没有理会.编译执行后,能够正常输出!!!H ...
- AngularJS 实现 双击排序
关键代码:html <th class="col-md-3"><a href="" ng-click="desc('2',la=!l ...