Use git shortlog for gathering contributors

This commit is contained in:
Jonathan Coates 2022-12-13 20:31:59 +00:00
parent 06163e4f25
commit 0787e17ebe
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06
4 changed files with 32 additions and 39 deletions

View File

@ -2,6 +2,7 @@
import net.ltgt.gradle.errorprone.CheckSeverity
import net.ltgt.gradle.errorprone.errorprone
import org.gradle.api.GradleException
import org.gradle.api.NamedDomainObjectProvider
import org.gradle.api.Project
import org.gradle.api.Task
@ -25,10 +26,8 @@
import org.gradle.testing.jacoco.tasks.JacocoReport
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import java.io.BufferedWriter
import java.io.File
import java.io.IOException
import java.io.OutputStreamWriter
import java.net.URI
import java.net.URL
import java.util.regex.Pattern
@ -39,43 +38,30 @@ abstract class CCTweakedExtension(
) {
/** Get the hash of the latest git commit. */
val gitHash: Provider<String> = gitProvider(project, "<no git hash>") {
ProcessHelpers.captureOut("git", "-C", project.projectDir.absolutePath, "rev-parse", "HEAD").trim()
ProcessHelpers.captureOut("git", "-C", project.rootProject.projectDir.absolutePath, "rev-parse", "HEAD").trim()
}
/** Get the current git branch. */
val gitBranch: Provider<String> = gitProvider(project, "<no git branch>") {
ProcessHelpers.captureOut("git", "-C", project.projectDir.absolutePath, "rev-parse", "--abbrev-ref", "HEAD")
ProcessHelpers.captureOut("git", "-C", project.rootProject.projectDir.absolutePath, "rev-parse", "--abbrev-ref", "HEAD")
.trim()
}
/** Get a list of all contributors to the project. */
val gitContributors: Provider<List<String>> = gitProvider(project, listOf()) {
val authors: Set<String> = HashSet(
ProcessHelpers.captureLines(
"git", "-C", project.projectDir.absolutePath, "log",
"--format=tformat:%an <%ae>%n%cn <%ce>%n%(trailers:key=Co-authored-by,valueonly)",
),
ProcessHelpers.captureLines(
"git", "-C", project.rootProject.projectDir.absolutePath, "shortlog", "-ns",
"--group=author", "--group=trailer:co-authored-by", "HEAD",
)
val process = ProcessHelpers.startProcess("git", "check-mailmap", "--stdin")
BufferedWriter(OutputStreamWriter(process.outputStream)).use { writer ->
for (authorName in authors) {
var author = authorName
if (author.isEmpty()) continue
if (!author.endsWith(">")) author += ">" // Some commits have broken Co-Authored-By lines!
writer.write(author)
writer.newLine()
.asSequence()
.map {
val matcher = COMMIT_COUNTS.matcher(it)
matcher.find()
matcher.group(1)
}
}
val contributors: MutableSet<String> = HashSet()
for (authorLine in ProcessHelpers.captureLines(process)) {
val matcher = EMAIL.matcher(authorLine)
matcher.find()
val name = matcher.group(1)
if (!IGNORED_USERS.contains(name)) contributors.add(name)
}
contributors.sortedWith(String.CASE_INSENSITIVE_ORDER)
.filter { !IGNORED_USERS.contains(it) }
.toList()
.sortedWith(String.CASE_INSENSITIVE_ORDER)
}
/**
@ -257,7 +243,7 @@ fun downloadFile(label: String, url: String): File {
}
companion object {
private val EMAIL = Pattern.compile("^([^<]+) <.+>$")
private val COMMIT_COUNTS = Pattern.compile("""^\s*[0-9]+\s+(.*)$""")
private val IGNORED_USERS = setOf(
"GitHub", "Daniel Ratcliffe", "Weblate",
)
@ -269,6 +255,9 @@ private fun <T> gitProvider(project: Project, default: T, supplier: () -> T): Pr
} catch (e: IOException) {
project.logger.error("Cannot read Git repository: ${e.message}")
default
} catch (e: GradleException) {
project.logger.error("Cannot read Git repository: ${e.message}")
default
}
}
}

View File

@ -4,33 +4,37 @@
import org.gradle.api.GradleException
import java.io.BufferedReader
import java.io.File
import java.io.IOException
import java.io.InputStreamReader
internal object ProcessHelpers {
fun startProcess(vararg command: String): Process {
// Something randomly passes in "GIT_DIR=" as an environment variable which clobbers everything else. Don't
// inherit the environment array!
return Runtime.getRuntime().exec(command, arrayOfNulls(0))
return ProcessBuilder()
.command(*command)
.redirectError(ProcessBuilder.Redirect.INHERIT)
.also { it.environment().clear() }
.start()
}
fun captureOut(vararg command: String): String {
val process = startProcess(*command)
process.outputStream.close()
val result = ProcessGroovyMethods.getText(process)
if (process.waitFor() != 0) throw IOException("Command exited with a non-0 status")
process.waitForOrThrow("Failed to run command")
return result
}
fun captureLines(vararg command: String): List<String> {
return captureLines(startProcess(*command))
}
val process = startProcess(*command)
process.outputStream.close()
fun captureLines(process: Process): List<String> {
val out = BufferedReader(InputStreamReader(process.inputStream)).use { reader ->
reader.lines().filter { it.isNotEmpty() }.toList()
}
ProcessGroovyMethods.closeStreams(process)
if (process.waitFor() != 0) throw IOException("Command exited with a non-0 status")
process.waitForOrThrow("Failed to run command")
return out
}

View File

@ -22,6 +22,6 @@ dependencies {
}
tasks.javadoc {
// Depend on
classpath += docApi
// Depend on the common API when publishing javadoc
classpath += docApi.get()
}

View File

@ -32,7 +32,7 @@ tasks.processResources {
inputs.property("gitHash", cct.gitHash)
filesMatching("data/computercraft/lua/rom/help/credits.txt") {
expand(mapOf("gitContributors" to cct.gitContributors.get()))
expand(mapOf("gitContributors" to cct.gitContributors.map { it.joinToString("\n") }.get()))
}
}