pre-commitフックを作ってみる。

リポジトリ作成時に作られたpre-commit.tmplにいろいろ説明が書いてあるので要約すると。

  • Subversionトランザクションがコミットする前に呼ばれる。
  • 2つの引数とともに呼ばれる。
    1. リポジトリパス
    2. トランザクション
  • 'pre-commit'というファイル名でhooksに置く。(Windows環境の場合は、pre-commit.batや、pre-commit.exe)
  • コミットさせたくないときは、0以外を返して終了させる。
  • svnlookコマンドを使っていろいろ情報を取得する。


まず、svnlookコマンドを使って、どんな情報がとれるか見たいので。
以下のスクリプトを作成し、pre-commitというファイル名で、/home/svn/repository/hooksに置く。

#!/bin/sh
REPO=$1
TXN=$2

SVNLOOK=/usr/bin/svnlook
echo "--------------------" >> /home/svn/message.txt
$SVNLOOK date -t "$TXN" "$REPOS" >> /home/svn/message.txt
echo "$REPOS" >> /home/svn/message.txt
echo "$TXN" >> /home/svn/message.txt
$SVNLOOK author -t "$TXN" "$REPOS" >> /home/svn/message.txt
$SVNLOOK changed -t "$TXN" "$REPOS" >> /home/svn/message.txt
$SVNLOOK dirs-changed -t "$TXN" "$REPOS" >> /home/svn/message.txt
$SVNLOOK tree -t "$TXN" "$REPOS" >> /home/svn/message.txt
$SVNLOOK info -t "$TXN" "$REPOS" >> /home/svn/message.txt

exit 0

そして、作業コピー上のtags/tag_050125/hoge1.txtをコミットしてみる。
すると以下のようなメッセージが出力された。

--------------------
2005-01-25 11:01:52 +0900 (Tue, 25 Jan 2005) ・・・ svnlook date
/home/svn/repository   ・・・リポジトリパス($REPOS)
s  ・・・トランザクション名($TXN)
masakas  ・・・ユーザ名(svnlook author)
U   tags/tag_050125/hoge1.txt  ・・・変更のあったパス(svnlook changed)
tags/tag_050125/  ・・・変更のあったディレクトリ(svnlook dirs-changed)
/ ・・・ svnlook tree
 trunk/
  hoge1.txt
  hoge2.txt
 branches/
 tags/
  tag_050125/
   hoge1.txt
   hoge2.txt
masakas ・・・ svnlook info
2005-01-25 11:01:52 +0900 (Tue, 25 Jan 2005)
11
fadfafafafa

dirs-changedを使えば、ディレクトリごとのアクセス制御を実現できそう。
一応、複数のファイルが同時にコミットされた場合にどういうログがでるか確認しておく。

--------------------
2005-01-25 11:15:25 +0900 (Tue, 25 Jan 2005)
/home/svn/repository
u
masakas
U   tags/tag_050125/hoge1.txt ・・・ svnlook changedの結果
U   tags/tag_050125/hoge2.txt
U   trunk/hoge1.txt
U   trunk/hoge2.txt
tags/tag_050125/ ・・・ svnlook dirs-changedの結果
trunk/
・・・以下略・・・

ということで、dirs-changedの結果の中に、tagsディレクトリ以下のディレクトリがある場合は、異常終了するスクリプトを書いてみる。

#!/bin/sh

REPOS="$1"
TXN="$2"

SVNLOOK=/usr/bin/svnlook
CHANGED_DIRS=`$SVNLOOK dirs-changed -t $TXN $REPOS`

if echo $CHANGED_DIRS | grep "^tags" > /dev/null
then
  echo -e "tags directory is read-only!\n$CHANGED_DIRS" 1>&2
  exit 1
fi

exit 0

これを、hooksに置いて、tagsの中にあるファイルをコミットしようとすると怒られるようになる。
これで、とりあえずやりたいことができるようになったかと。