Files
version-plugin/src/main/kotlin/net/keinekekse/version/AddVersionTask.kt
T

192 lines
6.1 KiB
Kotlin

package net.keinekekse.version
import io.github.z4kn4fein.semver.Version
import io.github.z4kn4fein.semver.withoutSuffixes
import org.gradle.api.DefaultTask
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.MapProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.*
import java.util.*
@CacheableTask
abstract class AddVersionTask : DefaultTask() {
// 1. Define what triggers the task (Source Files)
@get:InputFiles
@get:PathSensitive(PathSensitivity.RELATIVE)
abstract val sourceFiles: ConfigurableFileCollection
// 2. Define the output (The properties file)
@get:OutputFile
abstract val buildNumberFile: RegularFileProperty
@get:OutputFile
abstract val versionClassFile: RegularFileProperty
@get:Input
abstract val projectVersion: Property<String>
@get:Input
abstract val projectName: Property<String>
@get:Input
abstract val projectDescription: Property<String>
@get:Input
abstract val displayNameExtra: Property<String>
@get:Input
abstract val copyrightExtra: Property<String>
@get:Input
abstract val versionPackageName: Property<String>
@get:Input
abstract val modules: MapProperty<String, Map<String, String>>
@TaskAction
fun execute() {
val buildNumber = incrementAndGetBuildNumber()
writeClassFile(buildNumber)
}
private fun writeClassFile(buildNumber: String) {
var fileContent =
"""
package ${versionPackageName.get()}
import net.keinekekse.version.Version
""".trimIndent() +
buildVersionObject(
"",
projectVersion.get(),
buildNumber,
displayNameExtra.get(),
copyrightExtra.get(),
projectName.get(),
projectDescription.get()
)
if (modules.isPresent) {
modules.get().forEach { (moduleName, moduleInfo) ->
fileContent +=
buildVersionObject(
moduleName,
moduleInfo["version"] ?: "",
buildNumber,
moduleInfo["displayName"] ?: moduleName,
moduleInfo["copyright"] ?: copyrightExtra.get(),
moduleName,
moduleInfo["description"] ?: ""
)
}
}
val file = versionClassFile.get().asFile
file.parentFile.mkdirs()
file.writeText(fileContent)
}
private fun buildVersionObject(
moduleName: String,
versionString: String,
buildNumber: String,
longName: String,
copy: String,
shortName: String,
desc: String,
): String {
val ver = getVersionInfo(versionString, buildNumber, longName, copy, shortName, desc)
val module = if (moduleName.isBlank()) {
""
} else {
"_$moduleName"
}
return """
object VERSION$module: Version {
override val version = "${ver.version}"
override val fullVersion = "${ver.fullVersion}"
override val major = ${ver.major}
override val minor = ${ver.minor}
override val patch = ${ver.patch}
override val preRelease = "${ver.preRelease}"
override val buildMetadata = "${ver.buildMetadata}"
override val buildDate = "${ver.buildDate}"
override val displayName = "${ver.displayName}"
override val copyright = "${ver.copyright}"
override val name = "${ver.name}"
override val description = "${ver.description}"
}
""".trimIndent()
}
private fun getVersionInfo(
versionString: String,
buildNumber: String,
longName: String,
copy: String,
shortName: String,
desc: String,
): VersionInfo {
val version =
if (Version.parse(versionString, strict = false).buildMetadata.isNullOrEmpty())
Version.parse("$versionString+build.$buildNumber", strict = false)
else Version.parse(versionString, strict = false)
println("Source files changed. Setting version to $version")
return VersionInfo(
major = version.major,
minor = version.minor,
patch = version.patch,
preRelease = version.preRelease ?: "",
buildMetadata = version.buildMetadata ?: "",
fullVersion = version.toString(),
version = if (version.isPreRelease)
"${version.major}.${version.minor}.${version.patch}-${version.preRelease}" else
version.withoutSuffixes().toString(),
buildDate = java.time.Instant.now().toString(),
displayName = longName,
copyright = copy,
name = shortName,
description = desc
)
}
private fun incrementAndGetBuildNumber(): String {
val file = buildNumberFile.get().asFile
val props = Properties()
if (file.exists()) {
file.inputStream().use { props.load(it) }
}
val current = props.getProperty("build.number")?.toLongOrNull() ?: 0
val actual = (current + 1).toString()
props.setProperty("build.number", actual)
file.outputStream().use {
props.store(it, "auto generated")
}
return actual
}
data class VersionInfo(
val version: String,
val fullVersion: String,
val major: Int,
val minor: Int,
val patch: Int,
val preRelease: String,
val buildMetadata: String,
val buildDate: String,
val displayName: String,
val copyright: String,
val name: String,
val description: String,
)
}