彷徨えるフジワラ

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

Mercurial のパターン指定におけるディレクトリ相対性/合致条件

本エントリも、備忘録代わりに「お気に入り」に入れておいたツィートの棚卸しシリーズの一部です(笑)

随分前になりますが、以下のツィートに関連する一連のツィートで、パターン指定に関してのやり取りがありました。

一般的な利用ケースでは、それほど踏み込んだパターン指定の必要はないと思いますが、折角ですので、文書化されていない情報を含めて、パターン指定絡みの仕様をきっちりとまとめておこうと思います。

パターンにおける「起点ディレクトリ」

以下の表は、hg help patterns で表示されるオンラインヘルプ(ウェブ経由でも参照可能)の記載を元に、パターン形式と起点ディレクトリの関係について、簡単にまとめたものです。

パターン形式名称起点ディレクト
拡張ワイルドカード glob ディレクト
正規表現 re リポジトリルート
文字列一致 path リポジトリルート

しかしこれだけでは、パターン指定の全貌を掴むのには不十分です。
起点ディレクトリに関して、文書化されていない指定形式の情報を含めて、もう少し詳しく見てみましょう。

パターン形式起点ディレクト
ディレクトリポジトリルート任意(部分一致)
拡張ワイルドカード glob----relglob
正規表現 ----rerelre
文字列一致 relpathpath----

通常のパターン指定は、特定の起点ディレクトリからのパスに対して、先頭一致であることが求められます。しかし、「任意(部分一致)」の場合は、リポジトリルート相対パスに対する部分一致のみで、そのファイルはパターンに一致したものとみなされます。

例えば、管理対象ファイル foo/bar/baz.txt に対して、foo/bar 以外ディレクトリからは、glob:baz.txt 指定は合致しませんが、relglob:baz.txt であれば、作業領域中のどのディレクトリにいても合致します。

このように、起点ディレクトリ(glob であれば現ディレクトリ)と結びついている状態は、"rooted" と表現されます。relglobrelre は rooted ではありません。

.hgignore における文法指定 globre は、実際には relglobrelre のことを指しています。つまり、コマンドラインでの glob 指定と、.hgignore での glob 指定では、起点となるディレクトリが違うということです。

hg help patternshg help hgignore 等のオンラインヘルプでも、これらの特徴に関して、備考として補足しています(2.8.2 版時点だと、翻訳版の hg help hgignore での備考の表現は、ちょっと微妙かもしれません。2.9 版向けに直しておこうと思います)。

パターンにおける「末尾一致」

さて、先程の "rooted" の話は、起点ディレクトリからのパスに対する「先頭一致」の話と言えますが、もう一点、パスに対する「末尾一致」の話があります。

以下の表は、パターンと指定方法の組み合わせに対して、末尾一致が要求されているか否かをまとめたものです。

形式 名称 末尾一致
引数指定時-I/-X 指定時
拡張ワイルドカード glob 必要不要
relglob
正規表現 re 不要不要
relre
文字列一致 path 不要不要
relpath

末尾一致が必要なものは、管理対象ファイル名の末尾までが、指定パターンの合致範囲に含まれていなければ、合致したものとみなされません。

例えば foo/bar/baz.txt に対して、コマンドライン引数としての glob:foo/barrelglob:bar は合致しません

その一方で、末尾一致が不要なものは、パターンの合致範囲がファイル名末尾を網羅していなくても、合致したものとみなされます。

そのため、-I glob:foo/bar-X relglob:bar であれば、先述の foo/bar/baz.txt に対しても合致とみなされます。

もしも、コマンドライン引数での指定で glob 形式を合致させたい場合は、glob:foo/bar/** のように指定する必要があります(あるいは path:foo/bar で代替する手も)。

この辺の微妙な差異は、代表的なユースケースにおける利便性ベースで決定されたのか、歴史的経緯(=後方互換性維持)に由来するものなのかは定かではありませんが、微妙にわかりにくい感じではありますね。

まとめ

以下の表は、これまでの情報をまとめたものです。

形式 名称 起点ディレクト 末尾一致 備考
引数指定時-I/-X 指定時
拡張ワイルドカード glob ディレクト 必要不要 ----
relglob 任意 .hgignore での glob
正規表現 re リポジトリルート 不要不要 ----
relre 任意 .hgignore での re
文字列一致 path リポジトリルート 不要不要 ----
relpath ディレクト コマンドラインのデフォルト形式

今回色々確認した際に気付いたのですが、pathrelpath なども末尾一致が不要なパターンであるため、正確には「厳密一致」という訳ではありませんね。個人的には、これらのパターンは「末尾合致が必要」なイメージを持っていたので、ちょっと意外でした。