/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * License: GNU Lesser General Public License (LGPL), version 2.1 or later
 * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
 */

apply from: rootProject.file( 'gradle/releasable.gradle' )
apply from: rootProject.file( 'gradle/java-module.gradle' )
apply from: rootProject.file( 'gradle/publishing-pom.gradle' )

apply plugin: 'signing'

// Make sure that the publishReleaseArtifacts task of the release module runs the release task of this sub module
tasks.getByPath( ':release:publishReleaseArtifacts' ).dependsOn tasks.release

configurations {
	javadocSources {
		description 'Used to aggregate javadocs for the whole project'
	}
}

dependencies {
	javadocSources sourceSets.main.allJava
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Publishing

publishing {
	publications {
		// main publication
		publishedArtifacts {
			// Add the Java component to the main publication
			from components.java
		}
	}
}

java {
	// include javadoc and sources jar in the Java component
	// 		- classes jar included by default
	withJavadocJar()
	withSourcesJar()
}

var signingKey = resolveSigningKey()
var signingPassword = findSigningProperty( "RELEASE_GPG_PASSPHRASE" )

signing {
	useInMemoryPgpKeys( signingKey, signingPassword )

	sign publishing.publications.publishedArtifacts
}

String resolveSigningKey() {
	var key = findSigningProperty( "RELEASE_GPG_PRIVATE_KEY" )
	if ( key != null ) {
		return key
	}

	var keyFile = findSigningProperty( "RELEASE_GPG_PRIVATE_KEY_PATH" )
	if ( keyFile != null ) {
		return new File( keyFile ).text
	}

	return null
}

String findSigningProperty(String propName) {
	def sysProp = System.getProperty(propName)
	if ( sysProp != null ) {
		logger.debug "Found `{}` as a system property", propName
		return sysProp
	}

	def envVar = System.getenv().get(propName)
	if ( envVar != null ) {
		logger.debug "Found `{}` as an env-var property", propName
		return envVar
	}

	def projectProp = project.hasProperty(propName)
	if (projectProp) {
		logger.debug "Found `{}` as a project property", propName
		return projectProp
	}

	logger.debug "Did not find `{}`", propName
	return null
}


var signingTask = project.tasks.getByName( "signPublishedArtifactsPublication" ) as Sign
var signingExtension = project.getExtensions().getByType(SigningExtension) as SigningExtension

task sign {
	dependsOn "signPublications"
}

task signPublications { t ->
	tasks.withType( Sign ).all { s ->
		t.dependsOn s
	}
}

signingTask.doFirst {
	if ( signingKey == null || signingPassword == null ) {
		throw new GradleException(
				"Cannot perform signing without GPG details.  Please set the `signingKey` and `signingKeyFile` properties"
		)
	}
}


boolean wasSigningExplicitlyRequested() {
	// check whether signing task was explicitly requested when running the build
	//
	// NOTE: due to https://discuss.gradle.org/t/how-to-tell-if-a-task-was-explicitly-asked-for-on-the-command-line/42853/3
	// we cannot definitively know whether the task was requested.  Gradle really just does not expose this information.
	// so we make a convention - we check the "start parameters" object to see which task-names were requested;
	// the problem is that these are the raw names directly from the command line.  e.g. it is perfectly legal to
	// say `gradlew signPubArtPub` in place of `gradlew signPublishedArtifactsPublication` - Gradle will simply
	// "expand" the name it finds.  However, it does not make that available.
	//
	// so the convention is that we will check for the following task names
	//
	// for each of:
	//		1. `sign`
	//		2. `signPublications`
	//		3. `signPublishedArtifactsPublication`
	//
	// and we check both forms:
	//		1. "${taskName}"
	//		2. project.path + ":${taskName}"
	//
	// we need to check both again because of the "start parameters" discussion

	def signingTaskNames = ["sign", "signPublications", "signPublishedArtifactsPublication"]

	for ( String taskName : signingTaskNames ) {
		if ( gradle.startParameter.taskNames.contains( taskName )
				|| gradle.startParameter.taskNames.contains( "${project.path}:${taskName}" ) ) {
			return true
		}
	}

	return false
}

if ( wasSigningExplicitlyRequested() ) {
	// signing was explicitly requested
	signingExtension.required = true
}
else {
	gradle.taskGraph.whenReady { graph ->
		if ( graph.hasTask( signingTask ) ) {
			// signing is scheduled to happen.
			//
			// we know, from above if-check, that it was not explicitly requested -
			// so it is triggered via task dependency. make sure we want it to happen
			var publishingTask = project.tasks.getByName( "publishPublishedArtifactsPublicationToSonatypeRepository" ) as PublishToMavenRepository
			if ( graph.hasTask( publishingTask ) ) {
				// we are publishing to Sonatype OSSRH - we need the signing to happen
				signingExtension.required = true
			}
			else {
				// signing was not explicitly requested and we are not publishing to OSSRH,
				// so do not sign.
				signingTask.enabled = false
			}
		}

	}
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Release / publishing tasks

task ciBuild {
	dependsOn test, tasks.publishToSonatype
}

tasks.release.dependsOn tasks.test, tasks.publishToSonatype

tasks.preVerifyRelease.dependsOn build
tasks.preVerifyRelease.dependsOn generateMetadataFileForPublishedArtifactsPublication
tasks.preVerifyRelease.dependsOn generatePomFileForPublishedArtifactsPublication

tasks.publishToSonatype.mustRunAfter test


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Ancillary tasks

task showPublications {
	doFirst {
		project.publishing.publications.each { publication ->
			println "Publication (${publication.name}): ${publication.groupId}:${publication.artifactId}:${publication.version}"
			publication.artifacts.each { artifact ->
				println "    > ${artifact}"
			}
		}
	}
}