Mercurial は、一貫性と表現力を兼ね備えた方法でファイル名を扱う仕組みを提供しています。
Mercurial は “under the hood” において、ファイル名を取り扱う統一された仕組みを用いています。ファイル名に関する全てのコマンドの挙動は統一されています。ファイル名に対するコマンドの挙動は、以下のようになっていま す。
コマンド行で実ファイル名を明示的に指定した場合、 Mercurial は指定されたファイル名に厳密に作用します。
ディレクトリ名を指定した場合、 Mercurial はその指定を、 “当該ディレクトリならびにサブディレクトリ中の全てのファイル” とみなします。 Mercurial は当該ディレクトリ配下のファイル・サブディレクトリを、アルファベット順に走査します。あるディレクトリの走査中にサブディレクトリに遭遇した場合、当該ディレクトリの走査よりも先に、サブディレクトリの走査を実施しま す1 。
ファイル名を引数に取る Mercurial コマンドは、引数ないしパターン指定無しで起動された場合も、有用な基底時動作が定められています。コマンドに期待される振る舞いは、コマンドの用途に依存します。ファイル名指定無しの起動 において、コマンドがどのように振舞うのかを推測するための、一般的な目安となる幾つかのルールを以下に示します。
この振る舞いがそぐわない状況であれば、簡単に振る舞いを変えることができます。作業領域ディレクトリ全体に作用するコマンドであれば、 “.” を指定することで、コマンドの作用を現在のディレクトリおよびその配下に限定することができます。
ルート以外のディレクトリでコマンドを実行した場合でも、リポジトリのルートに対する相対的なファイル名を表示するコマンドも あります。このようなコマンドは、明示的な名前を指定することで、現在のディレクトリ位置に対する相対的なファイル名を表示するよ うになります。非ルートディレクトリでの“hg status” 起動の際に“hg root” コマンドの出力を指定することで、対象を作業領域 ディレクトリ全体に維持したまま、現在のディレクトリ位置に対する相対的なファイル名を表示させることができま す。
先の節における“hg add” コマンド実行例は、 Mercurial コマンドに関するもう一つの有益な事柄を示しています。コマンド行で明示 的な指定をしていないファイルに対してコマンドが作用する場合、通常は対象ファイル名を表示しますので、思わぬコマンドの実行結果 に後から驚かされることはありません。
これは驚きを最小にする原則に則ったものです。コマンド行で厳密なファイル名を指定した場合には、それを復唱す る必要は無いでしょう。ファイル名・ディレクトリ名ないしパターン(後述します)を指定しないことで暗に指定さ れた対象ファイルに Mercurial が作用する場合、どのファイルを対象とするのかを通知するのは安全性の上で有用で す。
上記方針に沿って振舞うコマンド群は、-q オプションを指定することで、その出力を抑止することができます。明示的にファ イル名等を指定した場合でも、-v オプションを指定することで、全ての対象ファイル名を表示させることができま す。
ファイル名・ディレクトリ名による指定に加えて、 Mercurial ではパターンによるファイル指定機能が使用できます。 Mercurial のパ ターン操作は表現力に富んだものです。
Linux や MacOS のような Unix 的システムでは、ファイル名とパターンとの間の突合せは通常シェルがその役目を 負います。これらのシステムでは、パターンを指定している旨を Mercurial に対して明示的に指示する必要がありま す2 。 Windows においては、シェルによるパターンの展開が行われませんので、 Mercurial は自動的に指定されたものがパターンであると認 識し、ファイル名へと展開します。
コマンド行において、ファイル名を指定する場所でパターンを使用するには、以下のように記述します。
パターンの記述は、パターンの種類を識別するための短い文字列、コロン、そして実際のパターンを連結したもので す。
Mercurial は2種類のパターン形式に対応しています。最も利用頻度が高いものは glob と呼ばれ、 Unix のシェルによるパターン マッチングと同様の機能を持つもので、その振る舞いは Windows のコマンドプロンプトユーザにも馴染みがあることでしょ う。
Windows において Mercurial が自動的にパターンマッチングを行う場合、glob 形式とみなされます。そのため、 Windows にお いては “glob:” 接頭辞を省略可能ですが、明示的に指定することも可能です。
re 形式は、glob 形式よりも強力で、 regexps としても知られる正規表現を使用したパターンの記述が可能です。
ちなみに、以降の例では、全てのパターン指定を注意深く引用符で囲むことで、 Mercurial の処理の前にシェルによって展開されて しまうことを防いでいる、という点に注意してください。
glob 形式によるマッチングの際に、使用可能なパターンについての概要を以下に示します。
パターン “*” は、同一ディレクトリ内で任意の文字列に合致します。
パターン “**” は、ディレクトリ境界を超えて任意の文字列に合致します。このパターンは Unix における標準的なものではありま せんが、幾つかの著名なシェル実装で採用されており、非常に便利です。
パターン “?” は、単一の文字に合致します。
パターン “[” は、文字集合(character class)の開始を意味します。このパターンは当該集合に属する任意の一文字に合致します。 集合指定は “]” によって終了します。集合指定には、 “abcdef” の省略指定である “a-f” 形式の範囲指定を、複数含めることが可能で す。
文字集合指定において “[” の直後の文字が “!” 3 の 場合、集合指定は反転され、集合に属さない任意の一文字に合致します。
パターン “{” はサブパターンのグループ化の開始を意味し、グループ中の何れかのサブパターンが合致した場合は、グループ全体が 合致したものとみなされます。グループ指定におけるサブパターンの区切りには “,” が使用され、 “}” がグループの終了を意味しま す。
任意のディレクトリにおけるパターン合致が必要な場合は、単一ディレクトリ内でのマッチングしか行わない “*” を使用すべきでは無 い、という点は忘れないようにしてください。 “*” の代わりに “**” を使用しましょう。両者の違いを以下で説明しま す。
Mercurial は(Python の内部的な正規表現エンジンを利用しているので) Python が受け付けるのと同じ正規表現を受け付けます。こ の正規表現は Perl の正規表現文法を基にしており、最も多用されている(例えば Java でも使用されています)方言で す。
正規表現パターンはそれほど多用されるものではないので、 Mercurial の正規表現の詳細に関してここでは説明しません。 Perl 形 式の正規表現は様々な形式で、多くのウェブサイトや出版物において余す所無く説明されています。その代わりここでは、 Mercurial で正規表現を使用する必要に迫られた際に、知っておくべき幾つかの事柄について説明しようとおもいま す。
正規表現は、リポジトリルートからの相対的なファイル名全体に対して適用されます。言い換えるなら、foo サブディレクトリで作 業している場合でも、このディレクトリ配下のファイルに対してマッチングを行うなら、指定するパターンは “foo/” で始まっていなけ ればなりません。
Perl 形式の正規表現に馴染んでいる場合、 Mercurial の正規表現は rooted である点に注意してくださ い4 。正規 表現は文字列先頭からマッチングを実施しますので、文字列途中に対するマッチングは行われません。任意の位置に対してマッチングを 実施させたい場合、パターンの記述を “.*” で始める必要があります。
Mercurial が多様な方法を提供しているものは、ファイルの指定方法だけではありません。 Mercurial はフィルタによるファイル選別の 機能も提供しています。ファイル名指定を受け付けるコマンドは、以下の2つのフィルタリングオプションも受け付けま す。
複数の-I および-X オプションを、コマンド行で好きなように混在させることができます。 Mercurial の基底動は、指 定されたパターンを “glob” 形式とみなして解釈します(必要であれば明示的に “glob” を指定することも可能で す)。
-I フィルタは、 “合致したファイルのみを処理対象とする” ものと解釈すれば良いでしょう。
-X フィルタは、 “合致しないものを処理対象とする” ものと解釈することができます。
※ 原文未稿
Linux (ないし他の Unix 系 OS)と、 MacOS ないし Windows が混在する開発環境で作業する場合、ファイル名における文字の大小 (“N” と “n”)の扱い方針が全く異なる、という知識を心に留めておく必要があります。良くある事では無いかもしれ ませんし、容易に解決できる可能性もありますが、知らない状況で遭遇した場合、非常に驚かされる問題でもありま す。
OS およびファイルシステムに応じて、ファイルおよびディレクトリ名の文字の大小の扱いは異なります。名前における文字の大小 の一般的な扱い方を、以下に3つ示します。
Unix 的なシステムの上では、上記の大文字・小文字の取り扱い形式のうちの “任意” のものが(あるいは全てが同時に)要求される 可能性があります。例えば、 FAT32 ファイルシステムでフォーマットされた USB 小型メモリモジュールを Linux で 使用する場合、そのファイルシステム上での Linux の振る舞いは、文字の大小は保持しつつ無視するものとなりま す。
Mercurial のリポジトリ格納機能は、文字大小の区別の可否に影響を受けません。リポジトリの保存先ファイル名は元ファイル名を変換 したものなので、ファイルシステムにおける大文字小文字の区別の可否に関わり無く、構成管理情報を格納できます。つまり、 OS の標 準的な複製ツールを使用して、 Mercurial のリポジトリを例えば USB 小型メモリモジュールに複製し、 Mac、 Windows PC および Linux の間で持ち運ぶことができます。
作業領域ディレクトリにおける操作の際には、 Mercurial は作業領域を載せているファイルシステムの命名方針に従います。ファイル システムが文字の大小は保持しつつ無視するものであった場合、文字の大小のみが異なる名前を Mercurial は同じものとみなしま す。
この方針の重要な点は、文字大小を区別する(一般的な Linux や Unix における)ファイルシステムにおいて、文字大小を区別できない( Windows や MacOS の)ユーザが取り扱えないようなチェンジセットをコミットすることが可能である点です。 Linux の利用者が myfile.c とMyFile.Cという名前の2つのファイルに対する変更をコミットした場合、変更内容はリポジトリに正しく保存されます。他の Linux 利用者の作業領域ディレクトリにおいても、これらのファイルは異なるファイルとして正しく存在しま す。
Mercurial のリポジトリ格納機構が文字大小の扱いの可否に影響を受けないため、 Windows ないし MacOS 利用者がこの変更を取 り込んでも、最初は問題が発生しません。しかし、作業領域ディレクトリを当該チェンジセットで“hg update” しよ うとした場合、あるいは当該チェンジセットと“hg merge” しようとした場合、ファイルシステムが同じファイルと して扱う2つのファイルの衝突を見つけた Mercurial によって、“hg update” ないし“hg merge” は禁止されま す。
他のメンバーが Linux や Unix を使用している混在環境で Windows ないし MacOS を使用していて、“hg update” あるいは“hg merge” の際に Mercurial が文字大小の衝突を報告する場合、問題の解決手順は簡単です。
手近な Linux ないし Unix 利用者を探し、問題のリポジトリを“hg clone” してから、問題のファイルないしディレクトリを大文 字小文字の衝突が発生しないように、 Mercurial の“hg rename” コマンドで改名をすれば良いのです。その後、変更をコミット し、“hg pull” ないし“hg push” で Windows や MacOS に変更を取り込み、“hg update” によって衝突しない名前で変更内容を取 り出します。
大文字小文字の衝突を生じさせるチェンジセットそのものは、プロジェクトの履歴に残っており、当該チェンジセット を Windows や MacOS 上で作業領域ディレクトリに取り出すことはできませんが、開発を継続することは可能で す5 。