結局こうした。
def set_revision(kommit) repo = kommit.repository.repo Dir.chdir(repo.working_dir) do `git commit -m "#{kommit.message}"` branch_name = kommit.init_at.try(:name) || "master" output = `git rev-list #{branch_name}` newest_revision = output.split("\n").first kommit.revision = newest_revision end end
gritの挙動で非同期以外にもう一つ理解不能な点があって、repo.commitsでコミットオブジェクトの配列を取得するとき、その並びがドキュメントによるとコミット履歴順になって、commits.firstで最新のコミットがとれるはずなのだけど、自分の環境下ではテストのときにfirstが最新と限らないことがあった。
もしかしたら、コミットオブジェクトが持つ作成時間dateでソートしていて、これは秒単位だからテスト環境のように全く同じ時刻に作成してしまうと思わぬ挙動をしてしまうということか。
git commitの部分も結局自分で同期してやったほうが確実だと思ったのでこうした。もしこの部分がIOが負荷になるのであれば、そもそも@kommit.create自体をDelayedJobなどで処理するほうがよいだろうと思う。
ちなみに``(バッククオート)とKernel#systemの違いは、内部的なことはともかく使う分には前者は標準出力を文字列で返して、後者は処理が正常終了したかを真偽値で返してくれる。