「入門TortoiseHg+Mercurial」発売中(詳細は「執筆情報」参照)


文字コード

注意: 他環境での Mercurial インストール経験があっても、 別環境で Mercurial をインストールする際には、 以下の節を一通り確認することを強くお勧めします。

Mercurial での日本語利用における文字コードの扱いに関してまとめてみました。

備考: ここでは、文字集合体系とその符号化に関する包括的な領域を、 慣習的な点から「文字コード」と表現しています。

Mercurial における文字コード設定の概要

Mercurial が履歴を記録する際には、 ログメッセージを UTF-8 形式に変換した上で格納しているため、 文字コード設定の異なる環境の間で履歴情報をやり取りする場合でも、 ログメッセージは期待する文字コードで参照することができます。

また、テキスト系ファイルの内容に関しては、 ファイルに保存した際の文字コードのまま記録されます。

そのため、Mercurial での日本語対応に関して問題が生じるのは、 日本語ファイル名のファイルを構成管理したいという状況に限定される、と考えて良いでしょう。

Mercurial がファイル名に適用する文字コードは、 コミットログ等の記録に用いるものと同じ文字コードが用いられますので、 文字コードの設定は『日本語ファイル名の使用』を軸に考えることになります。

日本語ファイル名を使用しない場合、 推奨文字コード設定は以下のようになります。

日本語ファイル名を使用する場合、 ファイル参照/改変等の作業実施を想定している環境が、 どの程度のバリエーションになるかで、 大きく方針が異なります。

各環境の使用有無の組み合わせに応じた推奨文字コードを以下に示します。

WindowsMac OS Unix/Linux
使わない使う
使わない使わない----UTF-8
使う UTF-8UTF-8(*1)
使う 使う
使わないCP932UTF-8/CP932

(*1): ファイル名正規化に関する配慮が必要

備考: ファイルに対する作業を実施しない (= 履歴情報の格納のみ) 共有リポジトリでは、 ファイル名に纏わる問題の影響を受けないため、 共有リポジトリをどの環境に配置するかは、 文字コード設定方針を検討する際に考慮する必要がありません。

Windows 環境での文字コード設定

CP932 の設定

Windows ネイティブ版の hg コマンド (※ TortoiseHg 付属のものを含む) を使用する場合、 OS レベルでの文字コード設定が有効になります。

日本語 Windows では、 この設定値のデフォルトが CP932 ですので、 文字コードとして CP932 を使用する場合、 文字コード設定に関しては、 特に新たな設定を行う必要はありません。

注意: Windows環境において IntelliJ IDEA(あるいは Android Studio) 経由で Mercurial を使用する場合は、 文字コードに CP932 を使用する場合であっても、 HGENCODING 環境変数に CP932 を明示的に設定してください。

但し、 文字コードに CP932 を使用する環境で、 ファイル名に日本語文字を使用する際には、 win32mbcs エクステンションを有効にする必要が有ります。 win32mbcs エクステンションは、 他の文字コードと比較した際に、 文字コードとしての CP932 が抱える問題を回避するためのものです。

win32mbcs エクステンションを有効化するには、 設定ファイルに以下のような記述を追加するか:

[extensions]
hgext.win32mbcs =
win32mbcs エクステンションの有効化

TortoiseHg の GUI 経由であれば、 コンテキストメニューから 『TortoiseHg』 ⇒ 『Global Settings』 ⇒ 『エクステンション』等を経由して、 win32mbcs エクステンションにチェックを入れてください。

CP932 を利用するための設定は、以上で完了です。

UTF-8 の設定

Windows ネイティブ版の hg コマンドで、 ファイル名文字コードに UTF-8 を使用するには、 fixutf8 エクステンションを使用する必要があります。

しかし、 Mercurial 本体の開発進行に対して、fixutf8 の対応状況は、 正直あまり活発とは言えません。

例えば、正式には Mercurial 2.0.x 版にへの対応が出来ていない (※ 2011/12/15 時点) ことから、 1.9.x 版を使用するか、 有志によるパッチを適用した fixutf8 を使用する必要がある状況です。

以上のことから、 Windows ネイティブ版の hg コマンド使用における UTF-8 文字コードの採用は、 私個人としてはあまりお勧めではありません。

但し、 構成管理ツール自体は、 余程致命的なバグが見つかりでもしない限り、 頻繁にアップデートする必要が無いので、 動作確実なバージョンで一旦導入してしまえば、 比較的安定して使用できる、 というのも事実です。

