hook は、新しいリビジョンの生成やバージョン化されていない属性の修正といったリポジトリに対するイベントをきっかけに実行されるプログラムです。フックのそれぞれは、どんなイベントが起こったか、何を対象にして操作をしたのか、そのイベントを起こした人のユーザ名などの情報を扱うことができます。フックの出力や戻り値によってフックプログラムは処理を続けたり終了したり、いくつかの方法で中断したりします。hooks サブディレクトリには、デフォルトではさまざまなリポジトリフックのテンプレートがあります。
Subversion リポジトリには9 種類のフックが実装されています。
これは、コミットトランザクションが作られる前に実行されます。典型的にはユーザがコ ミット権限があるかどうかを決定するのに使われます。リポジトリはこのプログラムに二つの引数を渡 します: リポジトリへのパスと、コミットしようとしているユーザ名です。もしプログラムがゼロ以外 の値を返した場合、コミットはランザクションが作られる前に中止します。フックが標準エラー出力に データを書き込むと、それは適切なデータ形式でクライアントに戻されます。
これは、トランザクションの完結後、実際のコミットの前に実行されます。典型的には、コ ミットの内容や場所(たとえばあなたのサイトでは、すべてのコミットはバグトラッカーの管理番号を 含むようなブランチに対してしなくてはならないとか、ログメッセージが空であってはいけないという ようなポリシーがあるかも知れません) によってコミットを許可しないようにするために使われます。 リポジトリはこのプログラムに二つの引数を渡します: リポジトリのパスと、コミットされるはずのト ランザクションの名前です。もしこのプログラムがゼロ以外の値を返した場合、コミットは中断され、 トランザクションは削除されます。フックが標準エラー出力にデータを書き込むと、それは適切なデー タ形式でクライアントに戻されます。 Subversion の配布パッケージは、アクセス制御を細かく実装するためにpre-commit から呼び出すことの できるいくつかのアクセス制御スクリプトを含んでいます(Subversion ソースツリーのtools/hook- scripts ディレクトリにあります)。他の選択子はApache のhttpd モジュールであるmod authz svn を使うもので、個別のディレクトリに対する読みこみ書き込みのアクセス制御をすることができます Subversion の今後のバージョンでは、ファイルシステムに直接アクセス 制御リスト(ACL) を実装する計画があります。
これはトランザクションがコミットされ、新しいリビジョンが作られた後に実行されます。 ほとんどの人はこのフックをリポジトリのコミットやバックアップに関する連絡メールを送るのに使 います。リポジトリはこのプログラムに二つの引数を渡します:リポジトリのパスと、今回作られた新 しいリビジョン番号です。このプログラムの終了コードは無視されます。 Subversion 配布パッケージはmailer.py とcommit-email.pl スクリプトを含んでいます。(Subversion ソースツリーのtools/hook-scripts/ ディレクトリにあります) それは、今回のコミットに付け られた説明をメールするために使うことができます。このメールの内容は変更されたパスの一覧、コ ミットに付けたログメッセージ、コミットした人、コミットの時刻、そして、コミットの変更部分の GNU のdiff スタイルでの表示です。 Subversion が提供するほかの役に立つツールはhot-backup.py スクリプトです。(Subversion ソースツ リーのtools/backup/ ディレクトリにあります)。このスクリプトはSubversion リポジトリのオン ラインバックアップをとるので、(今後はBerkeleyDB データベースのバックエンドとしてサポートす る予定です) リポジトリのアーカイブ化や緊急リカバリのためのコミットごとのスナップショットを作 るのに使うことができます。
Subversion のリビジョン属性はバージョン化されていないので、そのような属性 に対する修正は(たとえば、コミットメッセージ属性であるsvn:log ) 以前の属性値を永久に上書きし てしまいます。データはここで失われてしまうので、Subversion はこのフック(そしてこの相補的な部 分であるpost-revprop-change) を使って、必要に応じてリポジトリ管理者がこのような変更記録 を残すことが出来ます。バージョン化されていない属性データを失うことに対するあらかじめの警告 の意味で、Subversion クライアントはこのフックが自分のリポジトリに実装されているのではない限り リビジョン属性をリモートに変更することは決してありません。 このフックはリポジトリにそのような変更が発生する直前に実行されます。リポジトリはこのフックに 四つの引数を与えます: リポジトリのパス、修正される属性があるリビジョン、変更しようとしている、 認証の済んだユーザ名、そして属性の名前自身です。
以前に指摘したように、このフックはpre-revprop-change フックのもう 片割れです。実際、神経質な人のことを考えて、このスクリプトはpre-revprop-change フックが 存在しなければ実行されません。両方のフックが存在する場合、post-revprop-change フックは リビジョン属性が変更された直後に実行されます。典型的には、変更された属性の新しい値をメール するのに使います。リポジトリは四つの引数をこのフックに渡します: リポジトリへのパス、属性があ るリビジョン番号、変更しようとしている認証済みのユーザ名称、そして属性の名前自身です。 Subversion 配布パッケージはpropchange-email.pl スクリプトを含んでいます。(これは、tools/ hook-scripts/ ディレクトリにあります) これは、リビジョン属性の変更についての詳細をメール するために使われます。Email はリビジョンと変更属性の名前、変更した人、そして新しい属性値です。
このフックは誰かがファイルをロックしようとしたときには常に実行されます。これはロック を防ぐのにも利用するこどかできますし、誰が特定のパスに対してロックできるかという複雑なポリ シーを正確に設定するのにも使えます。フックが既にロックがかかっていることに気づいた場合には ユーザはそのロックが外れるのを「待つ」かどうかを決めることもできます。リポジトリはフックに 三つの引数を渡します: リポジトリへのパス、ロックされているパス、そしてロックしようとしている ユーザです。プログラムが0 ではない値で終了するとロック処理は異常終了し、標準エラー出力への メッセージはすべてクライアント側に転送されます。
このロックはパスがロックされた後に実行されます。ロックされたパスはフックの標準入力 に渡されるほか、フックはまた二つの引数も受け取ります: リポジトリへのパスと、ロックを実行した ユーザです。その後フックはemail 通知を送ったり好きな方法で出来事を記録したりすることが自由に できます。ロックはすでに実行されてしまっているのでフックの出力は無視されます。
このフックは誰かがファイルのロックを取り除こうとした時には常に実行されます。これを 使ってどのユーザがどの特定のパスに対してロック解除できるかを決めるポリシーを作るために利用で きます。ロック解除に関するポシリーを決めることは非常に重要です。ユーザA がファイルをロック した場合、B はそのロックを解除できるでしょうか? ロックが一週間以上も前のものだった場合は? こ れらのことはフックによって決定され、強制することができます。リポジトリは三つの引数をフック に送ります: リポジトリのパス、ロック解除されるパス、ロックを解除しようとしているユーザ。プロ グラムが0 以外の終了値を返した場合、ロック解除の処理は異常終了し標準エラーへの出力はすべて クライアント側に転送されます。
このフックはパスがロック解除された後で実行されます。ロックが解除されたパスはフッ クの標準入力に渡され、その他にも二つの引数がフックに渡されます: リポジトリのパスと、ロックを 解除したユーザです。その後フックはemail 通知を送ったり、好きな方法で出来事を記録することがで きます。ロックの解除は既に起こってしまっているのでフックの出力は無視されます。
D: cd \TracLight CScript //Nologo svnmail.vbs %1 %2
' -- 定数宣言 Const CDO_SENDUSINGMETHOD = "http://schemas.microsoft.com/cdo/configuration/sendusing" Const CDO_SENDUSINGPORT = 2 Const CDO_SMTPSERVER = "http://schemas.microsoft.com/cdo/configuration/smtpserver" Const CDO_SMTPSERVERPORT = "http://schemas.microsoft.com/cdo/configuration/smtpserverport" Const CDO_SMTPCONNECTIONTIMEOUT = "http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout" ' SMTPサーバ Const SMTP_SERVER = "smtpserver" ' 送信先のメールアドレス保存ファイル Const MAIL_LIST_PATH = "D:\TracLight\mail.txt" ' 送信元アドレス Const MAIL_FROM = "mail@mail.co.jp" ' -- Main ' 送信先アドレスの取得 Set objFSO = WScript.CreateObject("Scripting.FileSystemObject") Set objFile = objFSO.OpenTextFile(MAIL_LIST_PATH, 1) Do Until objFile.AtEndOfStream 'カンマ付け strAddr = strAddr & objFile.ReadLine & "," Loop objFile.Close strAddr = left(strAddr,len(strAddr)-1) Set objArgs = WScript.Arguments 'リポジトリパス strRepPath = objArgs(0) 'リビジョン strRepRevision = objArgs(1) WScript.echo strRepPath Set objShell = WScript.CreateObject("WScript.Shell") ' Author 情報の取得 Set objExec = objShell.Exec("svnlook author " + strRepPath + " -r " + strRepRevision) strAuthor = objExec.StdOut.ReadLine Set objExec = Nothing ' ログメッセージの取得 Set objExec = objShell.Exec("svnlook log " + strRepPath + " -r " + strRepRevision) Do Until objExec.StdOut.AtEndOfStream strLogMessage = strLogMessage & objExec.StdOut.ReadLine & vbCrLf Loop ' 変更ディレクトリの取得 Set objExec = objShell.Exec("svnlook dirs-changed " + strRepPath + " -r " + strRepRevision) Do Until objExec.StdOut.AtEndOfStream s = objExec.StdOut.ReadLine strDirsChanged = strDirsChanged & s & vbCrLf If strDirsChangedSubject = "" Then strDirsChangedSubject = s Else strDirsChangedSubject = strDirsChangedSubject & "," & s End If Loop ' サブジェクト用の変更ディレクトリは、40文字で切る If Len(strDirsChangedSubject) > 40 Then strDirsChangedSubject = Left(strDirsChangedSubject, 40) & "...." End If ' 変更ファイルの取得 Set objExec = objShell.Exec("svnlook changed " + strRepPath + " -r " + strRepRevision) Do Until objExec.StdOut.AtEndOfStream strChanged = strChanged & objExec.StdOut.ReadLine & vbCrLf Loop ' メール設定 Set objConfig = CreateObject("CDO.Configuration") Set Fields = objConfig.Fields With Fields .Item(CDO_SENDUSINGMETHOD) = CDO_SENDUSINGPORT .Item(CDO_SMTPSERVER) = SMTP_SERVER .Item(CDO_SMTPSERVERPORT) = 25 .Item(CDO_SMTPCONNECTIONTIMEOUT) = 10 .Update End With ' メール送信 Set objMsg = CreateObject("CDO.Message") Set objMsg.Configuration = objConfig ' メールの BODY を作成 strBody = strBody & "-- Author/Date -----------------------------------" & vbCrLf strBody = strBody & "Author : " & strAuthor & vbCrLf strBody = strBody & "Date : " & Date() & vbCrLf strBody = strBody & vbCrLf strBody = strBody & "-- Log Message -----------------------------------" & vbCrLf strBody = strBody & strLogMessage & vbCrLf strBody = strBody & "-- Changed Directories ---------------------------" & vbCrLf strBody = strBody & strDirsChanged & vbCrLf strBody = strBody & "-- Changed Files ---------------------------------" & vbCrLf strBody = strBody & "※ A:追加、U:更新、D:削除" & vbCrLf strBody = strBody & strChanged & vbCrLf strBody = strBody & vbCrLf strBody = strBody & vbCrLf strBody = strBody & "※ 注意 " & vbCrLf strBody = strBody & " このメールは自動送信されたメールです。" & vbCrLf strBody = strBody & " アドレスは架空の物を使用していますので返信しないでください。" & vbCrLf ' メールヘッダの成型 objMsg.From = MAIL_FROM objMsg.To = strAddr objMsg.Subject = "[svn commit message] " + strRepPath + " : " + strRepRevision objMsg.TextBody = strBody ' メール送信処理 objMsg.Send