Windows下WSH/JS實現SVN伺服器鉤子指令碼阻止提交空日誌資訊和垃圾檔案

來源:互聯網
上載者:User

如何強制使用者在提交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 %2EXIT %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表示版本差異中新增的檔案。// 此Regex可匹配新增檔案中的“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)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.