また、 単に『最新の開発状況に追従していない』だけで、 fixutf8 自体は必ずしも『実運用に耐えない』というわけではありません。

『fixutf8 エクステンションを使いたいが、 どうすれば良いのか?/期待通りに動いてくれない』などといった質問や、 『こうしたら上手く動いた』と言った情報は、 Mercurial 日本語 ML 宛てに寄せて頂けれれば幸いです。

なお、 fixutf8 を使用する場合は、 HGENCODING 環境変数への UTF-8 設定確実に実施してください。

ちなみに、 Cygwin 環境経由であれば、 ファイル名文字コードに UTF-8 を使用するのも比較的容易ですので、 GUI 操作の必要が無いのであれば、 Cygwin 環境の利用も一考の価値があると思われます。

Cygwin 環境での文字コード設定

1.7 版以降の Cygwin では国際化対応強化の一環からか、 ファイル名指定時の文字コードとして UTF-8 を使用するようになりました。

どの版の Cygwin が稼動しているかは、 以下のように "uname -a" コマンドなどで確認することができます。

% uname -a
CYGWIN_NT-6.0 ホスト名 1.7.5(0.225/5/3) 2010-04-12 19:07 i686 Cygwin
Cygwin 版の確認

CP932 の設定

1.7 版以降の Cygwin 上で Mercurial (※ Cygwin 上の Python でソースからビルドしたもの含む) で、 ファイル名の文字コードに CP932 を使用する場合、 ロケール系環境変数で明示的に CP932 を指定する必要が有ります。

ロケール系環境変数で CP932 の使用が明示されていれば、 基本的に HGENCODING 環境変数の設定は不要です。

1.7 版よりも前の Cygwin 環境であれば、 HGENCODING 環境変数で CP932 の使用を明示してください。

また、 Mercurial の 2.1 版 (※ 2012/02/01 前後にリリース予定) 以降を使用する場合は、 win32mbcs エクステンションを有効にすることをお勧めします。

備考: win32mbcs によって、 『ファイル名に関する本来必要の無い警告が表示される』 問題が回避されます。

Mercurial 2.0.x 以前の win32mbcs は、 そのままでは Cygwin 環境では有効にできません。

UTF-8 の設定

1.7 版以降の Cygwin では、 環境変数の初期設定が、 ファイル名指定時の文字コードのデフォルト値として UTF-8 を使用するようになっています。

そのため、 ファイル名の文字コードとして UTF-8 を使用するのであれば、 ロケール系環境変数を明示的に変更している場合を除いて追加的な環境変数の設定 (HGENCODING 環境の設定含む) は不要です。

1.7 版よりも前の Cygwin 環境であれば、 HGENCODING 環境変数で UTF-8 の使用を明示してください。

Unix/Linux 環境での文字コード設定

作業環境として Unix/Linux 環境が想定される場合、 文字コードの選択肢は基本的には UTF-8 一択なのですが、 (1) Windows 環境での作業が想定され、且つ (2) Mac OS 環境での作業は想定されない場合は、 CP932 も選択肢として検討した方が良いでしょう。

Unix/Linux 環境では、 ファイル名は単なるバイト列としてしか扱われないため、 GUI 等での操作の際に、 ファイル名が正しく表示されない等の支障が生じる点を除けば、 ファイル名の文字コードとして CP932 を使用しても、 それ程深刻な問題は発生しません。

備考: もちろん、エディタやターミナルソフト、その他関連するコマンド群が、 CP932 なファイル/文字列を正しく扱えることが前提となるため、 『簡単に使用できる』とは言い難いのですが ....

文字コードは環境変数で指定してください。

Mac OS 環境での文字コード設定

作業環境として Mac OS 環境が想定される場合、 Mac OS で使用されているファイルシステム (HFS+) の仕様上、 文字コードの選択肢は UTF-8 一択となります。

文字コードは環境変数で指定してください。

環境変数の設定

Windows 環境での環境変数設定

Windows 環境で環境変数を設定する必要があるのは、 ファイル名の文字コードに UTF-8 を使用する際に、 HGENCODING 環境変数を設定する場合のみです。

『コントロールパネル』 ⇒ 『システム』 ⇒ 『詳細設定』 ⇒ 『環境変数』経由で、 『ユーザ環境変数』等に HGENCODING 設定を追加してください。

HGENCODING の設定値には、文字コード名称をそのまま指定します。

Cygwin 環境での環境変数設定

Cygwin 環境での環境変数設定は、 基本的に後述する Unix/Linux/Mac OS 環境でのそれと同じです。

