エラーのあるファイルはコミットしない(Subversion編)
git編はこちら
先日はgitでやったんだけどせっかくだからsvnのコミットにもフックしてみた.
svnのほうで苦労したのは,フックのタイミングにしても,ローカルにファイルの実体のあるgitと違って,フックをかけるサーバと実体のあるクライアントマシンが別ってところで,コミットするタイミングで初めてサーバにファイルの実体が来るところ.
で,色々探ってみたものの,コミットされるファイルが一時的におかれる場所があったりするわけではないので,以下の要領でテストを走らせてみたりする*1.
- svnlook changed で変更されたファイル一覧を取得
- svnlook cat で変更されたファイルの中身を取り出し,一時ファイルに保存
- その一時ファイルに対して php -l
- 一時ファイルを削除する
- ファイルにエラーがあったら,コミットをうけつけず,エラーを表示して終了
流れをみただけで面倒くさそうでとってもうんざり...w
で,いったとおり,gitとの違いは,ファイルの実体がリポジトリのあるマシンと同じ場所にあるわけではない・・・というところで.
svnlookコマンドでは,そのコミットを「トランザクション」という単位で扱っているらしく,まぁこのへんはhelpとか見ればわるか.
PHP の Lint 動かすファイル
実体は以下のファイルです.これを,SVNENVのhooksとかに設置(たとえば,リポジトリ foo の /var/svn/foo/hooks/phplint とか).
#!/usr/bin/env php <?php $exitsatus = 0; $txn = escapeshellarg($argv[1]); $repo = escapeshellarg($argv[2]); $cmd = "/usr/bin/svnlook changed -t $txn $repo"; exec($cmd, $changed_files, $return); if (count($changed_files) > 15) { exit(0); } $result = array(); foreach ($changed_files as $file) { $filename = preg_replace("/^\s*[a-z]+\s+/i", "", $file); if (substr($filename, -4) == ".php") { $tmp_filename = "/tmp/svn-{$argv[1]}-" . str_replace("/", "--dir--", $filename); $esc_filename = escapeshellarg($filename); $cmd = "/usr/bin/svnlook cat -t $txn $repo $esc_filename > $tmp_filename"; // get contents of the file and out to tmp file exec($cmd, $cat_output, $return); // run lint exec("php -l " . escapeshellarg($tmp_filename) . " 2>/dev/null", $lint_output, $return); if ($return) { $result[] = str_replace( array("/tmp/svn-{$argv[1]}-", "--dir--", "\n"),- array(pack("c", 0x1B) . "[1;41m", "/", pack("c", 0x1B) . "[0m \n"), trim(implode("\n", $lint_output)) . "\n"); unset($lint_output); $exitsatus = 1; } unset($cat_output); unlink($tmp_filename); } } fwrite(STDERR, implode("\n", $result)); exit($exitsatus);
SVNENV/hooks/pre-commit を編集
以下の1行を追加*2.
/var/svn/foo/hooks/phplint $TXN $REPOS || exit 1
あ,上のほうで,
REPOS="$1" TXN="$2"
という行,これがコメントアウトされていたら,これはコメントを削除しておく.
問題点とか
ファイルが大量にコミットされたときに 生成→テスト→削除 を繰り返してると死んでしまう気がしたから,ファイル数が15以上のときはチェックしていない.
・・・のだけど,削除されたファイルとか,ディレクトリとかを判断していないので,大量のファイル削除+エラーのあるファイル1つとか,そういうコミットのされかたをしたときすり抜けちゃう.
まぁスクリプト自体改良の余地がありまくりだからそのへんはよしなに(ぉ
あとマージしたときとかどうなんの,って話もあるけど,どうなるかはためしてない...
参考にした
- 無駄に色とかつけたからw
- Unixの基礎知識ですが・・・・(´・ω・`) thx. @hamster0806