気ままなつぶやき

おべんきょしたこととか

【svn】リポジトリフック 〜pre-commit〜

どこにでも書いてるけど、自分めも。

svnredmineで連携して、
コミットメッセージの中にredmineのチケット番号が入ってなかったら
コミットできないようにしたい

ていう要望がありますた。

よくある話だけど、今回は、
1つのリポジトリの中の任意のプロジェクトだけコミットフックを適用したい
ってやつ。

今回はredmineとの連携はさておき、イラネッ(゚Д゚=)ノ⌒゚
同リポ内でコミットの制御を色々実験してみたー。

いつもお世話になっているこの本を参考にしてます(о´▽`о)♪
実用 Subversion 第2版

下準備

testリポジトリの下に、

  • svn_test:特に制限なく利用が可能になる
  • svn_hook_test:fileディレクトリ配下は、キーワード「pnsk」をコミットメッセージにつけないとエラー

という2つのプロジェクトを作成する。

プロジェクトのコミット

自分のローカルPCでテスト用プロジェクトを作成して
リモートsvnにコミットー。

こんな感じで。。

$mkdir svn_hook_test
$cd svn_hook_test
$mkdir file
$vim test.txt
(編集)
$svn import svn_hook_test http://svn.pnsk.jp/svn/test/svn_hook_test -m "first commit."

リモートリポにsvn_hook_testにimportしただけだと
手元にあるローカルのsvn_hook_testはバージョン管理されないのでチェックアウトし直す

$rm -r svn_hook_test
$svn co http://svn.pnsk.jp/svn/test/svn_hook_test/

あい。svn_testも同様にして準備おk

svnのフックスクリプト

準備ができたので、リモートsvnサーバでフックスクリプトを作成する

svnのフックスクリプトは

${SVN_HOME}/repos/test/hooks

にある

テンプレートが色々あるお

$ ls
post-commit.tmpl          post-unlock.tmpl  pre-revprop-change.tmpl
post-lock.tmpl            pre-commit.tmpl   pre-unlock.tmpl
post-revprop-change.tmpl  pre-lock.tmpl     start-commit.tmpl

今回使いたいのは、pre-commitフック。

pre-commit

コミット完了直前に一行されるフックスクリプト。
コミットの内容などから、コミット制御ができる。

pre-commitの作成

テンプレートをコピーして実行権限を追加

$cp pre-commit.tmpl pre-commit
$ chmod +x pre-commit
$ls  -l pre-commit
-rwxr-xr-x 1 svn svn 3436 112 11:25 pre-commit

pre-commitは引数で

リポジトリのパス
・コミットトランザクションの番号

がゲットできるので、それをつかって、svnlookコマンドでごにょごにょしまふ

svnlookコマンド

リポジトリ内の、リビジョンやトランザクションの確認をするためのコマンド
今回使うのはトランザクション周りのコマンド(-tを使う)。


文法的にはこんな感じ

$svnlook dirs-changed -t [トランザクション番号] [リポジトリのパス]

例えば、svn_hook_test/file/test.txtを修正、コミットすると
変更されたディレクトリはsvn_hook_test/file/となる。

このコマンドは、
コミットログの制御を適用するプロジェクトをハンドリングするために使う


  • 変更のあったコミットの、コミットメッセージの取得
$svnlook log -t [トランザクション番号]

コミットメッセージの内容が取得できる

フックスクリプト

svn_hook_testプロジェクトのfilerディレクトリに配下のコミットについてのみ
コミットログに"pnsk"というキーワードを入れないとエラーを返すようにする

#!/bin/sh

#-----------------------------------------
# SVN PARAMETERS
#-----------------------------------------
REPOS="$1"
TXN="$2"

#-----------------------------------------
# COMMAND
#-----------------------------------------
SVNLOOK=/usr/local/svn/bin/svnlook
CHANGED_DIRS=`${SVNLOOK} dirs-changed -t "${TXN}" "${REPOS}"`
COMMIT_LOG=`${SVNLOOK} log -t "${TXN}" "${REPOS}"`
CHECK_DIR="^svn_hook_test/file"
KEYWORD="pnsk"

#-----------------------------------------
# CHECK COMMIT_MESSAGE in CHECK_DIR
#-----------------------------------------
if echo ${CHANGED_DIRS} | grep "${CHECK_DIR}" > /dev/null
then
        if !(echo ${COMMIT_LOG} | grep ${KEYWORD} > /dev/null)
        then
                 echo -e "you need keyword" ${KEYWORD} > &2
                 exit 1
        fi
fi
exit 0

動作テスト

自分のPCからリモートsvnリポジトリへの動作確認

同リポ内のsvn_testプロジェクト

キーワードのチェックはないので、正常にコミットできる

$ pwd
{LOCAL_HOME}/workspace/direct/svn_test
$ vim file/test.txt 
$ svn commit -m "test"
Sending        file/test.txt
Transmitting file data .
Committed revision 53.

svn_hook_testプロジェクトのnot_hook_fileディレクトリ

キーワードのチェックはないので、正常にコミットできる

$ pwd
{LOCAL_HOME}/workspace/direct/svn_hook_test
$ vim not_hook_file/test.txt 
$ svn commit -m "test"
Sending        not_hook_file/test.txt
Transmitting file data .
Committed revision 52.

pnskキーワードをコミットログに入れなくてもコミットでけた

svn_hook_testプロジェクトのfileディレクトリ

  • コミットログにpnskキーワードを入れた場合
$ pwd
{LOCAL_HOME}/workspace/direct/svn_hook_test
$ vim file/test.txt 
$ svn commit -m "test pnsk"
Sending        file/test.txt
Transmitting file data .
Committed revision 51.
  • コミットログにpnskキーワードを入れなかった場合
$ svn commit -m "test "
Sending        file/test.txt
Transmitting file data .svn: Commit failed (details follow):
svn: Commit blocked by pre-commit hook (exit code 1) with output:
you need keyword pnsk

エラーになった



今日はここまで。


ちゃんちゃん