Mercurial は機能性の見地から見た場合には申し分無い一方で、変り種の機能群は故意に除外されています。簡潔さを保つ遣り方は、保守担当と利用者の両方に対してソフトウェアの扱いやすさを維持します。
しかし Mercurial は、利用者を杓子定規なコマンド群の只中に利用者を閉じ込めるようなことはしません。イクステンション(この種のものはプラグインと呼ばれることもあります)として機能を追加することができるのです。幾つかのイクステンションについては、 既に前の章で話題にしています。
本章では、上記以外の Mercurial で利用可能な幾つかのイクステンションについて取り上げ、その上で、自分でイクステンションを実装する際に必要と思われる仕組みについて、簡単に触れようと思います。
一般的な Mercurial の操作が 100 倍速くなることに興味があるのでしたら、ぜひこの節を読んでください。
Mercurial は通常の環境であっても高い性能でを発揮します。 XXXX 否定の接続の筈 XXXX 例えば“hg status” コマンドの実行の際には、ファイルの状態を表示するために、リポジトリ配下の殆ど全てのディレクトリとファイルに対する走査が必要です。他の多 くの Mercurial コマンドも、舞台裏では同様の作業を必要としています。例えば“hg diff” コマンドは、状態比較機 構1 を用いることで、明らかに変更されていないファイルに対して、実行コストの高い比較処理が実施されることを回避していま す。
ファイル状態の取得は性能確保上重要なことなので、 Mercurial の開発者達は、ギリギリのところまでこの部分の実装を最適化してきました。しかし “hg status” 実行の際には、前回の確認以降の変更の有無を知るために、コストの高いシステムコールを、 Mercurial の管理下にあるファイル毎に最低1回発行する必要がある、という事実は回避しようがありません。一定以上の大きさのリポジトリでは、この処理には長い時間がかかります。
影響の大きさを数値化すべく、 150,000 のファイルを管理するリポジトリで実験を行った結果、いずれのファイルも変更されていない場合であっても、 “hg status” の実行には10秒を要します。
多くの近代的 OS は、ファイル更新の通知機構を備えています。適切なサービスにプログラムを登録しておくことで、対象となるファイルに関する生成・変更・削除といったイベントが発生する都度、 OS が通知をしてくれます。 Linux 環境では、inotifyと呼ばれるカーネルコンポネントが通知機構を提供します。
Mercurial のinotify イクステンションは、カーネルの inotify と連携することで、“hg status” コマンドを最適化します。 inotify イクステンションは2つの要素から構成されています。デーモン部分がバックグラウンドで稼動することで、 inotify カーネルコンポネントから通知を受け取ります。デーモン部分は、通常の Mercurial コマンドからの接続要求も受け付けます。 inotify イクステンションは、ファイルシステムの走査の代替としてデーモ ンを必要とするため、 Mercurial の挙動そのものを改変します。デーモンはリポジトリ状態に関する完全な情報を保持しているので、リポジトリ配下のディレクトリやファイルを走査すること無しに、即座に応答を返すことができま す。
先に述べたとおり、通常の Mercurial では、 150,000 のファイルを管理するリポジトリでの“hg status” 実行に10秒を要しま した。inotify イクステンションを有効にすることで、実行に要する時間は 1000 倍早い 0.1 秒まで低減できまし た。
話を先に進める前に、以下の点に注意してください。
inotify イクステンションは、 2007 年 5 月の時点では Mercurial に同梱されていませ ん3 ので、 他のイクステンションと比較して多少の準備作業が必要ですが、性能向上にはそれだけの価値があります。
inotify イクステンションは目下、 Mercurial ソースコードへのパッチと、inotify サブシステム連携の Python バインディング ライブラリの2つの要素から構成されています。
事を進めるに当たっては、既に機能しているインストール済み Mercurial を複製するのが良いでしょう。 To get going, it’s best to already have a functioning copy of Mercurial installed. XXXXXX
“hg qpush” がエラーメッセージを表示した場合は、作業を継続せずに開発コミュニティに助けを求めてくださ い。
適切にパッチが適用された版の Mercurial が一旦できてしまえば、inotify イクステンションを有効にするために必要なこと は、hgrcファイルに以下の記述を追加することだけです。
inotify イクステンションが有効化されると、リポジトリの状態を必要とするコマンドの初回起動の時点で、 Mercurial は自動的 且つ透過的に状態管理用デーモンを起動します。状態管理デーモンは、リポジトリごとに起動されます。
状態管理デーモンはひそやかに起動され、バックグラウンドで実行し続けます。inotify イクステンションを有効にした複数のリポ ジトリで、幾つかのコマンドを実行した後に、実行中のプロセス一覧を見れば、カーネルからの通知と Mercurial からの問い合わせの 両方を待っている複数のhg プロセスを見ることができる筈です。
inotify イクステンションを有効にした際でも、リポジトリにおける Mercurial コマンドの初回起動は、通常の Mercurial コマン ド実行と同程度の性能で実行されます。これは状態管理デーモンによる通常の状態走査が必要なためで、後にカーネルからの更新通知を 受け取る際の基底状態となります。しかし、これ以降の状態確認の必要な全てのコマンド実行は、どんなに小さなサイズのリポジトリで あっても、目に見えて速くなっている筈です。リポジトリが大きければ大きいほど、目に見えて性能が大きく改善されることでしょ う。inotify デーモンは、どんなサイズのリポジトリであっても、状態取得操作を殆ど瞬時に終了させることができま す。
“hg inserve” コマンドにより、状態管理デーモンを手動で起動することもできます。手動での起動により、デーモンの実行に関し て幾分明瞭な制御を手にすることができます。このコマンドの起動は、当然inotifyイクステンションが有効になっている場合に限り 使用可能です。
inotify イクステンションを使用している際には、状態関連コマンドの実行全般がそれ以前と比較して速くなっている点を除けば、 Mercurial の挙動は全く変わらない筈です。
とりわけ、コマンドの出力は異ならず、同じ結果を返す筈です。 inotify イクステンションの有無で異なる結果が変える場合、障害として報告をしてください。
Mercurial の組み込み“hg diff” コマンドは、 unified 差分をそのまま出力します。
変更内容の表示に外部ツールを使いたい場合は、extdiff イクステンションが良いでしょう。extdiff イクステンションにより、 変更内容表示に例えばグラフィカルな外部差分ツールが利用できるようになります。
extdiff イクステンションは Mercurial に同梱されているので簡単に利用できます。hgrcファイルの[extensions] セクション に、イクステンションを有効にする記述を1行追加するだけで良いのです。
この設定により、“hg extdiff” コマンドが利用可能になりますが、基底状態ではこのコマンドは、組み込みの“hg diff” コマン ドと同じ形式の unified 差分を、システムのdiff コマンドにより生成します。
組み込みの “hg diff” コマンドの結果出力と厳密には一致しませ ん5 が、同じオプションを 指定してもシステム6 ご とに(システムの)diff コマンドの出力が異なるからです。
上記の出力結果に “making snapshot” 行が含まれていることからも察することができますが、“hg extdiff” コマンドはソースツリーに関するスナップショットを2つ作成します。1つ目のスナップショッ トはソースのリビジョンのもので、2つ目は作業領域ディレクトリにおける対象リビジョンのもので す7 。“hg extdiff” コマンドはこれらのスナップショットを一時ディレクトリに作成し、これらのディレクトリ名を引数にして外部の差分表示 ツールを起動し、その後一時ディレクトリを削除します。実行効率上、2つのリビジョンの間で差分のあるディレクトリ・ファイルのス ナップショットだけが作成されます。
スナップショットディレクトリの名前は、元となるリポジトリのベース名と同じ名前を持ちます。/quux/bar/foo というリポジト リの場合、個々のスナップショットのディレクトリ(ベース)名は foo となります。対応するチェンジセット ID がある場合、スナッ プショットのディレクトリ名にはチェンジセット ID が付与されます。a631aca1083f 版に対するスナップショットのディレクトリ名 はfoo.a631aca1083f となります。作業領域ディレクトリの現行状態に対するスナップショットは、チェンジセット ID が付与されま せんので、この例では単に foo という名前になります。実際の挙動を見るために、再度前出の“hg extdiff” の実行例を見てみ ましょう。差分出力のヘッダ部に、スナップショットディレクトリの名前が埋め込まれているのに気付くことでしょ う。
“hg extdiff” コマンドには、2つの重要なオプションがあります。 -p オプションは、システムのdiffコマンドの代替として使 用される差分表示プログラムを指定します。 -o オプションは、“hg extdiff” が外部の差分表示プログラム起動時に指定するオプショ ン(デフォルトでは “-Npru” が指定され、diff を使用する場合にのみ意味を持ちます)を指定します。それ以外の点では、“hg extdiff” コマンドは組み込みの“hg diff” コマンドと同様に振舞いますので、オプション名やオプション指定の文法、比較対象 リビジョンを指定する引数、比較したいファイル名の指定などは、組み込みの“hg diff” と同じように指定できま す。
実行例として、(通常の“hg diff” による) unified 差分の代わりに、システム標準のdiff コマンドによる context 差分(-c オ プション使用)を、デフォルトの3行ではなく5行の context 行(-C オプションでの 5 指定)で表示する方法を示しま す。
グラフィカルな差分ツールの起動は非常に簡単です。kdiff3 起動の例を示します。
利用する差分表示コマンドがディレクトリ指定を扱えない場合でも、簡単なスクリプトを使うことでその問題を解決できます。 そのようなスクリプトによるmq イクステンションとinterdiff コマンドの連携例は、13.9.2 節を参照してくださ い。
“hg extdiff” コマンドや利用する差分表示コマンドの、両方のオプションを覚えておくのは面倒ですので、extdiff イクステン ションは、使用する差分表示コマンドを正しいオプションで起動する新しいコマンドを定義できるようになっていま す。
新しいコマンド定義のために必要なのは、hgrcファイルを編集し、[extdiff] という名前のセクションを追加するだけ です。このセクションでは、複数のコマンドを定義することができます。以下に kdiff3 コマンドを追加する例を示 します。一旦定義してしまえば、 “hg kdiff3” と入力するだけでextdiff イクステンションがkdiff3 を起動しま す。
定義の右辺を上記例のように空にした場合、extdiff イクステンションは、定義したコマンドの名前を実行すべき外部プログラムの 名前と見なします。しかし、これらの名前が一致している必要はありません。以下の例では、kdiff3 を実行するコマンドを “hg wibble” という名前で定義しています。
差分表示プログラム起動の際のデフォルトオプションも指定することができます。 “opts.” 接頭辞に続いて、オプションを適用し たいコマンド名を記述してください。以下の例では、vim エディタの DirDiff 拡張を実行する “hg vimdiff” コマンドを定義してい ます。
※ Brendan とチャットでの話し合いが必要
多くのプロジェクトでは、共有リポジトリに最終成果をコミットする前に、変更内容をメーリングリストに投稿して査読や論評を行う “変更レビュー” の文化を持っています。リポジトリへのアクセス権を持たない人々からの変更依頼を適用する、門番の役割を果たす 人々がいるプロジェクトもあります。
Mercurial のpatchbomb イクステンションを利用することで、レビューや提案のための電子メールによる変更送信が容易になりま す。このイクステンションの名前は、変更がパッチ形式で整形され、1チェンジセット毎に1つの電子メールで送信されることに由来し ています。電子メールによる一連の変更の送信が、受信者のメールボックスにとって “爆撃” (bombing)のようであることから、 “patchbomb” と呼ばれています。
patchbomb イクステンションの基本的な設定記述は、いつものようにhgrcへの1行か2行程度の記述だけです。
一旦イクステンションを有効にしたならば、“hg email” という新たなコマンドが利用可能になります。
“hg email” コマンドの安全且つ最善の実行手順は、必ず -nオプションを付けて一旦実行してみることです。 -n オプション付 きの実行は、実際の電子メール送信は行わずに、送信されるであろう内容を表示します。変更内容にざっと目を通し て、送信内容が適切であることを確認したならば、 -nオプション抜きで再度“hg email” コマンドを実行してくださ い。
“hg email” コマンドは、他の Mercurial コマンドと同様のリビジョン指定が可能です。例えば以下の実行例では、リビジョン 7 から tip までの全てのリビジョン(リビジョン 7 および tip も含みます)が送信されます。
比較対象のリポジトリを指定することもできます。リビジョン指定無しでリポジトリを指定した場合、“hg email” コマンドは、遠 隔リポジトリに存在しないローカルリポジトリの全てのリビジョンを送信します。リビジョンないし( -b オプションによる)ブランチ 名を追加指定することで、送信されるリビジョンを制限することができます。
送信先アドレスを指定しない“hg email” 実行は完璧に安全で、その場合には“hg email” は対話的に入力を求めてきます(Linux や Unix ライクなシステムを利用している場合、これらのヘッダ値入力の際には、readline 様式の編集機能が利用可能で す)。
単一のリビジョンだけを送信する場合、“hg email” コマンドの基底動作では、コミットメッセージの最初の1行を送信する電子 メールのサブジェクトに利用します。
複数のリビジョンを送信する場合、“hg email” コマンドはチェンジセット毎に電子メールを送信します。この場 合、送信しようとする一連の変更の目的を記述した前置きの電子メールを、一連のメール送信の先触れとして送信しま す。
電子メールによる変更内容送信の形式が、全てのプロジェクトで厳密に同じわけでは無いことから、patchbomb イクステンションは、 コマンド行でのオプション指定による幾つかの適合処理を実施します。