但し、 Unix/Linux/Mac OS 環境では 基本的に HGENCODING 環境変数の設定のみでも十分であるのに対して、 Cygwin 環境 (1.7 版以降) で CP932 を使用する場合、 ロケール系環境変数の設定が必須となりますので、注意してください。

また、 ロケール系環境変数での設定と異なる文字コードを、 ファイル名文字コードとして使用することはできません。

HGENCODING 環境変数と、 ロケール系環境変数設定が食い違う場合、 一見何の問題も無く動作しているように見えても、 内部の管理情報に不整合が生じている可能性がありますので、 注意してください。

なお、 Cygwin 上で動作するコマンドも Windows プロセスの一種ですので、 『コントロールパネル』 ⇒ 『システム』 ⇒ 『詳細設定』 ⇒ 『環境変数』経由で設定した環境変数の影響を受けますので、 シェルの初期化ファイルではなく、 上記の方法で環境変数を設定することも可能です。

Unix/Linux/Mac OS 環境での環境変数設定

Unix/Linux/Mac OS 環境での 環境変数による Mercurial への文字コード指定方法は、 大きく以下の2種類に分類されます。

『ロケール系環境変数』とは、 LC_ALL や LC_CTYPE、LANG といった環境変数です。

Mercurial 固有の環境変数である HGENCODING と異なり、 ロケール系環境変数の設定は、 国際化対応している他のコマンド群の挙動にも影響を及ぼします。

例えば "LC_CTYPE=ja_JP.utf-8" といったように、 ロケール系環境変数が適切に設定されているならば、 Mercurial を使うに当たって、改めて環境変数を設定する必要はありません。

しかし『他のコマンド挙動への影響を回避したい』などといった理由から、 ロケール設定を無効化したいような場合は、 HGENCODING 環境変数を使って Mercurial にピンポイントで文字コードを指定する必要があります。

環境変数による指定の場合、 シェルの起動時設定ファイル (${HOME}/.bashrc 等) に、 以下のような記述を行うのが一般的でしょう (※ 記述例は Bourne Shell 系のもの):

HGENCODING=utf-8; export HGENCODING

    あるいは

LC_CTYPE=ja_JP.utf-8; export LC_CTYPE
環境変数による文字コード指定

HGENCODING による設定の場合は文字コード名のみの指定ですが、 ロケール系環境変数の設定は:

『言語名』 + "_" + 『国名』 + "." + 『文字コード』

という構成要素を正しく選択する必要があります (環境依存で省略可能)。

また、ロケール系環境変数の設定は、 設定する変数に応じて有効範囲や優先度が定められています。 あまり理解せずに設定すると、予期せぬ挙動に出くわす可能性がありますから、 注意が必要です。

『Mercurial への文字コード指定』に限定すれば、 環境変数設定の優先順位は以下のようになっています。

  1. HGENCODING
  2. LC_ALL
  3. LC_CTYPE
  4. LANG

ウェブサーバによる公開時の設定

リポジトリをウェブサーバ ("hg serve" や、hgweb.cgi 等と HTTPD の併用) によって公開する場合の文字コード設定方法/設定内容は、 基本的にはコマンドラインでの使用における設定と同一です。

備考: ウェブサーバ経由でリポジトリを公開する場合でも、 ブラウザ経由でのアクセスを想定しない(例: push/pull 向けに限定した運用) ならば、 文字コード設定に関しては特に意識する必要はありません。

しかし、Apache 等の外部 HTTPD を併用するようなケースでは、 以下の様な理由から、 必ずしも意図する文字コードを自由に設定できるとは限りません。

Mercurial では、設定ファイルの "[web]" セクションにおける "encoding" 項目の設定によって、 ウェブサーバ経由での公開時に使用する文字コードを、 明示的に指定することが可能です。

[web]
encoding = UTF-8
ウェブサーバ経由公開時の文字コード指定例

"hg serve" への "--web-conf" オプション指定時や、 hgweb.cgi を使用したリポジトリ公開の際には、 通常のコマンド実行の際に有効になる設定ファイル群の他に、 『hgweb 設定ファイル』と呼ばれる設定ファイルが読み込まれますので、 設定記述先ファイルの選択肢として考慮してみてください。

読み込み対象となる設定ファイルに関する詳細は "hg help config" を、 『hgweb 設定ファイル』に関する詳細は "hg help hgweb" を参照してください。

