彷徨えるフジワラ

年がら年中さまよってます

Mercurial/TortoiseHg での差分表示に外部ツールを使う設定

本エントリでは、Mercurial/TortoiseHg で差分表示を行う際に、外部ツールを使いたい場合の設定方法について説明します。

注意: Windows 環境で実行する場合、Mercurial 3.2.1 〜 3.2.4 では、適切に設定されていても、外部マージツールの起動が失敗してしまう可能性がありますので、これら以外の版を使用するようにしてください。

当初は、外部ツールを使ったマージに関する設定も、一緒に説明しようと思っていたのですが:

  • 差分表示に比べると、マージの動作確認は面倒 (マージ前の状態を作る必要がある)
  • 簡略化しても、説明全体が結構な分量になる

以上のような理由から、まずは外部ツールによる差分表示に関して、説明しようと思います。

多くの場合、マージツールは差分表示ツールを兼ねていますので、「外部ツールの利用はマージだけ」という場合でも、とりあえずは差分表示に関する設定を通して、外部ツールを使用する際の要領を掴んでおくのが良いと思います。

なお、本エントリでは、設定項目に関する網羅的な説明は行いません。

「余計な説明はいらないから、設定に関する網羅的な情報が欲しい!」という方は、"hg help config" 出力中の "merge-tools" に関する項目を参照してください (日本語訳はネット上でも参照可能です)

「網羅的な情報が欲しいが、多少は解説的なものも欲しい」という方は、いわたさんによる "External Diffのはなし" を参照してみてください。

ちなみに、設定ファイルの記述形式や配置場所に関して、基本的な知識はあるものと仮定します。不安な方は、"hg help config" 出力冒頭の説明等を参照してください。

以下、使えるようにしたいツールの名前を、便宜上 mytool と表記しますので、使用するツールに応じて適宜読み替えてください。

設定に関する事前確認

コマンドラインからの使用が面倒で TortoiseHg を使いたい方は、あまり面白くないかもしれませんが、幾つかの項目に関する事前確認のため、少しの間、コマンドプロンプト (@Windows) やターミナルソフト経由での、コマンドライン上での作業になります。

まずは "hg showconfig merge-tools" コマンドを実行して、出力される内容を確認します。

"hg showconfig merge-tools" 実行結果は、環境に応じて、(殆ど)何も出力されないか、大量の情報が出力されるかの、両極端な結果になります(Windows 環境は基本的に後者になります)。

大量に出力されるとは言っても、出力内容の各行は以下のような単純な形式です。

merge-tools.ツール名.項目名=設定値

出力される設定項目の中に、merge-tools.mytool.diffargs が存在する場合は、特に何も設定しなくても mytool による差分表示が (多分) できます! (とりあえず) 万歳!

この項目が設定されていない場合、あるいは設定されていても期待通りの動作にならない場合は、以降で述べる手順に従って設定を追加してください。

なお、本エントリの説明では、Mercurial の設定ファイルにおいて、[extdiff] セクションには何も設定項目が無いことを前提としています。

これは、[extdiff] セクションに何らかの設定がある場合、TortoiseHg 経由での差分表示におけるデフォルト挙動の説明が、非常に入り組んだ内容になってしまうためです。

もしも "hg showconfig extdiff" で何らかの設定内容が出力されるようなら、以降の説明を読む前に、一時的に設定項目を無効化しておいてください (一般的な環境であれば、[extdiff] 設定は個人レベルの設定だけなので、無効化は簡単な筈)。

使用ツールに関する事前確認

次に、使用するツール mytool の実行方法に関して、いくつかの事前確認を行います。

なお、以降の説明に従って、設定ファイルに記述を追加する際には、各設定項目を必ず1行で記述するようにしてください。

Mercurial の設定ファイル自体は、1項目を複数行に渡って記述することが可能ですが、コマンド実行系の記述が複数行に渡っている場合、実際にコマンドを実行した際に、想定外の実行となります (詳細はこちらを参照してください)。

● コマンドインストール先と PATH 環境変数の確認

以下のようなケースでは、コマンド名として mytool を指定しただけでは、mytool を実行することができない可能性があります。

  • PATH 環境変数では検出できない場所に mytool がインストールされている
  • 後から PATH 環境変数が変更された
    (= 起動済みの他のプロセスの PATH 環境変数mytool を検出できないまま)

このような場合は、.executable に関する設定を [merge-tools] セクションに追加する必要があります。

[merge-tools]
mytool.executable = /path/to/executable/of/mytool
● 引数並びの確認

「差分表示」を外部ツールで実施する場合、extdiff エクステンション (詳細は後述) を使って hg コマンド経由で使用するケースと、TortoiseHg 経由で使用するケースでは、デフォルト引数の扱いが違います。

hg コマンド経由の場合、特に設定が無ければ、以下の引数形式で外部ツールが実行されます。

mytool $parent1 $child

$ で始まる引数は、実行時に適宜対象ファイル(or ディレクトリ)指定で置き換えられます。各引数は以下の意味を持っています。

  • $parent1: 比較における「親」の内容を持つファイル
  • $child: 比較における「子」の内容を持つファイル

その一方で、TortoiseHg 経由での差分表示では、特に設定が無い場合、「引数なし」で外部コマンドが実行されてしまいます。

以下のような場合は、.diffargs に関する設定を [merge-tools] セクションに追加してください。

  • TortoiseHg 経由でも外部ツールによる差分表示を行いたい
  • mytool での引数並びが上記と異なる
  • 差分表示を実行するために特別な引数が必要
# 引数並びの変更+オプションの追加例
[merge-tools]
mytool.diffargs = --special-option $child $parent1

なお、hg コマンド経由での差分表示に外部ツールを使用する場合、外部ツールはディレクトリ同士の比較が出来る必要があります。

