Git Companion Scripts
まだしつこくマルチプラットフォーム開発環境における Git のエンコーディングチェック についてやってます。とはいっても、ほとんどもう Perl の話になっているのですが。
いろいろファイルが増えてきたので、新しく Github に Git Companion Scripts というリポジトリを作ってまとめました。これの使い方について書きたいと思います。
2012/05/11 更新: git check-attr による Git 属性の活用 において pre-commit-encoding
スクリプトを改良しましたので、この記事の使用法を改訂しました。
概要
Git Companion Scripts は Git の標準環境で追加のソフトウェアのインストールなしに使える便利なスクリプト集です。Linux や Unix の Git だけでなく Git for Windows (msysgit) もサポートしています。
使用法
とりあえずいますぐ利用可能なスクリプトは次のふたつです。
hooks/pre-commit-encoding
このスクリプトは Git のコミット前にテキストファイルのエンコーディングと改行文字をチェックする pre-commit フックスクリプトです。Git リポジトリ中に .git/hooks/pre-commit
として名前を変えて設置すればすぐに使えます。
チェックの対象となるファイルの指定は .gitattributes
ファイルで encoding
属性を設定することによって行います。 encoding
属性の値として許可するエンコーディングをコンマで区切って並べてください。
属性の値を指定しない場合はデフォルトのエンコーディングを使用します。これはスクリプトへの引数またはスクリプト中の変数 $default_allowed
により指定できます。
エンコーディングとしては次のような Emacs 的表記を受け付けます。
ascii
(ASCII 改行文字任意)shiftjis
(シフト JIS 改行文字任意)7bit-jis
(7bit JIS 改行文字任意)utf-8
(UTF-8 改行文字任意)utf-8-unix
(UTF-8 改行文字 LF)utf-8-with-signature-dos
(UTF-8 BOM 付き 改行文字 CRLF)
エンコーディング表記は様々なエイリアスが存在します。詳しくは Perl のドキュメント Encode::Supported を参照してください。
.gitattributes
ファイルの記述例を次に示します。文法についてはマニュアル (git help attributes
) を参照してください。
# *.log ファイルには ASCII エンコーディングを設定する *.log encoding=ascii # *.txt ファイルにはデフォルトエンコーディングを設定する *.txt encoding # Visual C++ が正しく受け付けるエンコーディングを設定する [attr]msvc encoding=ascii-dos,utf-8-with-signature-dos *.c msvc *.h msvc *.cpp msvc
コミットするファイルに不正なエンコーディングが含まれていると、次のように git commit
が失敗します。
$ git add hoge.c $ git commit hoge.c: utf8-unix (ascii-dos,utf-8-with-signature-dos) Commit aborted! (Use "git commit --no-verify" to skip this)
一時的にエンコーディングチェックを無効にしたい場合は git commit --no-verify
を使うと pre-commit スクリプトの実行をスキップできます。
utils/ipconv
このユーティリティスクリプトは -e
オプションで指定したエンコーディング、またはスクリプト中の変数 $output_encoding
で指定したエンコーディングに、引数で指定したファイルを上書き一括変換します。元のファイルは .orig
の拡張子をつけた名前でバックアップされます。
エンコーディングの指定は pre-commit-encoding
スクリプトと同様な Emacs 的表記を使います。 utf-8
のように改行コードを指定しなかった場合、改行コードはいじらず素通しします。
マルチプラットフォーム開発環境
このスクリプトが想定している、処理系が受け付けるファイルエンコーディングの違いが問題になるようなマルチプラットフォーム開発環境について説明します。
たとえば Visual C++ と GCC でコンパイルできる共通のソースファイルを書こうとするとき、日本語の文字コードとしては UTF-8 を使いたくなると思いますが、各処理系が受け付けるエンコーディングには次のような要件があります。
UTF-8 | 改行文字 | |
---|---|---|
Visual C++ | BOM が必要 | CRLF のみ |
GCC (4.4 以降) | BOM の有無は問わない | LF または CRLF |
たいていのプロジェクトでは一番融通のきかない Visual C++ に合わせ、リポジトリ中のソースコードのエンコーディングは UTF-8 BOM つき・改行コード CRLF (または LF で core.autocrlf
の自動変換機能を使用) で統一することが多いと思います。
このようなエンコーディングの強制については Git では clean/smudge フィルタ を使って自動変換する方法などが考案されていますが、これは意図せぬ変換が起きて問題になりまくる気がしたので、 pre-commit フック pre-commit-encoding
でエラーを出してプログラマ自身に正しいファイルに変換させるほうがよいと思いました。
しかしながら、そこですぐに nkf
とか iconv
とか set bomb
とか C-x C-m C-f utf-8-with-signature-unix
とかが出てくるプログラマは少ないと思うので、簡単にエンコーディングと改行文字と BOM の有無が一括変換できるスクリプト ipconv
を用意することにしたのでした。
どちらのスクリプトも単一ファイルで Git が動く環境であれば動くので、ソースコードリポジトリに同梱して使ってもらえばと思います。
おわりに
当初はあまり凝る気はなかったのですが、標準的 Git 環境で動くという制約の下で Perl スクリプトの実験を繰り返すうちにだんだん面白くなってきてしまい、最終的にはテストスイートまで書いてしまいました。
テストのフレームワークには shUnit2 というものを初めて使ってみました。シェルスクリプトでファイルひとつを source するだけで使えるので大変使い勝手がよいです。
バグ報告などを歓迎します。普段 Perl を書いておらずへぼいスクリプトなので、悪い作法の指摘などをしていただけるとうれしいです。
2012/04/22 18:56:00 JST