sqlite3-ruby 1.2.2 の gem のパーミッションが変な話

http://slashdot.jp/developers/comments.pl?sid=410440&cid=1384452

最近RoR始めたんだけど、標準のデータベースsqlite3がうまく扱えなかった。
原因は、sqlite3-rubyのGEMのパーミッションが腐ってるからだった。
いくらなんでも、品質悪過ぎ。
RoRが悪いわけじゃないけど。

という話ですが、これは困る人結構いるんじゃないでしょうか。原因は、/.J の方にも書きました(http://slashdot.jp/developers/comments.pl?sid=410440&cid=1384686)が、単純にパッケージングミスだと思います。でも根本的には RubyGems が gem の中の data.tar.gz のパーミッション値をアテにしているのが間違っているような気がします。umask の値を利用するか、もしくは bin は 755、その他は 644 のように決め打ちしちゃった方が良いのではないかと思うのですが、どうなのでしょう。

しかしまさか RubyGems が自前で tar を展開しているとは思いませんでした。というわけで RubyGems は tar なライブラリとしても便利に使えそうです。まずは書庫の作成から。

require "rubygems/package"

File.open("test.tar", "w") do |tar|
  Gem::Package::TarWriter.new(tar) do |writer|
    writer.add_file("test.rb", 0o644)
  end
end

これで test.tar が作成されるので確認。

% tar tfv test.tar
-rw-r--r-- wheel/wheel       0 1970-01-01 09:00 test.rb

ということで、パーミッション情報は記録されているけれども作成時間やグループ名、ユーザ名は記録されていません。でもこれは TarWriter#add_file を使っているからで、add_file 相当の処理を自分で書いて header をきちんとすれば対応できます。

では読み込み。

require "rubygems/package"

File.open("test.tar") do |tar|
  Gem::Package::TarReader.new(tar) do |reader|
    reader.each do |entry|
      puts entry.header.name
    end
  end
end
# => "test.rb"

以上により、Ruby の可搬性のある tar ライブラリとしてとっても役に立ちそうな気がしました。1.9 なら標準添付なので間違いなく使えるし 1.8 でもほとんどの人が RubyGems を使用していると考えられますから、こいつは間違いなく便利ですね!