VirtualBox の設定ファイルを簡単にバックアップするツールを作って公開する過程で分かったこと
まとめ
- bin/ ディレクトリに置いて gemspec の exectables に入れてやれば Rakefile も実行ファイルとしてインストール可能
- github で gem を公開するには repository の設定で [ Rubygem ] にチェックを入れて gemspec を push するだけ
cutagem 簡単だし依存も少ないし、いいよ! PHP で Pear パッケージ作るより楽だと思うよ!
vbox_tools
wtnabe's vbox_tools at master - GitHub
昨今なんでもかんでも rake でやりたい病の wtnabe です。今回は VirtualBox の設定ファイルのバックアップの取り回しを rake でやります。
背景
なんでこんなもん作ったか。
- VirtualBox はバージョンアップで xml ファイルに非互換が入る場合がある
- VirtualBox はバージョンアップするとなんだか分からないけど guest が kernel panic で起きなくなる場合がある。その際、extradata の部分を一度削除して素の状態に戻すると普通に起動できることが多い。
- 一度新しいバージョンで起動できると extradata を元に戻しても以前と同じように動作する。
という、困った症状が Windows host, MacOSX host 問わず起きることがあります。経験から言うと Windows host の方がトラブルが多い気がします。Linux host では使ったことがありません。
そして設定ファイルのフォーマットに非互換が生まれる場合しか VirtualBox はバージョンアップ時に自動的に設定ファイルのバックアップを取ってくれません。これはちょっと怖いというか何かあったときに面倒くさい。
ということで作りました。
中身は VBoxManage1 と FileUtils の組み合わせで、そんなに面白いもんじゃないです。苦労したのは設定ファイルなどをエディタに渡して開くところで、最終的に Windows では満足いく動作を得られていません。
Rakefile を gem で bin としてインストールしたい
bin としてインストールするためにやったことは簡単で、
bin/vbox_tools ( <- Rakefile )
に Rakefile を置いてこれを gemspec に exectables として追加するだけ2。これで gem install すると PATH の通った bin ディレクトリにこの Rakefile を読み込むだけのファイルができあがります。
ただし、開発時にはこのままでは実行できないので shebang を
#! /PATH/TO/rake -f
にしておきます。あ、実際に作ったものは
#! /usr/bin/env rake -f
にしてあるんだけど、これで動くのは *BSD だけかも。
Windowsでは
ただし Windows の場合は事情が違います。Windows で gem install すると bin/vbox_tools が Ruby をインストールした bin ディレクトリ、たぶん C:\Ruby\bin に作られ、さらにこれを ruby で実行するための .bat ファイルが生成されます。
しかしこの自動生成の .bat ファイルはあくまで Ruby で呼び出すことを目的としているので Rakefile を bin としてインストールしたい場合は嬉しくありません。
今回は解決方法が分からなかったので gem の中に予め .bat を用意しておいて、Windows の人は手作業でこの .bat ファイルを C:\Ruby\bin などの中に copy して使ってくれとドキュメントの中に書くことでお茶を濁しました。
何かいい方法あるんでしょうか。
cutagem で github に gem を置きたい
先日のgem 作るには何がいいのという記事には全然反応がありませんでしたが3、結局依存が少なくて手間の少なそうな cutagem を使うことにしました。
準備
gem source -a http://gems.github.com
gem install genki-cutagem
作業開始
cutagem GEMNAME
すると
- 指定した名前のディレクトリがカレントに作成される
- その中に skelton がダダっとできる
- 何かキーを押すと Rakefile を編集するためにエディタが起きる
- ここで AUTHOR や EMAIL など必要な情報を入れて閉じる
試しにこの段階の vbox_tools は以下のようなツリーになります
vbox_tools
|-- ChangeLog
|-- README
|-- Rakefile
|-- lib
| `-- vbox_tools.rb
`-- test
|-- test_helper.rb
`-- vbox_tools_test.rb
Rakefile がありますね。早速
rake
と叩くといきなりテストが動いて、当然何もコードがないので RED になります。いいですね、TDD です4。こういう環境がお膳立てされるのはゼロから自分でテストツールの使い方を調べて導入して…とやっていくより断然楽ちんなので、すぐにスタートを切ることができます。
で、今回は github の話なので
作ったディレクトリで git init
を忘れずに。
cutagem にできること
rake -T
rake clean # Remove any temporary products.
rake clobber # Remove any generated file.
rake clobber_package # Remove package products
rake clobber_rdoc # Remove rdoc products
rake debug_gem # Show information about the gem.
rake gem # Build the gem file vbox_tools-0.0.1.gem
rake gemspec # Update gem spec
rake package # Build all the packages
rake rdoc # Build the rdoc HTML Files
rake release # Package and upload the release to rubyforge.
rake repackage # Force a rebuild of the package files
rake rerdoc # Force a rebuild of the RDOC files
rake rubyforge # Publish to RubyForge
rake test # Run tests for test
今回使うのは gemspec, test だけです。
作る
省略。
rake で test しまくって目的の動作を実現してください。
実行ファイルを gemspec の exectables に追加
skelton の bin/ ディレクトリの中に実行バイナリとしてインストールしたいファイルを置くだけでは gem install したときにはインストールされません。
cutagem で作った Rakefile の中に
BIN_FILES = %w()
という行がありますので、ここを書き換えます。vbox_tools の場合は
BIN_FILES = %w( vbox_tools )
としました。
gem を公開するまで
いちばん簡単に書くと
repository 側の準備が
- github 上にアカウントを取って repository を作成する
- repository admin で [ Rubygem ] にチェックを入れる
で ok. 手元の作業としては
- rake gemspec
- .gemspec を生成します。lib/ 内の VERSION の値が自動的に使われるので、gem のバージョンを上げる場合はこの値を変更します。
- git commit
- git push
で、おしまいです。github では gemspec が生成、更新されたタイミングで gem を生成するらしいので、動作が安定するまで gemspec は放置で、必要に応じて rake gemspec してあげればよいということになります5。なるほどよくできてる。
実際には今回自分は Windows と MacOSX 両方での動作を確認するために
- rake gem で gem を生成
- Dropbox 経由で Windows に転送
- Windows, MacOSX で gem install XXX.gem を実行して、生成した gem をローカルでインストールし、動作を確認
- 必要に応じて修正
という作業を行っていました。Dropbox 内のファイルって別ドライブとしてコピーされるんじゃなくて、移動になるんですね。初めてまともに使った。便利だ。
ハマったところ
github 上で gem が生成されるのは
- repository の [ Rubygem ] にチェックが入った状態で
- gemspec ファイルが生成されたか更新されたタイミング
のようです。
私は
- Rubygem のチェックを忘れたまま gemspec を上げていた
- 忘れていたチェックを入れて gemspec のバージョンを上げてみたけど反映されなかった
- 一度消して( rm -> push )、これを戻した( revert -> push )ら、あっという間に生成された
という経緯でした。ま、新しいことをやってみるんだから一度や二度ハマるのは想定の範囲内ってもんです。
special thanks
以下の発言、記事に助けられました。ありがとう!