1414 * limitations under the License.
1515 */
1616
17- import com.github.jengelman.gradle.plugins.shadow.ShadowExtension
17+ import com.github.jengelman.gradle.plugins.shadow.ShadowPlugin
1818import groovy.util.Node
1919import groovy.util.NodeList
20+ import javax.inject.Inject
2021import org.gradle.api.GradleException
2122import org.gradle.api.Plugin
2223import org.gradle.api.Project
2324import org.gradle.api.artifacts.Configuration
25+ import org.gradle.api.artifacts.ConfigurationVariant
26+ import org.gradle.api.artifacts.ProjectDependency
2427import org.gradle.api.artifacts.component.ModuleComponentSelector
2528import org.gradle.api.artifacts.result.DependencyResult
29+ import org.gradle.api.attributes.Bundling
30+ import org.gradle.api.attributes.Category
31+ import org.gradle.api.attributes.LibraryElements
32+ import org.gradle.api.attributes.Usage
33+ import org.gradle.api.component.SoftwareComponentFactory
34+ import org.gradle.api.plugins.JavaBasePlugin
2635import org.gradle.api.publish.PublishingExtension
2736import org.gradle.api.publish.maven.MavenPublication
2837import org.gradle.api.publish.tasks.GenerateModuleMetadata
@@ -37,7 +46,9 @@ import org.gradle.plugins.signing.SigningPlugin
3746
3847/* * Applies common configurations to all Nessie projects. */
3948@Suppress(" unused" )
40- class PublishingHelperPlugin : Plugin <Project > {
49+ class PublishingHelperPlugin
50+ @Inject
51+ constructor (private val softwareComponentFactory: SoftwareComponentFactory ) : Plugin <Project > {
4152 override fun apply (project : Project ): Unit =
4253 project.run {
4354 extensions.create(" publishingHelper" , PublishingHelperExtension ::class .java, this )
@@ -46,24 +57,22 @@ class PublishingHelperPlugin : Plugin<Project> {
4657 configure<PublishingExtension > {
4758 publications {
4859 register<MavenPublication >(" maven" ) {
49- val shadowExtension = project.extensions.findByType( ShadowExtension :: class .java)
50- if (shadowExtension != null ) {
51- shadowExtension.component( this )
52- project.afterEvaluate {
53- // Sonatype requires the javadoc and sources jar to be present, but the
54- // Shadow extension does not publish those.
55- artifact(tasks.named( " javadocJar " ))
56- artifact(tasks.named( " sourcesJar " ) )
60+ val mavenPublication = this
61+ afterEvaluate {
62+ // This MUST happen in an 'afterEvaluate' to ensure that the Shadow*Plugin has
63+ // been applied.
64+ if (project.plugins.hasPlugin( ShadowPlugin :: class .java)) {
65+ configureShadowPublishing(project, mavenPublication, softwareComponentFactory)
66+ } else {
67+ from(components.firstOrNull { c -> c.name == " javaPlatform " || c.name == " java " } )
5768 }
58- } else {
59- from(components.firstOrNull { c -> c.name == " javaPlatform" || c.name == " java" })
69+ suppressPomMetadataWarningsFor(" testApiElements" )
70+ suppressPomMetadataWarningsFor(" testJavadocElements" )
71+ suppressPomMetadataWarningsFor(" testRuntimeElements" )
72+ suppressPomMetadataWarningsFor(" testSourcesElements" )
73+ suppressPomMetadataWarningsFor(" testFixturesApiElements" )
74+ suppressPomMetadataWarningsFor(" testFixturesRuntimeElements" )
6075 }
61- suppressPomMetadataWarningsFor(" testApiElements" )
62- suppressPomMetadataWarningsFor(" testJavadocElements" )
63- suppressPomMetadataWarningsFor(" testRuntimeElements" )
64- suppressPomMetadataWarningsFor(" testSourcesElements" )
65- suppressPomMetadataWarningsFor(" testFixturesApiElements" )
66- suppressPomMetadataWarningsFor(" testFixturesRuntimeElements" )
6776
6877 groupId = " $group "
6978 version = project.version.toString()
@@ -260,3 +269,89 @@ class PublishingHelperPlugin : Plugin<Project> {
260269 return null
261270 }
262271}
272+
273+ internal fun configureShadowPublishing (
274+ project : Project ,
275+ mavenPublication : MavenPublication ,
276+ softwareComponentFactory : SoftwareComponentFactory ,
277+ ) =
278+ project.run {
279+ fun isPublishable (element : ConfigurationVariant ): Boolean {
280+ for (artifact in element.artifacts) {
281+ if (JavaBasePlugin .UNPUBLISHABLE_VARIANT_ARTIFACTS .contains(artifact.type)) {
282+ return false
283+ }
284+ }
285+ return true
286+ }
287+
288+ val shadowJar = project.tasks.named(" shadowJar" )
289+
290+ val shadowApiElements =
291+ project.configurations.create(" shadowApiElements" ) {
292+ isCanBeConsumed = true
293+ isCanBeResolved = false
294+ attributes {
295+ attribute(Usage .USAGE_ATTRIBUTE , project.objects.named(Usage ::class .java, Usage .JAVA_API ))
296+ attribute(
297+ Category .CATEGORY_ATTRIBUTE ,
298+ project.objects.named(Category ::class .java, Category .LIBRARY ),
299+ )
300+ attribute(
301+ LibraryElements .LIBRARY_ELEMENTS_ATTRIBUTE ,
302+ project.objects.named(LibraryElements ::class .java, LibraryElements .JAR ),
303+ )
304+ attribute(
305+ Bundling .BUNDLING_ATTRIBUTE ,
306+ project.objects.named(Bundling ::class .java, Bundling .SHADOWED ),
307+ )
308+ }
309+ outgoing.artifact(shadowJar)
310+ }
311+
312+ val component = softwareComponentFactory.adhoc(" shadow" )
313+ component.addVariantsFromConfiguration(shadowApiElements) {
314+ if (isPublishable(configurationVariant)) {
315+ mapToMavenScope(" compile" )
316+ } else {
317+ skip()
318+ }
319+ }
320+ // component.addVariantsFromConfiguration(configurations.getByName("runtimeElements")) {
321+ component.addVariantsFromConfiguration(
322+ project.configurations.getByName(" shadowRuntimeElements" )
323+ ) {
324+ if (isPublishable(configurationVariant)) {
325+ mapToMavenScope(" runtime" )
326+ } else {
327+ skip()
328+ }
329+ }
330+ // Sonatype requires the javadoc and sources jar to be present, but the
331+ // Shadow extension does not publish those.
332+ component.addVariantsFromConfiguration(project.configurations.getByName(" javadocElements" )) {}
333+ component.addVariantsFromConfiguration(project.configurations.getByName(" sourcesElements" )) {}
334+ mavenPublication.from(component)
335+
336+ // This a replacement to add dependencies to the pom, if necessary. Equivalent to
337+ // 'shadowExtension.component(mavenPublication)', which we cannot use.
338+
339+ mavenPublication.pom {
340+ withXml {
341+ val node = asNode()
342+ val depNode = node.get(" dependencies" )
343+ val dependenciesNode =
344+ if ((depNode as NodeList ).isNotEmpty()) depNode[0 ] as Node
345+ else node.appendNode(" dependencies" )
346+ project.configurations.getByName(" shadow" ).allDependencies.forEach {
347+ if (it is ProjectDependency ) {
348+ val dependencyNode = dependenciesNode.appendNode(" dependency" )
349+ dependencyNode.appendNode(" groupId" , it.group)
350+ dependencyNode.appendNode(" artifactId" , it.name)
351+ dependencyNode.appendNode(" version" , it.version)
352+ dependencyNode.appendNode(" scope" , " runtime" )
353+ }
354+ }
355+ }
356+ }
357+ }
0 commit comments