注意書き
情報を集めたのが数年前なので、より新しい方法が存在する可能性があります。
背景
JGitは少し癖のあるライブラリで、gitの解析をしていた際に困った記憶があります。
そんな当時のコードが一部発掘され、役に立つ人がいるかもしれないので掲載します。
他の解析をしたい場合は、以下のドキュメントが参考になるかと思います。
JGit User Guide
JGit API Documentation
前提
リポジトリを表す変数名は、repositoryとします。
以下のコードで作成しています。
val repository = new FileRepository(new File(repositoryPath + "/.git"))
if( ! repository.getRepositoryState.canResetHead ){
println("target path is not a valid repository")
System.exit(0);
}
ここでは、gitリポジトリが存在するかどうか、また、正常な状態かどうかの判定をcanResetHeadで行っています。
チェック方法は様々あるかと思いますが、resetできればおおよそ解析には困らない状態なはずですので、ひとまずこの方法を採用しています。
サンプル
カレントブランチのコミットメッセージ一覧を表示
val revWalk = new PlotWalk(repository)
val rootId = repository.resolve("HEAD")
val root = revWalk.parseCommit(rootId)
revWalk.markStart(root)
val plotCommitList = new PlotCommitList[PlotLane]()
plotCommitList.source(revWalk)
plotCommitList.fillTo(Integer.MAX_VALUE)
for( c <- plotCommitList )
println( c.getFullMessage )
HEADからInteger.MAX_VALUE個だけコミットを遡る、というシンプルなサンプルです。
もちろんそんなにコミット数は無いので、限界まで遡る、という意味合いになります。
repository.resolve()に文字列を与えると、解析して適切なObjectId(git内部で使ってるハッシュ)を返してくれます。
下の例では"HEAD"を与えていますが、例えば"HEAD^"を与えると1つ前のコミットからたどり始めます。
このサンプルではコミットメッセージのみですが、RevCommitクラスに格納されている情報を出力することができます。
あるコミットにおけるdiffを取得
val df = new DiffFormatter(DisabledOutputStream.INSTANCE)
df.setRepository(repository)
df.setDiffComparator(RawTextComparator.DEFAULT)
df.setDetectRenames(true)
def get(c: RevCommit): mutable.Buffer[DiffEntry] =
c.getParentCount match {
case 0 => mutable.Buffer.empty[DiffEntry]
case _ => df.scan(c.getParent(0), c.getTree).asScala
}
getにコミットを与えることで、その親との差分を取得できます。
差分情報は、ファイルごとにDiffEntryというクラスに収められます。
DiffEntryには、新しい側の情報と古い側の情報が両方保存されており、リネームや破棄を検出することが可能です。
例えば、AからBにrenameされた場合は、getOldPath="A", getNewPath="B"となります。
また、Aが破棄された場合は、getOldPath="A"、getNewPath="/dev/null"となります。
特定リビジョンのファイルの内容を表示
git cat-file -pです。
該当ファイルのID(blob)を取得した後、以下の通りストリームを使って取得する必要があります。
val fileId = ... // 目的ファイルのobject ID
val loader = repository.open(fileId)
loader.copyTo(System.out) // loader.openStream でInputStreamが取得できる
まとめ
JGitは扱いにくい癖があるので、上記サンプルが参考になれば幸いです。