Created
February 21, 2018 06:45
-
-
Save wobu/ccfaccfc6c04c02b8d1227a0ac151c36 to your computer and use it in GitHub Desktop.
Get first commit of file with JGit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.nio.file.Paths | |
import org.eclipse.jgit.lib._ | |
import org.eclipse.jgit.api._ | |
import org.eclipse.jgit.revwalk._ | |
import org.eclipse.jgit.treewalk._ | |
import org.eclipse.jgit.diff._ | |
val repo: Repository | |
val git: Git | |
def getFirstCommit(file: java.io.File): RevCommit = { | |
val filePathToAddHeader = Paths | |
.get(repo.getDirectory.getParent) | |
.relativize(Paths.get(file.getAbsolutePath)) | |
.toString | |
.replace("\\", "/") | |
import scala.collection.JavaConverters._ | |
/** | |
* get the logs of a file in the git repository and follows andy renames / copies of this file until the source of original creation is found. | |
* used this example: https://stackoverflow.com/questions/11471836/how-to-git-log-follow-path-in-jgit-to-retrieve-the-full-history-includi | |
*/ | |
def followCommits(path: String): RevCommit = { | |
val latestCommit = git | |
.log() | |
.add(repo.resolve(Constants.HEAD)) | |
.addPath(path) | |
.all() // all() is needed to include commits from all refs, otherwise it could happen that ammend commits aren't shown | |
.call() | |
.asScala | |
.toList | |
.last | |
val previousCommits = git | |
.log() | |
.add(latestCommit) | |
.setMaxCount(2) // we don't need more, cause we only want the previous commit for diffing | |
.call() | |
.asScala | |
.toList | |
val commitForDiff = previousCommits match { | |
case _ :: next :: _ => next // next is the previous commit we want for diffing! | |
case head :: _ => head // is the same as oldestCommit | |
case Nil => latestCommit // shouldn't happen because the same commit is always included | |
} | |
val tw = new TreeWalk(repo) | |
// oder is important! old commit has to be added before the new commit... | |
tw.addTree(commitForDiff.getTree) | |
tw.addTree(latestCommit.getTree) | |
tw.setRecursive(true) | |
val rd = new RenameDetector(repo) | |
rd.setRenameScore(50) // git client also detects renames with sim of > 50% | |
rd.addAll(DiffEntry.scan(tw)) | |
val files = rd.compute | |
val renames = files.asScala.filter { diff => | |
List(DiffEntry.ChangeType.RENAME, DiffEntry.ChangeType.COPY) | |
.contains(diff.getChangeType) && diff.getNewPath.contains(path) | |
}.toList | |
renames match { | |
case Nil => | |
latestCommit | |
case head :: Nil => | |
followCommits(head.getOldPath) | |
case _ :: _ => | |
throw new Exception(s"Error in rename detection of file '$filePathToAddHeader'") | |
} | |
} | |
try { | |
followCommits(filePathToAddHeader) | |
} catch { | |
case e: Throwable => | |
throw new Exception( | |
s"Exception while getting first commit of path '$filePathToAddHeader'", | |
e) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment