gem2arch

実家に帰ってきているんだが,対応を誤って輪番停電により下宿のマシンが起きてこなくなってしまったためやることが無くなり,なんとなく gem を Arch のパッケージマネージャで管理しようとした.
同じような PKGBUILD を手動で書くのはタルいので cabal2arch のように gem から自動生成することを考えて書いたのがこれ.ローカルにある gem のパスを引数として渡すとそれの PKGBUILD を生成する.
自動といっても特にC向けのライブラリに依存するようなライブラリの depends まで知る術は無いので,必要に応じて適切に手書きする必要がある.*1
あと Gem::Specification のマニュアル によると license(s) というフィールドが (important ではないが) ちゃんとあるのに,これを設定している gem が手元だと rake-compiler しかなく,今回いくつか生成した PKGBUILD については全部 license を手動で書く羽目になった.

#!/usr/bin/ruby
# coding: utf-8
require 'rubygems'
require 'rubygems/format'
require 'fileutils'
require 'erb'

class Gem2Arch
  def initialize(gem)
    @gem = gem
    @spec = Gem::Format.from_file_by_path(@gem).spec
  end

  def name
    @spec.name
  end

  def pkgname
    'ruby-' + name
  end

  def version
    @spec.version.to_s
  end

  def pkgdesc
    #@spec.description
    @spec.summary
  end

  def arch
    @spec.extensions.empty? ? ['any'] : ['i686', 'x86_64']
  end

  def url
    @spec.homepage || "http://rubygems.org/gems/#{@spec.name}"
  end

  def license
    if @spec.licenses
      @spec.licenses
    else
      $stderr.puts "#{pkgname}: License not found!"
      []
    end
  end

  def depends
    ['ruby'] + @spec.runtime_dependencies.map do |dep|
      s = 'ruby-' + dep.name
      if dep.requirement and not dep.requirement.none?
        s + Gem::Requirement.parse(dep.requirement.to_s).join('')
      else
        s
      end
    end
  end

  ERB.new(DATA.read).def_method self, 'to_pkgbuild'
end

ARGV.each do |gem|
  arch = Gem2Arch.new gem
  Dir.mkdir arch.pkgname unless Dir.exist? arch.pkgname
  Dir.chdir arch.pkgname do
    if File.exist? 'PKGBUILD'
      FileUtils.mv 'PKGBUILD', 'PKGBUILD.bak'
    end
    open('PKGBUILD', 'w') do |f|
      f.write arch.to_pkgbuild
    end
  end
end

__END__
pkgname=<%= pkgname %>
_realname=<%= name %>
pkgver=<%= version %>
pkgrel=1
pkgdesc='<%= pkgdesc %>'
arch=(<%= arch.map(&:inspect).join(' ') %>)
url='<%= url %>'
license=(<%= license.map(&:inspect).join(' ') %>)
depends=(<%= depends.map(&:inspect).join(' ') %>)
makedepends=('rubygems')
source=(http://rubygems.org/downloads/$_realname-$pkgver.gem)
noextract=($_realname-$pkgver.gem)

build() {
  cd "$srcdir"
  local _gemdir="$(ruby -rubygems -e 'puts Gem.default_dir')"
  gem install --ignore-dependencies -i "$pkgdir$_gemdir" $_realname-$pkgver.gem
}

# vim:set ts=2 sw=2 et:

*1:例えば ruby-nokogiri が libxslt に依存しているとか