Mercurial: "File names and pattern matching" を読む
Tagged:  •    •  

今回は "7. File names and pattern matching" を読みます。

7.1 Simple file naming

Mercurial に対するディレクトリ指定は、 当該ディレクトリ配下全てを指定したことと同意となります。

7.2 Running commands without any file names

Mercurial にファイル名等の引数を指定しないで実行した場合、 多くのコマンドが作業領域ディレクトリ全体に対して作用します。

チェンジセット指向の構成管理であることを考えれば当然のことですが、 現ディレクトリ配下にしか作用しない CVS に慣れている場合は注意が必要です。

ちなみに、作用対象を現ディレクトリ配下に限定したい場合は、 引数として現ディレクトリを表す "." を指定します。

7.3 Telling you what’s going on

5.1.1 Explicit versus implicit file naming」 でも述べられていますが、 ディレクトリ指定による間接的なものも含めて、 コマンドラインで明示的に指定されていないファイルを処理対象にする場合、 Mercurial は必ず対象ファイル名を列挙します。

7.4 Using patterns to identify files

Mercurial では、ファイルの特定に「パターン」指定を用いることができます。

パターンには、シェルにおける解釈と同等の、 いわゆる「ワイルドカード」的なものと、 正規表現の2種類が使用できます。

7.4.1 Shell-style glob patterns

ワイルドカードとして使用できるパターンを以下に示します。

  • "/" 以外の任意の文字列に合致する "*"
  • "/" を含む任意の文字列に合致する "**"
  • 任意の1文字に合致する "?"
  • 文字集合を指定する "[....]"
  • サブパターンの論理和を指定する "{A, B, ...}"

文字集合の否定形式には "!" を用いるそうです。

シェルでも正規表現と同様に "^" を使う筈だと記憶していたのですが、 試してみたところ bash などでは両方とも使用できるようです。いやぁ、日々勉強ですね。

7.4.2 Regular expression matching with re patterns

ファイル名マッチングにおける Mercurial の正規表現は、 暗黙のうちに "^" が付与 (Perl 等ではこれを "rooted" と言うらしいです)され、 リポジトリルートからの相対パスと比較されます。 つまり以下の指定は等価となります。

  • re:path/to/filename
  • re:^path/to/filename

そのため、以下の2つのパターンのうち、 リポジトリ中の path/to/filename に合致するのは前者のみです。

  • re:path/to/filename
  • re:to/filename

任意の階層下にある to/filename に合致させるには、 "re:.*/to/filename" と指定する必要があります。

7.5 Filtering files

ファイル名指定を受け付けるコマンドは、 パターン指定を伴った "-I"(including) オプションと "-X"(excluding) オプションの複数指定が可能になっています。

7.6 Ignoring unwanted files and directories

この節は原文では未稿状態となっています。

.hgignore ファイルの man page があるので、 とりあえず後回しとなっているのかもしれません。

注意しなければいけないのは、 「7.4.2 Regular expression matching with re patterns」 で説明されているように、 コマンド行指定での正規表現マッチングは、 暗黙のうちに rooted とみなされますが、 .hgignore ファイルにおける正規表現マッチングは rooted とは扱われないことです。

ですから、コマンド行での "-X re:hoge" と、 .hgignore ファイルでの "hoge" 正規表現指定は、 異なる意味に解釈をされます。 うーん、すごく紛らわしいと思うのですが、 こういう混在性って世間的には普通なんでしょか?

7.7 Case sensitivity

ファイル名・ディレクトリ名の文字の大小の扱いについて、 本節では以下のように分類しています。

  • 完全に文字の大小を無視(DOS)
  • 文字の大小は保持されるが無視(Windows/MacOS)
  • 文字の大小を区別(Unix/Linux)

しかし、X68000 というパソコンを持っていた人にとっては、 FAT 上に保持されているファイル名との比較の際に、 厳密には DOS は文字大小を無視するようにはなっていなかったことが、 骨身に沁みているのではないでしょうか。

