TimestampMod mbcs対応
そのうちwikiかissueにまとめる予定ではありますが、現状を。 現在Nathan氏の本家からforkして、https://bitbucket.org/flied_onion/timestampmod_fliedonion にリポジトリを構えて実装中です。
最新のリビジョンでは暫定的な対処がはいっています。暫定的とはいえ、簡単なテストはおこなっており、本家0.2.5で追加された部分をきちんとパスするかがきちんと検証できてないだけですし、私自身すでに実務で使用しています。 また、本家リポジトリのNathanも非常に協力的な姿勢でいてくれています。(お礼の返事を書かないといけないんだけど、なかなかまとまった時間がなくて英文が書けない) ある程度確認がとれたら本家に取り込んでもらうつもりでいます。
TimestampModの現状
ここ最近(0.1.4以降だっけ?)TimestampModは内部ファイル(.hgtimestamp)をcsv形式で持っていました。途中からJSONフォーマットに切り替わったのですが、このことによりマルチバイト問題が発生しました。csv時代は私もつかっていなかったので、起きてたかどうかわかりません…おきるんじゃないかとは思ってますが。
TimestampModの文字コードの扱い
Mercurialにはencodingモジュールに格納されたエンコード、HGENCODEの値、ファイルシステムエンコード、タグ文字列やコミットメッセージなどのエンコード、pythonのUNICODEオブジェクトなどさまざまなエンコードが登場しますが、TimestampModで気にしなくてはならないエンコードは現在のところ、ファイルシステムのデフォルトエンコードとUTF8です。 TimestampModでは.hgtimestampの書き込み時に特にエンコード指定なくファイルをopenし、出力します。読み込み時もまたJSONライブラリのloadメソッドで特にエンコード指定なく読み込みを行います。 一見問題なさそうですが、openはsys.getfilesystemencoding()で取得できるエンコードが選択され、JSON.loadはデフォルトはUTF8が選択されるので、ここでエンコードの不一致が起こります。 そしてファイル名にマルチバイトを使用した場合、.hgtimestampの書き込みには成功するが、読み込み(というかJSON.load)には失敗するという状況が発生します。
どこに寄せるか
先々のことを考えたりいろいろ悩んだりしたのですが、最初の修正の観点としては、 「書き込みには成功する以上、すでにシステムのデフォルトのファイルシステムエンコードのマルチバイト文字列を含む.hgtimestampは存在する。」ので、これをまず救うことだけ考えることにしました。異なるエンコードを持つシステムに対しての処置は行っていないことを意味しますが、現状でもマルチバイトを使用したリポジトリは、異なるエンコードの環境に移行できないので(Linux-UTF8とWindows-cp932の相互運用はできないという趣旨で言っています)そこは考えず、「そのリポジトリを使っている環境でちゃんと動く」をサポートします。 mercurialjaに投稿したものはUTF8で保存してみたり、cp932固定にしてみたり、encoding.encodingつかってみたりといろいろやってはいたんですが、上記の判断によって現状は「JSON.loadがデフォルト指定で開けない場合は、sys.getfilesystemencoding()のエンコードで開いてみる」だけの修正となっています。
解決したのか
Windows(cygwin除く)環境でsys.getfilesystemencoding()は 'mbcs'を返します。stdinやstdoutのエンコードはきちんとしたエンコードを返しますが、'mbcs'はエイリアスかなにかの扱いで実際のエンコードではありません(マルチバイトキャラクターシステムかなにかの略)。このため、日本語Windowsで作ったリポジトリはほかのマルチバイト環境のWindowsに持って行っても動かないんだろうなと思っています。これについては検証の予定はありません(もし実験された方がいれば教えてください。)。おそらく、デフォルトでのloadに失敗し、sys.getfilesystemencoding()を使ったopenにも失敗し、きっと古いフォーマットだからCSVとして処理しようとしてそれも失敗して更新時間が復元されない状態になると思います。
将来的な問題
Linux-Windows相互運用の話をしました。これ以外にも(私もよくわかっていませんが)Windowsの'mbcs'というエンコードが結局何かはOSしかしらないという問題があります。 これは現在UTF8化がすすめられているため、Mercurial側はいずれ統合されることになるでしょう。コンテキストから返されるファイル名のエンコードも変わるのであれば(変わると思いますが)TimestampModへの対応かリポジトリコンバートへの取り込み依頼が必要になります。対応となった場合はMercurialのバージョンで判断するのか、なにか別のプロパティ(リポジトリのバージョンだとか、encoding.encodingのようなもんだとか)から拾えるのか、判断基準がどうなるかなど考えることは多そうですが、考えすぎても仕方がないのでまずは見守ります。(-人-)ナムナム
それ以外のフィーチャ
現在わかっているTimestampModで直したいところをだらだらと挙げていきます
・同じファイルを修正していた場合に.hgtimestampに必ずコンフリクトが起こる
同じ行が変わるので当然といえば当然ですが、厄介です。また時刻のシリアル値でもっているのでパッと見どっちを採用していいのかわかりません。 マージツールを用意するのか、.hgtimestampのフォーマットを拡張するのかですね。 hgrcへ常にローカルとかつねにotherとかつねに新しい時刻とか設定できるようにするのもいいかもしれません。ソース(.hgtimestamp以外のリポジトリで管理されているファイル)の方でもコンフリクトが起きていた場合、どちらかが完全に捨てられる可能性があるので、システムで決定することはできませんがユーザーが指定できるようにするのはアリだと思っています。
・MQ周り
NathanはMQをあまり使わない人らしくあんまり気にしてなかったようですが、MQ使うと落ちるバグがありました。それ自体はissueに投稿して修正してもらったんですが、qrefreshとqapplyの振る舞いに少し不満があるため、そこを修正したいと考えています。フジワラさんの助言でwrapcommandを使うのがいいんじゃないかというコメントはもらっていますが、なかなか時間が取れずまだ取り掛かれていません。
・.hgtimestampが存在しないリビジョン
updateしたリビジョンに.hgtimestampが存在しない場合、現在はエラーとなります。 継続処理に影響ないですし、存在内から日付も復元しようがないので結果的には問題はないんですが、存在チェックするだけで精神衛生がすこし保たれるならやったほうがいいだろうなと思っています。ついでにない場合はコミット日付にしてしまうというのも手なのかなぁ、それならそのリビジョンに一番近い.hgtimestampひろってやるべきなのかなぁ、などと下手に壮大なことを考えて止まっています。 存在チェックだけはissueに投げてさっさといれちゃうかな。
・リポジトリ単位での無効化ができない
これはMercurial側のバグだと思ってますが、 (私のtortoiseHg 2.4.1環境で)Mercurial.iniのextensionsにTimestampModを定義しておいて、 リポジトリのhgrcにTimestampMod=! などとしても無効化できません。 ていうか localrepoのextensions読み込んで、!で始まるものをみつけてもpassするだけなので、親のextensionsを無効化する機能が抜けてるのかな?とちょっと思ってます。 フジワラさんがMLに投げていて修正も大体できているらしいですが、ひょっとするとそれとは逆なのかな(フジワラさんのは「有効化できない」というバグなのかな)という懸念もあります。 あんまり詳しく見ていませんが、とりあえず無効にできないのは場合によっては不便なのでなんとかしたいところです。
現状こんな感じです。あまり多くには答えられませんが、なにかあればお尋ねください。 Nathanもいい人だしレスポンスすごいはやいので、本家のissueにproposalとかで投稿するのも手です。その場合英語になりますが、私も苦手だから大丈夫です(何が)。










