Subversion 和 Mantis 的整合

http://kheresy.wordpress.com/2007/02/06/subversion-%E5%92%8C-mantis-%E7%9A%84%E6%95%B4%E5%90%88/

 

首先,Subversion(SVN) 是一套版本控制系統,可以用來管理程式的版本;而 Mantis 則是一套 bug tracking system,是用來追蹤、管理程式的 bug 的。而把版本控制和問題追蹤整合到一起的好處,就是可以在更新程式的時候,自動把相關訊息也整合到 bug tracking system 中。

而要做到兩者的整合,主要是透過 Subversion 有個叫做「hooks」的功能。透過這個功能,可以自己寫一些 script,甚至程式,讓 Subversion 在事件觸發時,自動執行指定的動作。而事件,則分為下面九種:

  • Pre-commit: Commit之前被執行
  • Pre-lock: 檔案鎖定之前被執行
  • Pre-revprop-change: 檔案庫被新增、修改或刪除前被執行
  • Pre-unlock: 檔案解除鎖定之前被執行
  • Post-commit: Commit之後被執行
  • Post-lock: 檔案鎖定之後被執行
  • Post-revprop-change: 檔案庫被新增、修改或刪除後被執行
  • Post-unlock: 檔案解除鎖定之後被執行

詳細說明,可以參考:[SVN] Hook scripts的使用方法

而 Heresy 是讓 script 在 post-commit 時執行。這樣做的原因,主要是因為在 Subversion 中,commit 時的資料(檔案、註解等等)的取得,似乎都得在 commit 完後,透過 svnlook 這個指令來完成。

先說明一下,Heresy 的環境是在 Linux 上,所以接下來的說明,也都是以 Linux 上的為主。而主要的修改,分成兩個部份:

  1. post-commit 的編寫
  2. mantis 的 checkin.php 的修改

post-commit

先講 post-commit 的編寫吧~方法滿簡單的,就是在 svnroot/hooks/ 的目錄下,建立一個檔名叫作「post-commit」的執行檔;這樣,SVN 就會在 commit 後,自動執行這個檔案了。

而 SVN 會給這個程式兩個參數,第一個($1)是 repository,應該算是 SVN 的位置吧~第二個($2)則是 revision,也就是版本。svnlook 這個程式,可以透過這兩個參數來取得大多數的資料。Heresy 所編寫的 post-commit 的檔案內容如下:

#!/bin/sh

PHP=/usr/bin/php

SCRIPTF=/.../svn2mantis.php

MANTIS=/.../mantisbt/core/checkin_svn.php 



$PHP $SCRIPTF $1 $2 |$PHP $MANTIS

其中,第二行到第四行,是在指定檔案的路徑。

  • $PHP 變數,是指定 PHP 執行檔的位置。
  • $SCRIPTF 是 Heresy 自己額外寫的一個 PHP script,主要是要把由 svnlook 取得的資料,做整理;同時,由於 svnlook 傳回來的中文是以字碼的形式傳回,所以在傳給 mantis 前,也要先做先處理。
  • $MANTIS 則是 mantis 提供的介面,檔名應該是叫做 checkin.php。不過由於 Heresy 一直沒辦法搞懂他的參數使用方法,所以後來就以原始版本為基礎,修改了一份。不過,這檔案的內容等第二部分再提了。

而實際執行上,也就只剩一行 $PHP $SCRIPTF $1 $2 |$PHP $MANTIS  了~實際上,就是先執行 PHP svn2mantis.php repository revision,然後再把他輸出到 stdout 的結果,pipe 給 $PHP $MANTIS,也就是 php checkin_svn.php 當成他的 stdin 了。

因此,比較重要的部分,應該就是 svn2mantis.php 的內容,和他輸出的東西了!下面就是他的內容:

<?

$REPOS = $argv[1];

$REV = $argv[2];



$rs = shell_exec( "svnlook info -r $REV $REPOS" );

$pat = explode( "n", $rs, 4 );

$author = $pat[0];

$comment = $pat[3];



