彷徨えるフジワラ

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

largefiles エクステンション漬けの日々

Mercurial 2.0 から largefile エクステンションが正式に同梱配布されるようになった。

Mercurial では、基本「ファイルの差分」を格納しているのだけれど、「差分」という形式上、バイナリファイルの格納はあまり効率的ではない。とは言っても、「すっげー無駄」って訳では無いと思うけどね。

で、バイナリファイルはそもそも特性が違うのだから、そういったファイルは、従来の「ファイルの差分」格納領域とは別な場所にまるごと格納するようにした方が良くねぇ?ということで導入されたのが、largefiles エクステンションなのだ。

名称からしてわかるように、「でかいファイル」を対象として想定していることから、おそらく:

後で使うかどうかもわからないでかいファイルを、pull 契機でバンバン転送するってのはどーよ?

と思ったのであろう、「pull 契機ではファイル本体は転送しない」という実装方針がとられている。
じゃぁ、どの契機でファイル本体を転送するのか?というと、update による作業領域更新とかで、実際にファイル本体が必要になった時なのだ。

そうなると当然:

同一起源のリポジトリを複数持っている場合、それぞれで必要になる都度、マスターリポジトリから転送するのって、無駄じゃねぇ?っていうか、オフラインの時はどうするのよ?

という突込みが入るであろうことは、容易に推測出来る。

それに対する回答が、「ユーザ単位のキャッシュ領域(e.g.: ${HOME}/.cache/largefiles 配下)にキャッシュして使いまわす」という実現方式。

まぁ、この辺の実現/管理方式の詳細に関しては、別途本家 Wiki ページの翻訳や、解説ページを作ろうと思うので、とりあえずここではこの辺で。

で、そんな感じの largefiles エクステンションなのだが、オフラインスキーな自分としては、当然キャッシュ周りの挙動を把握しておきたい所なので、早速使ってみた。

オフラインを想定した、キャッシュが無い状態での挙動を色々確認していると....あれ? "hg status" の出力がおかしくないか?

でかいファイルを追加するリビジョン前後で行き来するような "hg update" を行うと、キャッシュの引き当てに失敗したでかいファイルの状態が "R"、つまり "hg remove" 実施対象扱いされてしまう!

"hg revert" でも解消しないけど、.hg/largefiles の削除によって管理情報が再構築されると、正しい状態表示に戻るから、これは明らかにバグだよなぁ ... orz

しかし、ここで俄然スイッチが入ってしまうのが、因果な気性(笑)。

再現させながら発生条件を絞り込みつつ、ソースを彷徨うこと暫し....(日付が変わる)....largefiles 固有の dirstate 管理に漏れがあることが判明!

最初は Greg Ward 氏と同様に、lfiles_repo.status() の変更で対応する修正をしてみたのだけれど、問題発生が .hg/largefiles/dirstate の不完全性に起因するものなので、やっぱりそれって対処療法だよなぁ、でも、どこをどう直したら良いのかなぁ、と探し回って、1日余計に費やしてしまったのだ。

あぁ、やっぱり Pythonデバッグ技法/環境をゴニョゴニョしないと効率悪くていかんなぁ.... orz

さて、障害は修正したのだけれど、キャッシュ保証の問題とか、間接的にでかいファイルの転送が発生した場合の連携先リポジトリ指定とか、現状の実装には諸々の点で個人的な不満を感じたので、一連の改善案をまとめて mercurial-devel に投函するべく、今週はひたすら largefiles のソースと首っ引き状態。

とりあえず4本の改善案を投げてみたけれど、はてさて、どういう評価が得られるのやら、暫くはドキドキ状態だなぁ。