2010年1月アーカイブ

gem2rpm と "~>"

gem のバージョン指定(Gem::Requirement)で "~>" という指定ができるけど、RPM ではできない(ですよね?)件。
RubyForge: Gem to rpm converter: Project Info

gem2rpm の中(gem2rpm.rb)で、Gem::Requirement を拡張していて、Gem::Requirement#to_rpm というメソッドを追加しています。このメソッドは、gem の spec に記載(?)されている依存ライブラリのバージョン番号を、RPM にふさわしいバージョン番号に変換する役割を担います。

この to_rpm メソッドは、gem2rpm のバージョン 0.6.0 現在、ほぼ素通りとなっています。やっていることは、"> 0.0.0" だった場合に "" に置換するのみです。"~>" が使われていても、素通りしてしまうため、RPM に蹴られてしまいます。

gem2rpm は、2008/10/06 のリリースで止まっているので、"~>" に対応しないまま今日に至る、ということでしょう("~>" の追加がいつ行われたのかは把握していません)。

なんでこんな話をしているかというと、actionpack-2.3.5 の RPM を作成する必要があり、その中で rack のバージョン指定 "~> 1.0.1" に遭遇したわけです。なので、どうにかして gem2rpm を "~>" に対応させる必要があるわけなのです(gem2rpm を使わない、というのもありですが...)。

そんな訳で、RPM 作成どころか SRPM を作成するところまでは試していませんが、以下のような修正でごまかしてみようかと思っています。手元では RPM をビルドする環境が整っていないので、検証は後ほど。

--- gem2rpm.rb.orig     2010-01-29 00:19:42.000000000 +0900
+++ gem2rpm.rb  2010-01-29 00:28:15.000000000 +0900

@@ -24,15 +24,20 @@
 module Gem
   class Requirement
     def rpm_version_transform(version)
-      if version == "> 0.0.0"

-        version = ""
+      case version
+      when "> 0.0.0"
+        [""]
+      when /^~> (.+)$/
+        v = Gem::Version.new($1)

+        [">= #{v.version}", "< #{v.bump}"]
+      else
+        [version]
       end
-      version

     end
 
     def to_rpm
       result = as_list
-      return result.map { |version| rpm_version_transform(version) }
+      return result.inject([]) {|res, version| res += rpm_version_transform(version) }

     end
 
   end

CentOS5(x86_64) の script コマンドを実行すると、script という名前で 2 つのプロセスが存在するのは、なんでだろうか。OSX と FreeBSD では script という名前では 1 つしか存在しないのに。

どこに情報があるかわからなかったので ftp://ftp.kernel.org/pub/linux/utils/util-linux/util-linux-2.12a.tar.gz に含まれるソース(util-linux-2.12a/misc-utils/script.c)を読んでみました。

  • 親プロセスが fork() して子プロセスを生成する
  • 子プロセスが fork() して孫プロセスを生成する

まず、都合 3 プロセスが生成されることがわかりました。

そのうち、孫プロセスはわかりやすく、execl でシェルを起動させていました。bash であれば、ps に出てくる名前は "bash -i" になるので、script が複数存在する件とは関係ないこともわかりました。

子プロセスは、pty のマスタから read() で読み続け、読み込んだ内容はログファイルに書き出しています。read() が 0 以下を返した場合に、読み込みのループから抜けて終了処理に移る様です。

親プロセスは、まず SIGWINCH シグナルのハンドラを登録しています。そして、標準入力から read() で読み込んだ内容を pty のマスタに書き込み続け、read() が 0 以下を返したら終了処理に移る様です。

どうやら、pty がキーワードな様子。プロセスも pty もよくわかってないわけですが、よく見れば孫プロセスがシェルを起動する際にスレーブに触っているので、シェルから書き込んだ内容を親子が使っている様な空気を感じます。

孫プロセスから流れてくるデータを子プロセスがファイルに書き込んでいるという感じでしょうか。親プロセスが標準入力からマスタに書き込んでいるのは、シェルに出力する必要があると言うことでしょうか(シェル側で読み取って何かに使う?)。

んー、親が延々と標準入力を読み続けているから、親プロセスが生き続けているということでなんでしょうか。それとも、read() が返らないとかでしょうか。

というわけで、使い方を間違えているのか、この状態(親子孫が生き続ける)が自然なのか、今の自分では判断がつきませんでした。


OSX や FreeBSD の script のソースがどこにあるかわからず読んでいないので、Linux と BSD とでプロセスの数が異なるのが、script の実装が異なるのか、もっと下のところで違いがあるのか、わかりません。

理由もなくアップグレード。

なんか、インデックスページが賑やかになってよいです。

ほぼ、新規インストールなので、プロフィール的なリンクとか、色々と削れてますが、そのうち付け加えたりするかと思います。

2009 年はブログ記事の数もそうですが、だいぶ沈滞した年でした。今年は、そこそこ動いてみようかなと思ったり、思わなかったりのこの頃です。

プロフィール

このアーカイブについて

このページには、2010年1月に書かれたブログ記事が新しい順に公開されています。

前のアーカイブは2009年12月です。

次のアーカイブは2010年2月です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。