2011.12.25
■[Ruby] bundler gem での外部コマンド実行のための枠組み
bundler gem の gem_helper.rb の該当箇所を読んだメモです。これといって独特なところ、読みにくいところはなく、使いまわせそうな普通のコードでした。次の 2 つがおもな特徴です。
- 実行結果と実行したコマンドの終了ステータスが取得できる
- コマンドが成功だった場合に実行する処理を可変にしてある(ブロック渡しで指定)
▼ 定義
def sh(cmd, &block)
out, code = sh_with_code(cmd, &block) # 丸投げ
code == 0 ? out : raise(out.empty? ? "Running `#{cmd}' failed. Run this command directly for more detailed output." : out)
end
def sh_with_code(cmd, &block)
cmd << " 2>&1" # 2 の出力先を 1 の出力先と同じものに設定する、という指定を追加しておく
outbuf = ''
Bundler.ui.debug(cmd)
Dir.chdir(base) { # コマンドを実行するディレクトリは可変
outbuf = `#{cmd}`
if $? == 0
block.call(outbuf) if block # コマンド実行成功時の処理も可変
end
}
[outbuf, $?]
end
▼ 呼び出し
def build_gem
file_name = nil
sh("gem build -V '#{spec_path}'") { |out, code|
# 文字列[/正規表現/] で部分文字列の存在チェック
raise out unless out[/Successfully/]
file_name = File.basename(built_gem_path)
FileUtils.mkdir_p(File.join(base, 'pkg'))
FileUtils.mv(built_gem_path, 'pkg')
Bundler.ui.confirm "#{name} #{version} built to pkg/#{file_name}"
}
File.join(base, 'pkg', file_name)
end