差分表示の際に「毎回1つだけ対象ファイルのパスを指定」すれば、ファイル比較しかできないツールでも使用可能ではありますが、多分そのうち面倒になってくることでしょう(笑)

ディレクトリ同士の比較の際に特別なオプションが必要になる場合は、[merge-tools] での .diffargs に関する設定に、オプション記述を追加してください。

● プロセス分離の確認

Mercurial で外部ツールを使って差分表示を実施する場合、差分表示そのものが終了するまでは、コマンドが終了しない (= プロセス分離しない) ことを前提にしています。

コマンドラインから直接外部ツールを起動した際に、ツールの実行を終了するまでは、次のコマンドの入力を促すコマンドプロンプト表示されないことを確認してください。

特に GUI 表示を行うツールの場合は、GUI 表示を開始する一方で、外部ツールのコマンド自体は実行を終了してしまう (= GUI 表示プロセスが分離される) ケースがありますので、必ず確認を行うようにしてください。

なお、TortoiseHg は差分表示ツールのプロセス分離に対する配慮が含まれていますので、TortoiseHg 経由でのみ使用する場合は、この確認を飛ばしても構いません。しかし、デバッグ情報を表示できるコマンドライン経由での実行の方が動作確認が楽なので、この項目に関する確認&対処を実施しておくことをお勧めします。

もしも対象ツールが、デフォルトではプロセスが分離されてしまう実装になっていたとしても、おそらくは「実行終了までコマンドを終了させない」ようにする方法がある筈です。

"fork" や "spawn"、"foreground (execution)" のようなキーワードで、該当するオプションや設定項目が無いか確認してみてください(例: gvimdiff の --nofork オプション)

プロセス分離させないためにオプション指定が必要な場合は、[merge-tools] での .diffargs に関する設定に、当該オプションを追加してください。

動作確認

以上で必要な設定は済んでいる筈ですので、動作確認をしてみましょう。

hg コマンド経由での動作確認の方が、デバッグ情報等を出力可能な分、問題発生時の原因究明が比較的簡単ですので、TortoiseHg 経由でのみ使用する予定であっても、まずは hg コマンド経由で動作確認することをお勧めします。

● hg コマンドからの差分表示の動作確認

コマンドラインの hg コマンド経由で、外部ツールによる差分表示を行うには、以下の要領で extdiff エクステンションを有効にしておく必要があります。

[extensions]
hgext.extdiff =

extdiff エクステンションが正しく有効化されている場合は、"hg help extdiff" 実行により、extdiff のオンラインドキュメントが表示されますが、そうでない場合は、以下のような簡単な説明しか表示されません。

$ hg help extdiff
extdiff エクステンション - リビジョン間差分表示での外部コマンドの利用

"hg help extensions" で有効なエクステンションの情報が表示されます

この場合は、extdiff の有効化設定を、もう一度確認してみてください。

extdiff エクステンションを有効にしたなら、作業領域中の任意のファイルを変更した上で、以下の要領で mytool による差分表示を実施してください。

$ hg mytool

上記の実行例では、"hg diff" のような組み込みコマンドと同じ要領で、 "hg mytool" コマンドを実行しています。これは、有効化された extdiff エクステンションによって、[merge-tools] の設定を元に自動的に追加されたものです。

extdiff エクステンションが有効化されているのに、 "hg mytool" 自体が「不正なコマンド」扱いで実行できない場合、原因は [merge-tools] セクションにおいて mytool 関連の項目が正しく設定されていないためです。

スペルミス等の単純ミスの可能性を含めて、設定内容を再確認してみてください。

また、 "hg mytool" コマンド自体は実行できているのに、差分表示が思ったように機能しない場合は、--debug オプションを追加してみてください。

以下の様な、外部ツール起動に関する情報が表示されますので、mytool 実行時のオプション指定等が、期待通りであるかを確認できます。

$ hg --debug mytool
running 'mytool ....' in .....

例えば、追加した筈のオプションが指定されていない場合は、[merge-tools] mytool.diffargs の設定が、複数回記述されているため、最後の設定のみが有効になっている、といった原因が考えられます。

スペルミス等の単純ミスの可能性を含めて、設定内容を再確認してみてください。

なお、引数自体は想定通りに指定されていても、引数として指定されるファイル名等に空白が含まれるような場合は、引数が正しく解釈されない可能性があります。

このような場合は、[merge-tools] mytool.diffargs での引数形式の設定において、置換される引数を個別にダブルクォート等で囲んでみてください。

● TortoiesHg からの差分表示の動作確認

TortoiseHg 経由で、外部ツールによる差分表示を行う場合、あらかじめ使用するツールを設定しておく必要があります。

差分表示で使用する外部ツールは、「ファイル」メニュー ⇒ 「設定」 ⇒ (設定ファイルの選択) ⇒ 「TortoiseHg」カテゴリの選択 ⇒ 「GUI 差分表示ツール」から設定します。

事前の [merge-tools] 設定記述が正しく反映されていれば、プルダウンメニューの選択候補に mytool が表示されている筈です。

表示されない場合は、これまで説明した設定項目とあわせて、追加設定を記述したファイルと、「設定」ダイアログで選択している「設定ファイル」が、一致しているかも確認してみてください。

差分表示ツールの設定が済んだなら、以下の手順で外部ツールによる差分表示が実施されます。

  1. リビジョン一覧やファイル一覧中の要素を右クリック
  2. コンテキストメニューから「親リビジョンとの差分」や「ローカルとの差分」を選択

2つのリビジョンを選択した状態で、右クリックで表示されるコンテキストメニューから「GUI 差分表示」を選択することで、2つのリビジョンの間での差分表示もできます。