如何使用JGit查找提交距离?

问题描述

我有一个Kotlin实用程序类,它使用JGit查找以下信息:

func createPlayerQueue(from content: [URL]) -> [AVPlayerItem] {
    content.map { AVURLAsset(url: $0) }.map { AVPlayerItem(asset: $0) }
}

其中branch,latestCommit,lastTag,lastTagCommit,lastReleaseTag,lastReleaseTagCommit,commitdistance 通过匹配给定前缀找到。

除了lastReleaseTagcommitdistance标记间的提交次数)之外的所有工作。我正在使用RevWalkUtils.count,但它始终返回零。

latestCommit

class GitRepo(dir: File) { private val log = LoggerFactory.getLogger(GitRepo::class.java) constructor(dir: String) : this(File(dir)) private val repository = FileRepositoryBuilder() .setGitDir(File(dir,".git")) .readEnvironment() .findGitDir() .setMustExist(true) .build() @JvmOverloads fun info(releaseTagPrefix: String = "release/"): RepoInfo { repository.use { repo -> RevWalk(repo).use { walk -> val latestCommit: RevCommit? = Git(repository).use { try { it.log().setMaxCount(1).call().iterator().next() } catch (ex: NoHeadException) { log.warn("Repository has no HEAD") null } } val tags = repo.refDatabase.getRefsByPrefix("refs/tags/") .groupBy { it.name.startsWith("refs/tags/$releaseTagPrefix") } .mapValues { entry -> entry.value.maxByOrNull { it.name } } val lastReleaseTag = tags[true] val lastTag = tags[false] val lastTagCommit = lastTag?.toRevCommit(walk) val commitdistance = if (latestCommit == null || lastTagCommit == null) 0 else RevWalkUtils.count(walk,lastTagCommit) return RepoInfo( repo.branch,latestCommit?.toObjectId()?.shorten(),lastTag?.tagName(),lastTag?.objectId?.shorten(),lastReleaseTag?.tagName(),lastReleaseTag?.objectId?.shorten(),commitdistance ) } } } private fun ObjectId.shorten(): String { return name.take(8) } private fun Ref.tagName(): String? { return "refs\\/tags\\/(.*)".toRegex().find(this.name)?.groupValues?.get(1) } private fun Ref.toRevCommit(revWalk: RevWalk): RevCommit? { val id = repository.refDatabase.peel(this)?.peeledobjectId ?: objectId return try { revWalk.parseCommit(id) } catch (ex: MissingObjectException) { log.warn("Tag: {} points to a non-existing commit",tagName()) null } } } 的命令行调用返回33。

JGit 5.9.0.202009080501-r。

解决方法

感谢@fredrik,这很简单,只需交换对RevWalkUtils.count的调用中的提交即可。但是,事实证明,RevWalkUtils.count返回的数字大于git rev-list --count start...end,可能是由于以下原因:

计算从开始到到达可到达的提交的数量

我最终更改了实现方式,如下所示:

class GitRepo(dir: File) {
    constructor(dir: String) : this(File(dir))

    private val log = LoggerFactory.getLogger(GitRepo::class.java)
    private val repository = FileRepositoryBuilder()
        .setGitDir(File(dir,".git"))
        .readEnvironment()
        .findGitDir()
        .setMustExist(true)
        .build()

    @JvmOverloads
    fun info(tagPrefix: String = ".*"): RepoInfo {
        repository.use { repo ->
            val lastTag: Ref? = repo.refDatabase.getRefsByPrefix("refs/tags/")
                .filter { it.name.matches("refs/tags/$tagPrefix".toRegex()) }
                .maxByOrNull { it.name }
            var latestCommit: RevCommit? = null
            var lastTagCommit: RevCommit?
            var commitDistance = 0
            Git(repo).use { git ->
                try {
                    latestCommit = git.log().setMaxCount(1).call().firstOrNull()
                    lastTagCommit = lastTag?.let {
                        val id = repo.refDatabase.peel(it)?.peeledObjectId ?: it.objectId
                        git.log().add(id).call().firstOrNull()
                    }
                    if (latestCommit != null && lastTagCommit != null) {
                        commitDistance = git.log().addRange(lastTagCommit,latestCommit).call().count()
                    }
                } catch (ex: NoHeadException) {
                    log.warn("Repository has no HEAD")
                } catch (ex: MissingObjectException) {
                    log.warn("Tag: {} points to a non-existing commit: ",lastTag?.tagName(),ex.objectId.shorten())
                }

                return RepoInfo(
                    repo.branch,latestCommit?.toObjectId()?.shorten(),lastTag?.objectId?.shorten(),commitDistance
                )
            }
        }
    }

    private fun ObjectId.shorten(): String {
        return name.take(8)
    }

    private fun Ref.tagName(): String? {
        return "refs\\/tags\\/(.*)".toRegex().find(name)?.groupValues?.get(1)
    }
}