diff --git a/build.gradle.kts b/build.gradle.kts index fa5824a..9423f1a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,27 +1,32 @@ 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 { `kotlin-dsl` `maven-publish` } repositories { - mavenCentral() + maven("https://nexus.keinekekse.net/repository/maven-public/") } group = "net.keinekekse" -version = libs.versions.versionplugin.get() +version = masterLibs.versions.versionPluginVersion.get() description = "Adds version information to the project." -project.ext.set("displayname", "Version-Plugin") -project.ext.set("copyright", "(c) 2024 Hartmut Bauer") -project.ext.set("buildTimestamp", Instant.now().toString()) +extra["displayname"] = "Version-Plugin" +extra["copyright"] = "Copyright (c) 2024-2025 Hartmut Bauer" +extra["buildTimestamp"] = Instant.now().toString() +publishing { + repositories { + maven { + credentials { + username = "admin" + password = "admin123" + } + url = uri("https://nexus.keinekekse.net/repository/maven-releases/") + } + } +} gradlePlugin { plugins { create("version-plugin") { @@ -33,6 +38,6 @@ gradlePlugin { java { toolchain { - languageVersion.set(JavaLanguageVersion.of(17)) + languageVersion.set(JavaLanguageVersion.of(masterLibs.versions.javaVersion.get())) } } diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..7fc6f1f --- /dev/null +++ b/gradle.properties @@ -0,0 +1 @@ +kotlin.code.style=official diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a80b22c..37f853b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/settings.gradle.kts b/settings.gradle.kts index 1cd56fb..7dee989 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -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" dependencyResolutionManagement { + repositories { + maven("https://nexus.keinekekse.net/repository/maven-public/") + } + versionCatalogs { - create("libs") { - from(files("../../gradle-deps/libs.versions.toml")) + create("masterLibs") { + from("net.keinekekse:version-catalog:56") } } } diff --git a/src/main/kotlin/net/keinekekse/version/VersionPlugin.kt b/src/main/kotlin/net/keinekekse/version/VersionPlugin.kt index ce2fcc8..eb2a264 100644 --- a/src/main/kotlin/net/keinekekse/version/VersionPlugin.kt +++ b/src/main/kotlin/net/keinekekse/version/VersionPlugin.kt @@ -3,127 +3,129 @@ package net.keinekekse.version import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.file.RegularFile +import org.gradle.api.java.archives.Manifest import org.gradle.api.tasks.bundling.Jar 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.time.Instant import java.util.* class VersionPlugin : Plugin { - private lateinit var versionFileName: String - private val buildNumProp = "buildNumber" - private val addTaskName = "addVersion" private var isWar = false + companion object { + private const val BUILDNUMBER_FILE = "buildnumber.properties" + private const val BUILD_NUMBER_KEY = "build.number" + private const val GENERATED_COMMENT = "auto generated" + } + override fun apply(project: Project) { -// println("Version Plugin") - val extension = project.extensions.create("version", VersionPluginExtension::class.java) - versionFileName = extension.propertiesFilename.orNull ?: "${project.name}.properties" + validateNoSubprojects(project) - val warSource = - project.layout.projectDirectory.file("src/main/webapp/WEB-INF/classes/${versionFileName}") - val jarSource = - project.layout.projectDirectory.file("src/main/properties/${versionFileName}") - val targetDir = project.layout.buildDirectory.dir("resources/main") - val countFile = project.layout.projectDirectory.file("buildnumber.properties") - if (warSource.asFile.parentFile.parentFile.exists()) { - isWar = true - } - if (isWar) { - if (!warSource.asFile.parentFile.exists()) - warSource.asFile.parentFile.mkdir() - checkVersionFile(warSource) - } else { - checkVersionFile(jarSource) - } + project.afterEvaluate { + val projectInfo = ProjectInfo( + version = project.version.toString(), + displayName = getOptionalExtra(project, "displayname"), + copyright = getOptionalExtra(project, "copyright"), + name = project.name, + description = project.description ?: "" + ) - if (isWar) { + isWar = isWarProject(project) + if (isWar) { + addManifestTask(project, "war", projectInfo) + } else { + addManifestTask(project, "jar", projectInfo) + } + } + } + + private fun validateNoSubprojects(project: Project) { + if (project.parent != null) { + throw Exception("This plugin cannot handle subprojects!") + } + } + + private fun isWarProject(project: Project): Boolean { + return project.layout.projectDirectory.file("src/main/webapp/WEB-INF").asFile.exists() + } + + private fun getOptionalExtra(project: Project, key: String): String { + return try { + project.extra[key]?.toString() ?: "" + } catch (e: Exception) { + "" + } + } + + private fun addManifestTask(project: Project, taskType: String, projectInfo: ProjectInfo) { + val countFile = project.layout.projectDirectory.file(BUILDNUMBER_FILE) + + if (taskType == "war") { try { - project.tasks.named("war") { - filesMatching("**/${versionFileName}") { - val num = buildNumber(countFile) - project.extra[buildNumProp] = num - expand(project.properties) + project.tasks.named(taskType) { + doFirst { + applyManifestAttributes(manifest, countFile, projectInfo) } } } catch (e: Exception) { - println("\n*** Falsche Reihenfolge ***\n\nWAR-Plugin muss vor dem Versions-Plugin eingetragen werden!\n") + println("\n*** Falsche Reihenfolge ***\n\nwar-Plugin muss vor dem Versions-Plugin eingetragen werden!\n") throw e } - } else { - project.tasks.named("jar") { - dependsOn(project.tasks.named(addTaskName)) - } - - project.tasks.register(addTaskName, AddVersionTask::class.java) { - group = "net.keinekekse" - description = "Adds version information to the project." - outputs.upToDateWhen { false } - - mustRunAfter(project.tasks.named("classes")) - - onlyIf { - val cj by project.tasks.named("compileJava") - val pr by project.tasks.named("processResources") -// (cj.state.didWork || pr.didWork) - ((cj.state.didWork && !cj.state.upToDate) || (pr.didWork && !pr.state.upToDate)) - } - - from(jarSource) - into(targetDir) - filesMatching("*") { - val num = buildNumber(countFile) - project.extra[buildNumProp] = num - expand(project.properties) + } else if (taskType == "jar") { + project.tasks.named(taskType) { + doFirst { + applyManifestAttributes(manifest, countFile, projectInfo) } } } } - /** - * Increment build number - */ - private fun buildNumber(propFile: RegularFile): String { - val propName = "build.number" - val props = Properties() + private fun applyManifestAttributes( + manifest: Manifest, + countFile: RegularFile, + projectInfo: ProjectInfo, + ) { + val buildNumber = incrementBuildNumber(countFile) + with(manifest.attributes) { + this["module-name"] = projectInfo.name + this["displayname"] = projectInfo.displayName + this["description"] = projectInfo.description + this["copyright"] = projectInfo.copyright + this["version"] = projectInfo.version + this["build-number"] = buildNumber + this["build-timestamp"] = Instant.now().toString() + } + + println("build ${projectInfo.version}-$buildNumber") + } + + private fun incrementBuildNumber(propFile: RegularFile): String { + 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}") + val currentBuildNumber = props.getProperty(BUILD_NUMBER_KEY)?.toLongOrNull() ?: 0 + val newBuildNumber = currentBuildNumber + 1 - props.setProperty(propName, num.toString()) - props.store(FileOutputStream(propFile.asFile, false), "auto generated") - return num.toString() + props.setProperty(BUILD_NUMBER_KEY, newBuildNumber.toString()) + props.store(FileOutputStream(propFile.asFile, false), GENERATED_COMMENT) + + return newBuildNumber.toString() } - /** - * Create version properties file if it doesn't exist - */ - private fun checkVersionFile(file: RegularFile) { - if (!file.asFile.exists()) { - 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() - } - } + data class ProjectInfo( + val version: String, + val displayName: String, + val copyright: String, + val name: String, + val description: String, + ) } diff --git a/src/main/kotlin/net/keinekekse/version/VersionPluginExtension.kt b/src/main/kotlin/net/keinekekse/version/VersionPluginExtension.kt index 693c06c..c517c3c 100644 --- a/src/main/kotlin/net/keinekekse/version/VersionPluginExtension.kt +++ b/src/main/kotlin/net/keinekekse/version/VersionPluginExtension.kt @@ -2,14 +2,4 @@ package net.keinekekse.version import org.gradle.api.provider.Property -interface VersionPluginExtension { - - /** - * Name for the version properties file - * (JAR: src/main/properties, WAR: src/main/webapp/WEB-INF/classes) - * Will be copied to the classpath root. - * - * Default: .properties - */ - val propertiesFilename: Property -} +interface VersionPluginExtension