Scripts/convention/src/main/kotlin/io/gitlab/jfronny/scripts/JGitExt.kt

87 lines
3.2 KiB
Kotlin

package io.gitlab.jfronny.scripts
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.errors.IncorrectObjectTypeException
import org.eclipse.jgit.lib.AnyObjectId
import org.eclipse.jgit.lib.Constants
import org.eclipse.jgit.lib.ObjectId
import org.eclipse.jgit.lib.PersonIdent
import org.eclipse.jgit.lib.Ref
import org.eclipse.jgit.lib.Repository
import org.eclipse.jgit.revwalk.RevCommit
import org.eclipse.jgit.revwalk.RevTag
import org.eclipse.jgit.revwalk.RevWalk
import java.time.Instant
import java.time.ZoneOffset
import java.time.ZonedDateTime
fun Git.log(since: AnyObjectId? = null, until: AnyObjectId? = null): List<Commit> {
var command = this.log()
if (since != null) command = command.not(since)
if (until != null) command = command.add(until)
return command.call().map { it.resolve(repository) }
}
fun Git.getTags(): List<Tag> = repository.refDatabase.getRefsByPrefix(Constants.R_TAGS)
.map { it.resolveTag(repository) }
.sortedByDescending { it.dateTime }
fun Ref.resolveTag(repo: Repository): Tag = RevWalk(repo).use { walk ->
val rev = try {
walk.parseTag(objectId)
} catch (e: IncorrectObjectTypeException) {
// Lightweight (unannotated) tag
// Copy information from commit
val target = walk.parseCommit(objectId).resolve(repo)
return Tag(objectId, null, name, target, target.author, target.fullMessage, target.shortMessage, target.dateTime)
}
walk.parseBody(rev)
walk.parseBody(rev.`object`)
val target = walk.peel(rev)
walk.parseBody(target)
return rev.resolve((target as RevCommit).resolve(repo))
}
fun RevTag.resolve(commit: Commit): Tag {
val ident = taggerIdent
return Tag(
id,
this,
name,
commit,
Person(ident, ident.name, ident.emailAddress),
fullMessage,
shortMessage,
ZonedDateTime.ofInstant(
ident.`when`.toInstant(),
ident.timeZone?.toZoneId() ?: ZoneOffset.UTC
)
)
}
fun RevCommit.resolve(repo: Repository): Commit = Commit(
this,
ObjectId.toString(this),
try {
repo.newObjectReader().use { reader -> reader.abbreviate(this).name() }
} catch (e: Exception) {
Exception("Could not abbreviate $name", e).printStackTrace()
null
},
Person(committerIdent, committerIdent.name, committerIdent.emailAddress),
Person(authorIdent, authorIdent.name, authorIdent.emailAddress),
ZonedDateTime.ofInstant(
Instant.ofEpochSecond(commitTime.toLong()),
committerIdent.timeZone?.toZoneId() ?: ZoneOffset.UTC
),
fullMessage,
shortMessage,
parents.map { ObjectId.toString(it) }
)
data class Tag(val id: ObjectId, val original: RevTag?, val fullName: String, val commit: Commit?, val tagger: Person?, val fullMessage: String?, val shortMessage: String?, val dateTime: ZonedDateTime?) {
val name: String
get() = Repository.shortenRefName(fullName)
}
data class Commit(val original: RevCommit, val id: String, val abbreviatedId: String?, val committer: Person, val author: Person, val dateTime: ZonedDateTime, val fullMessage: String, val shortMessage: String, val parentIds: List<String>)
data class Person(val original: PersonIdent, val name: String, val emailAddress: String)