Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
package com.github.jengelman.gradle.plugins.shadow.util

import com.github.jengelman.gradle.plugins.shadow.testkit.gradleRunner
import java.nio.file.Path
import kotlin.io.path.appendText
import kotlin.io.path.bufferedWriter
import kotlin.io.path.copyTo
import kotlin.io.path.createDirectories
import kotlin.io.path.createDirectory
import kotlin.io.path.createFile
import kotlin.io.path.createParentDirectories
import kotlin.io.path.exists
import kotlin.io.path.invariantSeparatorsPathString
import kotlin.io.path.isRegularFile
import kotlin.io.path.name
import kotlin.io.path.writeText
import org.apache.maven.model.Dependency
import org.apache.maven.model.DependencyManagement
import org.apache.maven.model.Model
import org.apache.maven.model.io.xpp3.MavenXpp3Writer
import org.gradle.api.logging.Logging

class AppendableMavenRepository(val root: Path) {
Expand All @@ -21,9 +18,6 @@ class AppendableMavenRepository(val root: Path) {

init {
check(root.exists()) { "Maven repository root directory does not exist: $root" }

root.resolve("settings.gradle").createFile().writeText("rootProject.name = '${root.name}'\n")
root.resolve("build.gradle").createFile()
jarsDir = root.resolve("jars").createDirectory()
}

Expand All @@ -49,26 +43,48 @@ class AppendableMavenRepository(val root: Path) {
return bomModule.coordinate
}

private var publishCounter = 0

fun publish() {
check(modules.isNotEmpty()) { "No modules to publish. Please add at least one module." }
modules
.groupBy { it::class }
.forEach { (type, group) ->
@Suppress("UNCHECKED_CAST")
when (type) {
JarModule::class -> {
configureJarModules(group as List<JarModule>)
}
BomModule::class -> {
configureBomModules(group as List<BomModule>)
val writer = MavenXpp3Writer()

modules.forEach { module ->
val groupPath = module.groupId.replace('.', '/')
val versionDir =
root.resolve("$groupPath/${module.artifactId}/${module.version}").createDirectories()
val pomFile = versionDir.resolve("${module.artifactId}-${module.version}.pom")

val model =
Model().apply {
modelVersion = "4.0.0"
groupId = module.groupId
artifactId = module.artifactId
version = module.version
when (module) {
is JarModule -> {
dependencies = module.dependencies
}
is BomModule -> {
packaging = "pom"
dependencyManagement =
DependencyManagement().apply { dependencies = module.dependencies }
}
}
else -> error("Unsupported module type: $type")
}
}

gradleRunner(projectDir = root, arguments = listOf("publish", "--stacktrace")).build()
pomFile.bufferedWriter().use { writer.write(it, model) }

if (module is JarModule) {
val jar = module.existingJar ?: error("No jar file provided for ${module.coordinate}")
val targetJar = versionDir.resolve("${module.artifactId}-${module.version}.jar")
jar.copyTo(targetJar, overwrite = true)

module.existingSourcesJar?.let { sourcesJar ->
val targetSourcesJar =
versionDir.resolve("${module.artifactId}-${module.version}-sources.jar")
sourcesJar.copyTo(targetSourcesJar, overwrite = true)
}
}
}

logger.info(
"""
Expand All @@ -80,104 +96,9 @@ class AppendableMavenRepository(val root: Path) {
modules.clear()
}

private fun configureJarModules(jarModules: List<JarModule>) {
val mavenPublications =
jarModules.joinToString("\n") { module ->
var index = -1
val nodes =
module.dependencies.joinToString("\n") {
index++
val node = "dependencyNode$index"
"""
|def $node = dependenciesNode.appendNode('dependency')
|$node.appendNode('groupId', '${it.groupId}')
|$node.appendNode('artifactId', '${it.artifactId}')
|$node.appendNode('version', '${it.version}')
|$node.appendNode('scope', '${it.scope}')
"""
.trimMargin()
}
module.createMavenPublication(
"""
|artifact '${module.artifactPath}'
|pom.withXml { xml ->
| def dependenciesNode = xml.asNode().get('dependencies') ?: xml.asNode().appendNode('dependencies')
| $nodes
|}
"""
.trimMargin()
)
}
val scriptContent =
"""
|plugins {
| id 'maven-publish'
|}
|publishing {
| publications {
| $mavenPublications
| }
| repositories {
| maven { url = '${root.toUri()}' }
| }
|}
"""
.trimMargin()
val jarsModule = "jars-module-${publishCounter++}"
root.resolve("settings.gradle").appendText("include '$jarsModule'\n")
root.resolve("$jarsModule/build.gradle").createFileIfNotExists().writeText(scriptContent)
}

private fun configureBomModules(bomModules: List<BomModule>) {
// BOM modules are published one by one.
bomModules.forEach { module ->
val scriptContent =
"""
|plugins {
| id 'maven-publish'
| id 'java-platform'
|}
|dependencies {
| constraints {
| ${module.dependencies.joinToString("\n") { "api '${it.coordinate}'" }}
| }
|}
|publishing {
| publications {
| ${module.createMavenPublication("from components.javaPlatform")}
| }
| repositories {
| maven { url = '${root.toUri()}' }
| }
|}
"""
.trimMargin()
val pomModule = "pom-module-${publishCounter++}"
root.resolve("settings.gradle").appendText("include '$pomModule'\n")
root.resolve("$pomModule/build.gradle").createFileIfNotExists().writeText(scriptContent)
}
}

private fun Module.createMavenPublication(block: String): String {
return """
|create('${coordinate.replace(":", "")}', MavenPublication) {
| artifactId = '$artifactId'
| groupId = '$groupId'
| version = '$version'
| $block
|}
"""
.trimMargin()
}

sealed class Module(groupId: String, artifactId: String, version: String) : Model() {
sealed class Module(val groupId: String, val artifactId: String, val version: String) {
val coordinate = "$groupId:$artifactId:$version"

init {
this.groupId = groupId
this.artifactId = artifactId
this.version = version
}
val dependencies = mutableListOf<Dependency>()

fun addDependency(coordinate: String, scope: String = "runtime") {
val (groupId, artifactId, version) =
Expand All @@ -192,23 +113,17 @@ class AppendableMavenRepository(val root: Path) {
it.version = version
it.scope = scope
}
addDependency(dependency)
dependencies += dependency
}
}

inner class JarModule(groupId: String, artifactId: String, version: String) :
Module(groupId, artifactId, version) {
private var existingJar: Path? = null

val artifactPath: String
get() =
existingJar
?.also {
check(it.exists() && it.isRegularFile()) {
"Jar file does not exist or is not a regular file: $it"
}
}
?.invariantSeparatorsPathString ?: error("No jar file provided for $coordinate")
var existingJar: Path? = null
private set

var existingSourcesJar: Path? = null
private set

fun useJar(existingJar: Path) {
this.existingJar = existingJar
Expand All @@ -218,25 +133,18 @@ class AppendableMavenRepository(val root: Path) {
val jarPath = jarsDir.resolve("${coordinate.replace(':', '-')}.jar")
existingJar = JarBuilder(jarPath).apply(builder).write()
}
}

class BomModule(groupId: String, artifactId: String, version: String) :
Module(groupId, artifactId, version) {
init {
packaging = "pom"
fun buildSourcesJar(builder: JarBuilder.() -> Unit) {
val jarPath = jarsDir.resolve("${coordinate.replace(':', '-')}-sources.jar")
existingSourcesJar = JarBuilder(jarPath).apply(builder).write()
}
}

class BomModule(groupId: String, artifactId: String, version: String) :
Module(groupId, artifactId, version)
}

private val logger = Logging.getLogger(AppendableMavenRepository::class.java)

val Dependency.coordinate: String
get() = "$groupId:$artifactId:$version"

private fun Path.createFileIfNotExists(): Path {
if (!exists()) {
createParentDirectories()
createFile()
}
return this
}