ちなみに、 管理対象ファイルの内容が、 リポジトリ毎に異なる文字コードを採用している場合、 ウェブサーバプロセスで単一の文字コードを設定してしまうと、 ログ系情報(コミットログやユーザ名)の文字コードと、 ファイル内容/差分の文字コードが食い違うことで、 結果的に期待とは異なる画面表示となるかもしれません。

"[web]" の "encoding" 項目は、 リポジトリ単位でも設定可能ですので、 リポジトリ毎の応答文字コードを個別に指定することも可能です。

Emacs の hg モード利用における留意点

Emacs の hg モード経由で Mercurial を利用する場合、 ファイル名やログメッセージに日本語を使用するに当たって、 確認が必要な点が2つあります。

まず第1は、 hg モード経由での Mercurial 利用はシェルを経由しないため、 当該 Emacs プロセスそのものに対して HGENCODING 環境変数が設定されていることを確認してください。 Meadow のような非 Cygwin プロセスの場合は、 『コントロールパネル』 ⇒ 『システム』 ⇒ 『詳細設定』 ⇒ 『環境変数』経由での環境変数設定が必要です。

第2に、 以下の lisp 変数にも HGENCODING (および稼働環境の OS) と辻褄の合う適切な値が設定されていることが必要です。

以上の2点が適切であることが確認できれば:

hg モードにおける日本語利用(画像)

日本語ファイル名のファイルを add することも、 日本語のログメッセージを入力することも (勿論、日本語のログメッセージの閲覧も)可能です。

備考: 厳密に言えば、 開いてあるファイルに対する "hg-add" によって、 構成管理への追加をする必要が無ければ、 おそらく file-name-coding-system の設定は不要と思われます。

しかし、hg モードを使用しているのに、 ファイルの追加だけコマンドラインで実施、 という状況は普通に考えて有り得ないですから、 この lisp 変数も設定しておくことをお薦めします。




これ以降で述べる内容は、 文字コード設定/ファイル名に関する技術的な話題なので、 必ずしも利用者全員にとって必要なものではありません。 必要に応じて適宜参照してください。

また、 Mercurial Advent Calendar 2011 の一環で書いた文字コードに関するエントリも併せてご覧ください。


次節「マージプログラム」へ



ファイル名の正規化

Mac OS のファイルシステムである HFS+ では、 『濁点における濁点( ゛ )』や『半濁音における半濁点( ゜ )』などが、 自動的に分離されます。

$ echo a > ガイド
$ ls
カ゛イト゛
$
HFS+ における正規化実施例

これは、一般にUnicode 正規化 (HFS+ の場合は NFD) と呼ばれる手順の一環として実施されるものです。

備考: 実際の Mac OS 環境における正規化では、 『ガ』 (U+30ac) は 『カ』(U+30ab) と濁点 U+3099 に分解されます。

CP932 の濁点に相当する 『゛』 (U+309B) と異なり、 U+3099 は CP932 には含まない文字です。

説明の便宜/ページ文字コードの設定上、 上記の実行例では U+309B を使用しているため、 正規化後文字列をコピー&ペーストして用いるなどした場合、 『ガイド』と『カ゛イト゛』が同一とみなされない、 といった想定外の挙動となりますから注意してください。

また、ターミナルソフトが NFD 対応している場合等は、 上記実行例のような『カ』と濁点が分離したような表示にはなりませんので、 一見すると正規化実施の有無がわからないかもしれません。

Mac OS 上で動作する Mercurial は、 ディスク上に記録されている名前 = NFD 正規化後の名前ベースで処理を実施することから、 構成管理対象への登録を『ガイド』という名前で実施しても、 実際には『カ゛イト゛』という名前で構成管理されます。

その一方で、 Windows や Unix/Linux のファイルシステムでは、 濁点や半濁点の分離といった正規化が実施されないことから、 これらの環境で動作する Mercurail もその挙動に倣い、 正規化を行いません。

そのため、 濁点や半濁点といった、 正規化の影響を受ける文字を伴う日本語ファイル名を使用する場合、 どの環境において構成管理対象として登録されたかに応じて、 構成管理対象として記録される名前が異なります。

例えば、 『ガイド』というファイルを構成管理対象として登録する場合、 以下のようになります。

Mac OS 環境上で登録
どの環境でファイルを取り出しても、 『カ゛イト゛』 (= NFD により正規化された名前) という名前での取り扱い
Windows/Unix/Linux 環境で登録
Windows/Unix/Linux 環境では『ガイド』、 Mac OS 環境では『カ゛イト゛』で取り扱い可能。

