以前から,Gitのリポジトリの状態などをzshのプロンプトに表示していたのだけど,precmdのフックでgit logとかgit statusが何度も呼ばれていて,大変遅かった.
プロンプトが出るまで何も操作できなくて,困っていたので,dRubyで,非同期にリポジトリの状態を調べて,Growlで通知するようにした.
何かコマンドを実行するたびに,リポジトリの情報がGrowlで出てくるので,常に,自分が何をしているのか気にすることができる.
これを予めどこかで起動しておいて,
#! /opt/local/bin/ruby require 'rubygems' require 'drb/drb' require 'git' require 'g' class Service def git_status(path) Thread.new { path = File.expand_path path git = Git.open(path) rescue return g git.current_branch changed = git.status.changed.length g "#{changed} changes" if changed > 0 local = git.log(1).between('origin', 'HEAD').count g "#{local} local commits" if local > 0 } end end uri = ARGV.shift || 'druby://localhost:12345' DRb.start_service(uri, Service.new) puts DRb.uri sleep
このスクリプトを,パスの通ったところに置いて,
#! /opt/local/bin/ruby require 'rubygems' require 'drb/drb' there = DRbObject.new_with_uri('druby://localhost:12345') there.git_status(Dir.pwd)
.zshrcで,precmdのフックで実行するようにする.
precmd () { git_status }
GitHubに置いた.
http://gist.github.com/310741
体感速度が上がったので,Gitに限らず,重い処理をprecmdでやりたいときは,dRubyに処理させるとよい感じになりそう.
追記
どうも動きがおかしい気がする.branchがずっとmasterになってる.
追記2
直した.
git.branch
すると,今チェックアウトされてるブランチをもらえると思っていたら,そうではなくて,このメソッドは,
git.branch("piyo")
とかして,指定した名前のブランチを取得するメソッドだった.名前を省略するとmasterになる.
現在チェックアウトしているブランチを取得するには,
git.current_branch
する.そうすると,現在チェックアウトしている(ブランチのオブジェクトではなくて,)ブランチの名前を取得できる.想像を絶する感じだけど,そういう仕様だった.