package io.gitlab.jfronny.convention.ext 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 { 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 = 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) data class Person(val original: PersonIdent, val name: String, val emailAddress: String)