指定されたファイル名・ディレクトリ名を FAT に書き込む際に、 DOS は全てを大文字化してから書き込みます。 また、コマンド行で指定されたファイル名との一致比較の際にも、 入力値を全て大文字化してから実施しています。 つまり、 大文字に正規化していたのであって、 FAT 内容の処理の際に文字の大小を無視していたのでは無かったのです (後述する DOS の振る舞いを見れば、 このように実装されていたことが推測できます)。

しかし X68000 の OS は FAT への書き込みの際に文字大小の情報をそのままにして書き込んでいたため、X68000 で書き込んだ FD を DOS で読み込もうとすると:

  1. X68000 のコマンド行で書き出しファイル名を指定
  2. X68000 はファイル名の文字大小をそのままに FAT に書き込み
  3. DOS のコマンド行で読み込みファイル名を指定
  4. DOS はファイル名を大文字化
  5. DOS は FAT 中のファイル名と strcmp() 的に比較
  6. 文字大小が異なるので比較失敗
  7. ファイル不在でエラー

という困った状況に陥ってしまうのでした。

文字大小を無視した比較は結構なコストになりますから、 文字大小無視の比較をファイル名検証の都度実施するよりも、 書き込みの際に大文字に正規化しておいて比較そのものは単純比較、 という方が処理コストの点で考えると得策であることは自明なのですが、 だったら文字大小を区別する方が楽じゃないの? という気がしないでもありません。

ある意味どうでもよい豆知識ですが、 こういう経験が積み重なると、 可搬性(portability)とか相互接続性(inter-operability) とかの重要性が強く意識されますので、 痛い目に遭うことも役に立つと言えるでしょう。

7.7.1 Safe, portable repository storage

「Mercurial のリポジトリは、 ファイルシステムの文字大小認識性に依存せずに、 ファイル名の文字大小を認識可能」という話。

Mercurial 0.9.3 版から導入されたこの機能は、 例えば実際のファイル・ディレクトリ名中の "A" を、 リポジトリ中の対応するデータファイル・ディレクトリ作成の際には "_a" と符号化することで、 文字大小の識別をファイルシステムに依存せずに実現しています。

7.7.2 Detecting case conflicts

「リポジトリ自体は文字大小を区別できても、 ローカルファイルシステムが区別できない場合は hg update が失敗する」という話。

個人的な経験からも、 2つのファイルが文字の大小のみで識別されるのは見辛い事この上ないので、 避けるようにした方が良いでしょう。

ちなみに、文字大小とは関係ないですが、 ファイルシステム固有の名前問題繋がりで、 落とし穴になりやすい問題を一点。

Windows は "con" や "aux" という名前が任意のディレクトリにおいて参照可能になっているため、 全く同じ名前は勿論のこと、 "con.txt" のような、所謂「8.3形式ファイル名」 における 8 の部分がこれらの予約語に一致する名前の場合であっても、 ファイル・ディレクトリ共に作成が失敗します。

例えば OpenSolaris の Mercurial リポジトリはこういったディレクトリ・ファイルを含むため、 Windows 環境での hg clone は失敗します。

7.7.3 Fixing a case conflict

「文字大小で問題が発生した場合は、 手近な環境で文字大小の衝突が発生しないように hg rename」という話。


この節をもって、 コマンドリファレンス・インストール手順等を除いた "Distributed revision control with Mercurial" の全ての章を読み通したことになります("1. Introduction" は歴史的な経緯等の話が主である点から、 2. A tour of Mercurial: the basics は基本的な Mercurial の用法が主である点から、 Inside ASCADE での紹介は見送りました)。

このエントリが公開される頃には、 本家のリポジトリに日本語版として翻訳成果が統合されているようにしたいものです。 訳し切れていない箇所や、 見直さなければならない表現等が山のようにありますが…。


"Distributed revision control with Mercurial" 関連エントリの一覧は、BOSBook(Bryan O’Sullivan Book)タグで参照できます。