Shibuya.lisp Hackathon #1でJGit+Clojureをいじった
Shibuya.lisp Hackathon #1に参加してきました。各言語ごとで島を作ってわいわい(またはもくもく)やる中、私はClojure島に参加してました。
やったこと
Javaによるgitクライアント実装のJGitをClojureから使おうと試してました。
野望としてはWebベースのgitリポジトリブラウザでも作れればと思っていたのですが、全然そこまでは行きませんでした。
準備
leiningenで "lein new hoge" とかやってプロジェクトを作成。で、project.cljにJGitのリポジトリを追加。
:repositories {"jgit-repository" "http://download.eclipse.org/jgit/maven"}
dependenciesにもJGitを追加。
[org.eclipse.jgit/org.eclipse.jgit "0.9.3"]
SLIMEを使う場合には、:dev-dependenciesでlein-swankも追加しておきます。
あとはlein depsを実行してから、lein swank+SLIMEなりlein replなりでREPLを実行。
はまった過程
結論だけ読みたい人はこのセクションを飛ばしてください。
まず困ったのが、公式サイトにドキュメントがないっぽいし、jgitの.jarにもドキュメントがないこと。Clojure島の人に相談して、ソースをgit cloneしてjavadocでリファレンスを作りました。
で、org.eclipse.jgit.api.Gitクラスのインスタンスでgitコマンドの操作をできるらしいということがわかり、まずは参照系としてgit log的なことをやってみようかと。
ここからがハマりどころ。
- org.eclipse.jgit.api.Gitのインスタンスを作りたい
- コンストラクタの引数にorg.eclipse.jgit.lib.Repositoryのインスタンスをとるらしい
- org.eclipse.jgit.lib.Repositoryのコンストラクタの引数にorg.eclipse.jgit.lib.BaseRepositoryBuilderのインスタンスをとるらしい
- org.eclipse.jgit.lib.BaseRepositoryBuilderのコンストラクタの引数にjava.io.Fileのインスタンスをとるらしい
- java.io.Fileのインスタンスを作った
- org.eclipse.jgit.lib.BaseRepositoryBuilderのインスタンスを作った
- org.eclipse.jgit.lib.BaseRepositoryBuilderのコンストラクタの引数にjava.io.Fileのインスタンスをとるらしい
- org.eclipse.jgit.lib.Repositoryのnewがエラー(対応するコンストラクタがない)になる
- Baseってついてるのはダメかなと思って、org.eclipse.jgit.lib.RepositoryBuilderにしても、やっぱりダメ
- org.eclipse.jgit.lib.Repositoryのコンストラクタの引数にorg.eclipse.jgit.lib.BaseRepositoryBuilderのインスタンスをとるらしい
- コンストラクタの引数にorg.eclipse.jgit.lib.Repositoryのインスタンスをとるらしい
しょうがないので、org.eclipse.jgit.lib.Repositoryのソースを見てみました。
…"public abstract class" って宣言されてる…JavaDocなドキュメントを見返すと、確かにそこにも書かれてた orz
org.eclipse.jgit.lib.Repositoryの継承クラスを調べると、org.eclipse.jgit.storage.file.FileRepositoryというのがありました。java.io.Fileをとるコンストラクタがあるので簡単そう。
→成功。ここまででだいたい16時ぐらい。
使い方。
まずimport。
user> (import '(org.eclipse.jgit.api Git)) org.eclipse.jgit.api.Git user> (import '(org.eclipse.jgit.storage.file FileRepository)) org.eclipse.jgit.storage.file.FileRepository user> (import '(java.io File)) java.io.File
で、FileRepositoryクラスのオブジェクトをGitのnewに渡すと、Gitクラスのオブジェクトができました。".git"ディレクトリを指定するのに注意。
user> (Git. (FileRepository. (File. "/path/to/repo/.git"))) #<Git org.eclipse.jgit.api.Git@1e852be>
Clojureらしく->を使うと、こうかな。
user> (-> "/path/to/repo/.git" File. FileRepository. Git.) #<Git org.eclipse.jgit.api.Git@3f4a21>
とりあえずdefしておきます。
user> (def git (-> "/path/to/repo/.git" File. FileRepository. Git.)) #'user/git
git log相当の操作をしてみます。".."を使ってメソッドチェーン。
user> (.. git log call) #<RevWalk org.eclipse.jgit.revwalk.RevWalk@601f3f>
戻り値はシーケンスのようです。ためしにtakeで先頭の3要素を取ってみます。
user> (take 3 (.. git log call)) (#<RevCommit commit 7fe4cc728ae509ba48e48ae111cb32d6311bebc0 1271268189 ----sp> #<RevCommit commit 4d905b1b6cbc3709618c8706d5af910922adc49d 1270661391 ----sp> #<RevCommit commit a889cc92f2cbb97a138a282d700e02e26c9d600e 1270661330 ----sp>)
それぞれのコミットはRevCommitのインスタンスのようです。HEAD、つまりシーケンスの最初の要素をとって、コミットメッセージを取得してみます。
user> (. (first (.. git log call)) getFullMessage) "use Key in get-prop\n"
文字列として取れました。
ここまでで時間終了。
コメント
コメントの投稿
トラックバック
http://emasaka.blog65.fc2.com/tb.php/825-109c8a23