if( $rsa = explode( "?\", $comment ) )

{

    $comment = "";

    foreach( $rsa as $val )

    {

        if( ereg( "(^[0-9]{3})(.*)", $val, $p ) )

            $comment .= chr( $p[1] ) . $p[2];

        else

            $comment .= $val;

    }

}



$ra = shell_exec( "svnlook changed -r $REV $REPOS" );

echo "$authorn$commentn---n<b>Modified Files:</b>n$ra"

?>

這份程式需要 repository 和 revision 兩個參數,一開始是從 $rs = shell_exec( "svnlook info -r $REV $REPOS" );  開始;PHP 會去執行 svnlook info -r $REV $REPOS,以取得 SVN 記錄中的資料,他的形式大致像下面一樣:

author

2007-02-05 09:14:58 +0800 (Mon, 05 Feb 2007)

85

issue #1

?228?184?173?230?150?135?231?154?132?230?184?172?232?169?166

第一行是修改者、第二行是時間,第三行的數字 Heresy 不知道是什麼;第四行開始,則就是在 commit 時輸入的註解部分。由於 checkin_svn.php 也有做了些修改,因此第一行必須要是修改者名稱,沒有問題(不過要注意,帳號要和 mantis 的一樣)。但是第二行的日期和第三行的未知欄位,實際上沒有必要也加到 mantis 的 bug 筆記裡;因此,Heresy 決定把他們濾掉。也就是透過 $pat = explode( "n", $rs, 4 );  這個指令,將 $rs 根據換行符號切割成四部分;如此,第一部分就會是修改者帳號($author = $pat[0]; )、第二部分就會是時間、第三部分就是那個未知欄位、第四部分就是註解($comment = $pat[3];)。

不過,在註解的地方可以看到一些「?/###」形式的資料,其實這些都是中文字被 SVN 轉換成 UTF-8 字碼存下來的結果;如果要輸入到 mantis 中,還需要再重組,才能顯示出來。Heresy 在這裡的做法,是根據「?」來切割字串($rsa = explode( "?\", $comment ));然後再依序檢察每個字串的字首是否為三個數字,如果是,就把他透過 chr() 這個函式轉換回字元,不是的話就直接放回來。如此,就可以將這些字碼,成功的轉回為中文字了~

而在來的 $ra = shell_exec( "svnlook changed -r $REV $REPOS" ); 則是再次呼叫 svnlook 來取得有更動的檔案資料,並一起附加到 mantis 裡面。也就是最後輸出的格式:"$authorn$commentn—n<b>Modified Files:</b>n$ra"。以上面的例子來說,最後的結果會是:

author

issue #1

中文的測試

---

<b>Modified Files:</b>

U a.cpp

而讓他 echo 出來的原因,則是因為 mantis 的 checkin.php 是由 stdin 將資料讀取進去的~所以,這份程式只需要把要給 mantis 的資料,全部用 echo 輸出到 STDOUT 就可以了。

 

 


checkin_svn.php

前面已經有提到了,由於 Heresy 搞不定 mantis 原來的 checkin.php 的參數,所以後來決定將 checkin.php 修改為 checkin_svn.php。主要修改的地方呢,就是帳號的取得方法。

首先,checkin.php 本來的帳號取得、確認方法如下:

# Check that the username is set and exists

$t_username = config_get( 'source_control_account' );

if ( is_blank( $t_username ) || ( user_get_id_by_name( $t_username ) =$

    echo "Invalid source control account ('$t_username').n";

    exit( 1 );

}

不過由於 Heresy 徹底放棄他的取得方式,因此就要把這部分都 mark 掉(前方加上「#」就可以了)。而修改後的方法,是和註解一樣,由 STDIN 來讀取。Heresy 的作法是把 STDIN 讀進來的第一行當作是帳號,也就是在原本的 while ( ( $t_line = fgets( STDIN, 1024 ) ) ) 前,加上下列程式:

# Check that the username is set and exists

$t_username = trim( fgets( STDIN, 1024 ) );

if ( is_blank( $t_username ) || ( user_get_id_by_name( $t_username ) ==$

    echo "Invalid source control account ('$t_username').n";

    exit( 1 );

}

其實呢,也就是將 $t_username = config_get( ‘source_control_account’ ); 改成$t_username = trim( fgets( STDIN, 1024 ) ); 而已;不過由於本來的程式位置有可能還沒定義 STDIN,所以 Heresy 為了保險起見,才把它拉到 while ( ( $t_line = fgets( STDIN, 1024 ) ) ) 的前面。

 


在完成上面共三個檔案的修改、編寫後,只要將它們放到對應的位置,應該就能正常運作了~post-commit 必須要放在 svnroot/hooks/ 下,而 svn2mantis.php 則沒有限定,不過放一起可能比較方便。checkin_svn.php 則是要放到 mantisbt 的 core 目錄中,和原來的 checkin.php 同一位置(當然,也可以直接修改 checkin.php)。

而實際使用上,在 commit 程式的時候,必須要手動輸入對應到 mantis 的 issue 編號(形式是「issue #1」);這樣,程式就會自動把這份註解附加到 mantis issue#1 的「Bug 筆記」中了~

 

你可能感兴趣的:(subversion)