Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
238ef0a162 | ||
|
|
a1a6038219 | ||
|
|
94a6b7adaa | ||
|
|
e9e28d2ce7 | ||
|
|
0ec2193cc7 |
No files matched your search
+26
-12
@@ -1,27 +1,37 @@
|
|||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
/*
|
|
||||||
* This file was generated by the Gradle 'init' task.
|
|
||||||
*
|
|
||||||
* This is a general purpose Gradle build.
|
|
||||||
* To learn more about Gradle by exploring our Samples at https://docs.gradle.org/8.6/samples
|
|
||||||
*/
|
|
||||||
plugins {
|
plugins {
|
||||||
`kotlin-dsl`
|
`kotlin-dsl`
|
||||||
`maven-publish`
|
`maven-publish`
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
maven("https://nexus.keinekekse.net/repository/maven-public/")
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "net.keinekekse"
|
group = "net.keinekekse"
|
||||||
version = libs.versions.versionplugin.get()
|
version = masterLibs.versions.versionPluginVersion.get()
|
||||||
description = "Adds version information to the project."
|
description = "Adds version information to the project."
|
||||||
project.ext.set("displayname", "Version-Plugin")
|
extra["displayname"] = "Version-Plugin"
|
||||||
project.ext.set("copyright", "(c) 2024 Hartmut Bauer")
|
extra["copyright"] = "Copyright (c) 2024-2026 Hartmut Bauer"
|
||||||
project.ext.set("buildTimestamp", Instant.now().toString())
|
extra["buildTimestamp"] = Instant.now().toString()
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(masterLibs.semver)
|
||||||
|
compileOnly(masterLibs.kotlinGradlePlugin)
|
||||||
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
credentials {
|
||||||
|
username = "admin"
|
||||||
|
password = "admin123"
|
||||||
|
}
|
||||||
|
url = uri("https://nexus.keinekekse.net/repository/maven-releases/")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
gradlePlugin {
|
gradlePlugin {
|
||||||
plugins {
|
plugins {
|
||||||
create("version-plugin") {
|
create("version-plugin") {
|
||||||
@@ -31,8 +41,12 @@ gradlePlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
jvmToolchain(masterLibs.versions.javaVersion.get().toInt())
|
||||||
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
toolchain {
|
toolchain {
|
||||||
languageVersion.set(JavaLanguageVersion.of(17))
|
languageVersion.set(JavaLanguageVersion.of(masterLibs.versions.javaVersion.get()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
kotlin.code.style=official
|
||||||
Vendored
BIN
Binary file not shown.
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright © 2015-2021 the original authors.
|
# Copyright © 2015 the original authors.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@@ -15,6 +15,8 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
#
|
||||||
@@ -55,7 +57,7 @@
|
|||||||
# Darwin, MinGW, and NonStop.
|
# Darwin, MinGW, and NonStop.
|
||||||
#
|
#
|
||||||
# (3) This script is generated from the Groovy template
|
# (3) This script is generated from the Groovy template
|
||||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
# within the Gradle project.
|
# within the Gradle project.
|
||||||
#
|
#
|
||||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
@@ -84,7 +86,7 @@ done
|
|||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
APP_BASE_NAME=${0##*/}
|
APP_BASE_NAME=${0##*/}
|
||||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD=maximum
|
||||||
@@ -112,7 +114,6 @@ case "$( uname )" in #(
|
|||||||
NONSTOP* ) nonstop=true ;;
|
NONSTOP* ) nonstop=true ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
|
||||||
|
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM.
|
# Determine the Java command to use to start the JVM.
|
||||||
@@ -170,7 +171,6 @@ fi
|
|||||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
if "$cygwin" || "$msys" ; then
|
if "$cygwin" || "$msys" ; then
|
||||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
|
||||||
|
|
||||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||||
|
|
||||||
@@ -203,15 +203,14 @@ fi
|
|||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
# Collect all arguments for the java command:
|
# Collect all arguments for the java command:
|
||||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||||
# and any embedded shellness will be escaped.
|
# and any embedded shellness will be escaped.
|
||||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||||
# treated as '${Hostname}' itself on the command line.
|
# treated as '${Hostname}' itself on the command line.
|
||||||
|
|
||||||
set -- \
|
set -- \
|
||||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
-classpath "$CLASSPATH" \
|
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||||
org.gradle.wrapper.GradleWrapperMain \
|
|
||||||
"$@"
|
"$@"
|
||||||
|
|
||||||
# Stop when "xargs" is not available.
|
# Stop when "xargs" is not available.
|
||||||
|
|||||||
Vendored
+3
-2
@@ -13,6 +13,8 @@
|
|||||||
@rem See the License for the specific language governing permissions and
|
@rem See the License for the specific language governing permissions and
|
||||||
@rem limitations under the License.
|
@rem limitations under the License.
|
||||||
@rem
|
@rem
|
||||||
|
@rem SPDX-License-Identifier: Apache-2.0
|
||||||
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%"=="" @echo off
|
@if "%DEBUG%"=="" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@@ -68,11 +70,10 @@ goto fail
|
|||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
||||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
|
||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
@rem Execute Gradle
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
|||||||
+6
-9
@@ -1,16 +1,13 @@
|
|||||||
/*
|
|
||||||
* This file was generated by the Gradle 'init' task.
|
|
||||||
*
|
|
||||||
* The settings file is used to specify which projects to include in your build.
|
|
||||||
* For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.6/userguide/multi_project_builds.html in the Gradle documentation.
|
|
||||||
*/
|
|
||||||
|
|
||||||
rootProject.name = "version-plugin"
|
rootProject.name = "version-plugin"
|
||||||
|
|
||||||
dependencyResolutionManagement {
|
dependencyResolutionManagement {
|
||||||
|
repositories {
|
||||||
|
maven("https://nexus.keinekekse.net/repository/maven-public/")
|
||||||
|
}
|
||||||
|
|
||||||
versionCatalogs {
|
versionCatalogs {
|
||||||
create("libs") {
|
create("masterLibs") {
|
||||||
from(files("../../gradle-deps/libs.versions.toml"))
|
from("net.keinekekse:version-catalog:141")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,191 @@
|
|||||||
package net.keinekekse.version
|
package net.keinekekse.version
|
||||||
|
|
||||||
import org.gradle.api.tasks.Copy
|
import io.github.z4kn4fein.semver.Version
|
||||||
import org.gradle.api.tasks.TaskAction
|
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.*
|
||||||
|
|
||||||
abstract class AddVersionTask : Copy() {
|
@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
|
@TaskAction
|
||||||
fun updateVersion() {
|
fun execute() {
|
||||||
// action is defined in plugin
|
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,
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,129 +1,180 @@
|
|||||||
package net.keinekekse.version
|
package net.keinekekse.version
|
||||||
|
|
||||||
|
import org.gradle.api.InvalidUserDataException
|
||||||
import org.gradle.api.Plugin
|
import org.gradle.api.Plugin
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.file.RegularFile
|
import org.gradle.api.tasks.SourceSetContainer
|
||||||
import org.gradle.api.tasks.bundling.Jar
|
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||||
import org.gradle.api.tasks.bundling.War
|
|
||||||
import org.gradle.kotlin.dsl.extra
|
|
||||||
import org.gradle.kotlin.dsl.getValue
|
|
||||||
import org.gradle.kotlin.dsl.named
|
|
||||||
import java.io.FileInputStream
|
|
||||||
import java.io.FileOutputStream
|
|
||||||
import java.io.OutputStreamWriter
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Versions-Resource im Projekt anlegen und bei jedem Build eine Build-Nummer hochzählen
|
||||||
|
*
|
||||||
|
* Ohne weitere Konfiguration wird die Datei Version.kt mit der class VERSION im Verzeichnis
|
||||||
|
* src/main/kotlin/<project.group>/<project.name> erzeugt, für KMP in src/commonMain/kotlin.
|
||||||
|
* Die class wird mit Daten aus build.gradle.kts befüllt (s.u.).
|
||||||
|
*
|
||||||
|
* Für die Build-Nummer wird eine Datei buildnumber.properties im Projektverzeichnis erzeugt.
|
||||||
|
*
|
||||||
|
* Die class-Datei und der Package-Name können ggf. in build.gradle.kts konfiguriert werden:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* plugins {
|
||||||
|
* // Plugin einbinden
|
||||||
|
* id("net.keinekekse.version") version "3.0.0"
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Werte, die für die Version-Datei verwendet werden
|
||||||
|
* // in settings.gradle.kt: rootProject.name = "program-name"
|
||||||
|
* group = "org.example"
|
||||||
|
* version = "0.0.1-beta.1"
|
||||||
|
* description = "Program description"
|
||||||
|
* extra["displayname"] = "Program"
|
||||||
|
* extra["copyright"] = "Copyright (c) 2025 Hartmut Bauer"
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* // Optional: Konfiguration der Version-Datei und des Packages
|
||||||
|
* versionConfig {
|
||||||
|
* versionClassFile.set(layout.projectDirectory.file("src/main/kotlin/Version.kt"))
|
||||||
|
* versionPackageName.set("net.keinekekse")
|
||||||
|
*
|
||||||
|
* // Optional Versionen von Teilbereichen des Programms
|
||||||
|
* modules.set(
|
||||||
|
* mapOf(
|
||||||
|
* "books" to mapOf( // -> object VERSION_books
|
||||||
|
* "version" to libs.versions.books.get(),
|
||||||
|
* "displayName" to "Books-DB",
|
||||||
|
* "copyright" to "Copyright (c) 2026 Hartmut Bauer", // null => extra["copyright]
|
||||||
|
* "description" to "Books + Comics Database" // null => ""
|
||||||
|
* )
|
||||||
|
* )
|
||||||
|
* )
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* VERSION-class:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* import net.keinekekse.version.Version // -> util-Lib
|
||||||
|
*
|
||||||
|
* object VERSION: Version {
|
||||||
|
* override val version = "1.0.0-beta.1 // für Release-Ver: major.minor.patch
|
||||||
|
* override val fullVersion = "1.0.0-beta.1+build.13"
|
||||||
|
* override val major = 1
|
||||||
|
* override val minor = 0
|
||||||
|
* override val patch = 0
|
||||||
|
* override val preRelease = "beta.1"
|
||||||
|
* override val buildMetadata = "build.13"
|
||||||
|
* override val buildDate = "2026-01-10T18:54:42.227942Z"
|
||||||
|
* override val displayName = "Program"
|
||||||
|
* override val copyright = "Copyright (c) 2026 Hartmut Bauer"
|
||||||
|
* override val name = "program-name"
|
||||||
|
* override val description = "Program description"
|
||||||
|
* }
|
||||||
|
* object VERSION_books: Version {
|
||||||
|
* override val version = "0.1.0-alpha.1"
|
||||||
|
* override val fullVersion = "0.1.0-alpha.1+build.11"
|
||||||
|
* override val major = 0
|
||||||
|
* override val minor = 1
|
||||||
|
* override val patch = 0
|
||||||
|
* override val preRelease = "alpha.1"
|
||||||
|
* override val buildMetadata = "build.11"
|
||||||
|
* override val buildDate = "2026-09-19T00:18:40.584742Z"
|
||||||
|
* override val displayName = "Books-DB"
|
||||||
|
* override val copyright = "Copyright (c) 2026 Hartmut Bauer"
|
||||||
|
* override val name = "books"
|
||||||
|
* override val description = "Books + Comics Database"
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
class VersionPlugin : Plugin<Project> {
|
class VersionPlugin : Plugin<Project> {
|
||||||
private lateinit var versionFileName: String
|
|
||||||
private val buildNumProp = "buildNumber"
|
|
||||||
private val addTaskName = "addVersion"
|
|
||||||
private var isWar = false
|
|
||||||
|
|
||||||
override fun apply(project: Project) {
|
override fun apply(project: Project) {
|
||||||
// println("Version Plugin")
|
val extension =
|
||||||
val extension = project.extensions.create("version", VersionPluginExtension::class.java)
|
project.extensions.create("versionConfig", VersionPluginExtension::class.java)
|
||||||
versionFileName = extension.propertiesFilename.orNull ?: "${project.name}.properties"
|
|
||||||
|
|
||||||
val warSource =
|
val versionTask =
|
||||||
project.layout.projectDirectory.file("src/main/webapp/WEB-INF/classes/${versionFileName}")
|
project.tasks.register("incrementBuildNumber", AddVersionTask::class.java) {
|
||||||
val jarSource =
|
if (!extension.versionClassFile.isPresent) {
|
||||||
project.layout.projectDirectory.file("src/main/properties/${versionFileName}")
|
val packageName =
|
||||||
val targetDir = project.layout.buildDirectory.dir("resources/main")
|
project.group.toString().replace("-", ".") +
|
||||||
val countFile = project.layout.projectDirectory.file("buildnumber.properties")
|
"." + project.name.replace("-", ".")
|
||||||
if (warSource.asFile.parentFile.parentFile.exists()) {
|
val versionFileName = packageName.replace(".", "/") + "/Version.kt"
|
||||||
isWar = true
|
|
||||||
|
var targ = "src/main/kotlin/"
|
||||||
|
if (!project.layout.projectDirectory.file(targ).asFile.exists()) {
|
||||||
|
targ = "src/commonMain/kotlin/"
|
||||||
|
if (!project.layout.projectDirectory.file(targ).asFile.exists()) {
|
||||||
|
throw InvalidUserDataException(
|
||||||
|
"Version-Plugin: 'versionClassFile' and 'versionPackageName' must " +
|
||||||
|
"be set in a versionConfig-block in build.gradle.kts, " +
|
||||||
|
"as both 'src/main/kotlin' and 'src/commonMain/kotlin' do not exist!"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (isWar) {
|
}
|
||||||
if (!warSource.asFile.parentFile.exists())
|
extension.versionClassFile.convention(project.layout.projectDirectory.file(targ + versionFileName))
|
||||||
warSource.asFile.parentFile.mkdir()
|
extension.versionPackageName.convention(packageName)
|
||||||
checkVersionFile(warSource)
|
|
||||||
} else {
|
|
||||||
checkVersionFile(jarSource)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isWar) {
|
// Point to the source sets
|
||||||
try {
|
val files = project.files(
|
||||||
project.tasks.named<War>("war") {
|
"src/main/kotlin", "src/main/java",
|
||||||
filesMatching("**/${versionFileName}") {
|
"src/commonMain/kotlin", "src/commonMain/java",
|
||||||
val num = buildNumber(countFile)
|
"src/jvmMain/kotlin", "src/jvmMain/java"
|
||||||
project.extra[buildNumProp] = num
|
)
|
||||||
expand(project.properties)
|
// Filter lazily using a provider
|
||||||
}
|
sourceFiles.from(extension.versionClassFile.map { classFile ->
|
||||||
}
|
files.asFileTree.filter { it.name != classFile.asFile.name }
|
||||||
} catch (e: Exception) {
|
})
|
||||||
println("\n*** Falsche Reihenfolge ***\n\nWAR-Plugin muss vor dem Versions-Plugin eingetragen werden!\n")
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
project.tasks.named<Jar>("jar") {
|
|
||||||
dependsOn(project.tasks.named(addTaskName))
|
|
||||||
}
|
|
||||||
|
|
||||||
project.tasks.register(addTaskName, AddVersionTask::class.java) {
|
// Point to the properties file
|
||||||
group = "net.keinekekse"
|
buildNumberFile.set(project.layout.projectDirectory.file("buildnumber.properties"))
|
||||||
description = "Adds version information to the project."
|
|
||||||
outputs.upToDateWhen { false }
|
|
||||||
|
|
||||||
mustRunAfter(project.tasks.named("classes"))
|
// Link properties directly (this is lazy)
|
||||||
|
versionClassFile.set(extension.versionClassFile)
|
||||||
|
versionPackageName.set(extension.versionPackageName)
|
||||||
|
|
||||||
onlyIf {
|
projectVersion.set(project.provider { project.version.toString() })
|
||||||
val cj by project.tasks.named("compileJava")
|
projectName.set(project.provider { project.name })
|
||||||
val pr by project.tasks.named("processResources")
|
projectDescription.set(project.provider { project.description ?: "" })
|
||||||
// (cj.state.didWork || pr.didWork)
|
|
||||||
((cj.state.didWork && !cj.state.upToDate) || (pr.didWork && !pr.state.upToDate))
|
displayNameExtra.set(project.provider {
|
||||||
|
project.extensions.extraProperties.let {
|
||||||
|
if (it.has("displayname")) it.get("displayname")?.toString() else ""
|
||||||
}
|
}
|
||||||
|
})
|
||||||
from(jarSource)
|
copyrightExtra.set(project.provider {
|
||||||
into(targetDir)
|
project.extensions.extraProperties.let {
|
||||||
filesMatching("*") {
|
if (it.has("copyright")) it.get("copyright")?.toString() else ""
|
||||||
val num = buildNumber(countFile)
|
|
||||||
project.extra[buildNumProp] = num
|
|
||||||
expand(project.properties)
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
if (extension.modules.isPresent) {
|
||||||
|
modules.set(extension.modules)
|
||||||
|
extension.modules.get().forEach { (moduleName, moduleInfo) ->
|
||||||
|
// project.extensions.create("${moduleName}Version", VersionPluginExtension::class.java).apply {
|
||||||
|
// versionClassFile.set(project.layout.buildDirectory.file("generated/sources/version/${moduleName}/kotlin/${project.name}-version.kt"))
|
||||||
|
// modules.set(moduleInfo)
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// 1. Handle Kotlin/JVM (Standard Project)
|
||||||
* Increment build number
|
project.plugins.withId("org.jetbrains.kotlin.jvm") {
|
||||||
*/
|
project.extensions.getByType(SourceSetContainer::class.java).named("main") {
|
||||||
private fun buildNumber(propFile: RegularFile): String {
|
// This tells Gradle that this source set includes the directory containing the generated file
|
||||||
val propName = "build.number"
|
this.java.srcDir(versionTask.map { it.versionClassFile.get().asFile.parentFile })
|
||||||
val props = Properties()
|
|
||||||
|
|
||||||
try {
|
|
||||||
FileInputStream(propFile.asFile).use { props.load(it) }
|
|
||||||
} catch (e: Exception) {
|
|
||||||
// noop
|
|
||||||
}
|
}
|
||||||
val numStr: String? = props.getProperty(propName)
|
|
||||||
|
|
||||||
var num = numStr?.toLongOrNull() ?: 0
|
|
||||||
num++
|
|
||||||
println("build number ${num}")
|
|
||||||
|
|
||||||
props.setProperty(propName, num.toString())
|
|
||||||
props.store(FileOutputStream(propFile.asFile, false), "auto generated")
|
|
||||||
return num.toString()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// 2. Handle Kotlin Multiplatform
|
||||||
* Create version properties file if it doesn't exist
|
project.plugins.withId("org.jetbrains.kotlin.multiplatform") {
|
||||||
*/
|
val kotlinExt = project.extensions.getByType(KotlinMultiplatformExtension::class.java)
|
||||||
private fun checkVersionFile(file: RegularFile) {
|
kotlinExt.sourceSets.named("commonMain") {
|
||||||
if (!file.asFile.exists()) {
|
this.kotlin.srcDir(versionTask.map { it.versionClassFile.get().asFile.parentFile })
|
||||||
val content = """
|
|
||||||
|name=${'$'}{name}
|
|
||||||
|displayname=${'$'}{displayname}
|
|
||||||
|description=${'$'}{description}
|
|
||||||
|copyright=${'$'}{copyright}
|
|
||||||
|version=${'$'}{version}
|
|
||||||
|build.number=${'$'}{${buildNumProp}}
|
|
||||||
|build.timestamp=${'$'}{buildTimestamp}
|
|
||||||
""".trimMargin()
|
|
||||||
val outfile = OutputStreamWriter(FileOutputStream(file.asFile))
|
|
||||||
outfile.write(content)
|
|
||||||
outfile.close()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,13 @@
|
|||||||
package net.keinekekse.version
|
package net.keinekekse.version
|
||||||
|
|
||||||
|
import org.gradle.api.file.RegularFileProperty
|
||||||
|
import org.gradle.api.provider.MapProperty
|
||||||
import org.gradle.api.provider.Property
|
import org.gradle.api.provider.Property
|
||||||
|
|
||||||
interface VersionPluginExtension {
|
interface VersionPluginExtension {
|
||||||
|
val versionPackageName: Property<String>
|
||||||
|
|
||||||
/**
|
val versionClassFile: RegularFileProperty
|
||||||
* Name for the version properties file
|
|
||||||
* (JAR: src/main/properties, WAR: src/main/webapp/WEB-INF/classes)
|
val modules: MapProperty<String, Map<String, String>>
|
||||||
* Will be copied to the classpath root.
|
|
||||||
*
|
|
||||||
* Default: <project.name>.properties
|
|
||||||
*/
|
|
||||||
val propertiesFilename: Property<String>
|
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user