0
0

More than 3 years have passed since last update.

JGitで"git log --follow <path>"を実現

Last updated at Posted at 2020-03-10

Gitの再実装であるJGitは,JavaのAPIとして利用できることから開発や研究などの幅広い分野で用いられている.
一方非常に癖があることで知られており,良く知られているコマンドを実行するのにも苦労することがある.
今回は,ファイル名の変更を考慮したうえでファイル単位のログを取得するgit log --follow <path>をJGitを用いてJavaプロジェクト内で実行する方法をメモとして書き残しておく.

方法

実は過去に似たような質問がStack Overflowでされていて,それに対する解答もある.
https://stackoverflow.com/questions/11471836/how-to-git-log-follow-path-in-jgit-to-retrieve-the-full-history-includi

一方,この実装はかなりイケてないらしい(https://www.eclipse.org/lists/jgit-dev/msg03286.html ).
JGitの開発者曰く,用意されているFollowFilterを使えば良いらしい.

実装

FollowFilterはインスタンスをRevWalkに食わせて使うらしいので,call()の返り値をダウンキャストして食わせれば良さそう.

class LogCommand(projectPath: Path) {
    private val repository: Repository = FileRepository(projectPath.resolve(".git").toFile())
    private val git: Git = Git(repository)

    fun execute(filePath: Path): List<RevCommit> {
        val followFilter: FollowFilter = FollowFilter.create(filePath.toString(), Config().get(DiffConfig.KEY))
        followFilter.renameCallback = DiffCollector()

        val walk = git.log().addPath(filePath.toString()).call() as RevWalk
        walk.treeFilter = followFilter
        return walk.toList()
    }

    private static class DiffCollector : RenameCallback() {
        val diffs: MutableList<DiffEntry> = mutableListOf()
        override fun renamed(diff: DiffEntry) {
            diffs.add(diff)
        }
    }
}

実行した感じちゃんと動いてそう.

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0