Windows/Unix/Linux 利用者にとって、 NFD による正規化後の名前は馴染まないと思われますので、 利用環境が混在する状況での運用の場合、 ファイルの追加に関する何らかの運用ルールを設けた方が良いでしょう。

備考: 一般的にはレアケースと思われますが、 例えば同一ディレクトリ配下の『ガイド』と『カ゛イト゛』の両方が、 同一リビジョン中に存在するような状況を Windows/Unix/Linux 環境上で作成してしまった場合、 Mac OS 環境では該当するリビジョンでの作業領域更新 ("hg update") ができなくなります (※ "hg cat" 等での個別取り出しは可能)。

CP932 の問題点

様々な文字コードに対応するためには、 色々な配慮が必要なのですが、 日本語環境で一般的に使用される CP932 は、 とりわけ色々な配慮が必要な文字コードです。

一番根本的な問題は、 この文字コードが以下のような特徴を持っていることに尽きます:

2バイト文字の2バイト目に、 アルファベットや記号等の、 ASCII コードで一般的な文字と同じ値のバイトが使用されている

例えば『能』は、 CP932 なら 0x94 0x5c の2バイトで表現されますが、 2バイト目の 0x5c は、 ASCII で言うバックスラッシュ (\) に相当します。

バックスラッシュは以下のような、 極めて特殊且つ重要な用途を持つ文字です。

CP932 を正しく認識できない環境で、 このような文字を使用した場合、 厄介な問題が発生します。

Mercurial には、 これらの問題を回避するための対処が施されていますが、 「エスケープ文字との誤認」の可能性のある文字を、 正規表現処理で使用した場合に関しては、 期待通りの挙動とならない可能性があります。

パス区切りとの誤認

Windows 上で文字コード CP932 を意識せずに、 単純にバックスラッシュでパスを区切った場合、 想定外のファイルへアクセスしようとしてしまいます。

例えば、 『機能仕様書』というパスは、 『能』の2バイト目の 0x5c で区切られてしまいますから、 『機』+ 0x94 というディレクトリ配下の 『仕様書』というファイルとみなされてしまいます。

エスケープ文字との誤認

CP932 の多バイト文字における2バイト目が、 バックスラッシュ (0x5c) 相当であった場合、 これがエスケープ文字として扱われることで、 予期せぬ挙動となる場合があります。

例えば以下のように、 0x5c を含む文字がたまたま行末に来てしまった場合:

    // 〜対応機能
    result = doit();
紛らわし文字を使用したコメント

『能』の2バイト目の 0x5c によって改行がエスケープされることで、 実質的には以下のようなソースとして解釈されてしまい、 doit() 呼び出しは実行されません。

    // 〜対応機能 result = doit();
実際の解釈

あるいは、 hg などのコマンドが起動される前の段階で、 bash 等によるバックスラッシュの解釈が走ってしまう点にも注意が必要です。

例えば『機能A』(0x8b 0x40 0x94 0x5c 0x41) という引数を指定した場合、 bash が『能』の2バイト目のバックスラッシュを、 それに続く 'A' に対するエスケープ文字だと解釈してしまうため、 この引数が hg コマンドに渡される時点では、 『機尿』 (0x8b 0x40 0x94 0x41) になってしまいます。

$ echo 機能A
機尿
$ echo '機能A'
機能A
$
シェルによるエスケープ

引数をコマンドに正しく渡すためには、 bash による解釈を抑止するために、 シングルクォート等で囲む必要があります。 ダブルクォートを使用した場合、 閉じクォートがエスケープされてしまう危険があることから、 任意の文字列に対して有効とは限りませんので注意が必要です。

この挙動は、 LC_CTYPE 等による CP932 の使用を明示していたとしても、 回避することができません (少なくとも現行の bash 実装では回避できません)。

Emacs の hg-mode や、 TortoiseHg などの GUI を経由する場合、 hg コマンド起動に先立って余計な解釈が実施される余地がありませんので、 このような問題は発生しませんが、 コマンドラインで作業する場合は注意が必要です。

文字大小を無視した比較における誤認

例えば『ア』 (0x83 0x41) と『ヂ』 (0x83 0x61) という2つの文字は、 1バイト目が同一で、 2バイト目にそれぞれ 'A' (0x41) と 'a' (0x61) に相当する文字を使用しています。

そのため、 CP932 を意識せずに ASCII アルファベットの大文字化/小文字化を実施すると、 『ア』と『ヂ』が同一と判定されてしまう、という問題を抱えています。


次節「マージプログラム」へ