ZIP 形式アーカイブのタイムスタンプ問題
※ 2012/09/13 追記
とりあえず、時間の無い人向けに、簡単にまとめると:
- "
hg archive
" で生成した ZIP 形式のアーカイブは、展開時に日時情報がタイムゾーンオフセット分だけずれる ⇒ 日本では 9 時間早い日付になる - 展開時にタイムゾーンを明示的に GMT ベースにすれば回避可能: "
(export TZ=UTC; unzip archive.zip)
" など - 展開時に上記のようなタイムゾーンの明示的な指定ができない場合 (例: Windows のエクスプローラ等での展開が想定されるようなケース) は、以下の様な手順で ZIP 形式アーカイブを生成
#!/bin/sh # USAGE: hgziparch ZIPFILE [OPTS] ZIPFILE=$1; shift # 一時ディレクトリを作成 mkdir /tmp/$$ # tar 形式アーカイブを元に展開イメージを作成 hg archive -t tar $* - | (cd /tmp/$$ && tar xf - ) # 展開イメージを元に zip アーカイブを作成 (cd /tmp/$$ && zip -rq - *) > ${ZIPFILE} # 展開イメージを破棄 rm -rf /tmp/$$
ちなみに、この問題の根本的な原因は、Python が標準提供している zip アーカイブ取り扱いライブラリの zipfile モジュールが、タイムスタンプに関する extended attribute を扱えないことにあるので、Mercurial が独自に対応するのは難しい見込み。 ⇒ 既存機能の範囲で修正可能なことが判明しました! ※ 2012/09/13 追記
以上、簡単なまとめ終わり。
以下は、この障害に関する事の顛末。
発端は Twitter で寄せられた以下の不具合情報。
『9時間』というあたりが、明らかにタイムゾーン絡みなんだろうなぁ、とおもわせる問題なので、再現性確認と、問題箇所の絞込みを行う事に。
"hg archive -t zip -r REV
" で生成した ZIP アーカイブを、Windows のエクスプローラにより展開したところ、何のひねりも無く再現。
実装を確認したところ、アーカイブファイル作成処理では、tar も zip も格納されるタイムスタンプ情報はGMT ベースのものが使用されている。で、tar で展開した場合はタイムスタンプの問題が無いことから、unzip の実装がよろしくないのでは?という印象。
ところが、BTS での障害報告ベースでやり取りする過程で、zip アーカイブに extended attribute としてタイムスタンプ情報が付いている場合は、期待通りにタイムスタンプが設定されるらしいという情報を入手。
確かに、zip コマンドの通常実行で作成したアーカイブは、期待通りのタイムスタンプで展開されるけれど、"zip -X
" 実行により extended attribute 無しで作成されたアーカイブは、"hg archive -t zip
" と同様に想定外のタイムスタンプで展開される。
それならば、アーカイブファイル作成の際に extended attribute を足してやれば良かろう、と思いきや、Python 標準の zipfile モジュールでは、ZIP アーカイブの extended attribute に関する配慮が無いことが判明…… orz
こうなると、Python 本体に修正提案 ⇒ 取り込みができたとしても、古い Python 処理系では問題が解消されないので、根本的に対処しようとするなら、実行時にクラス定義を上書きしてやる、などの対処が必要に。
うーん、ZIP ファイルの仕様を把握するだけで、相当に骨が折れそうなので、そこまで頑張る気力がなぁ………。
※ 以下、2012/09/13 追記
と思っていたら、既存機能の範囲で修正可能であるとの情報が!
(extended, extra) x (attribute, field) の組み合わせが散在していて、ZIP の仕様書を読み込む気力が全然無かっただけに、この情報は大変ありがたい。
技術的な目処は付いたから、後は修正/試験だけだな。