aboutsummaryrefslogtreecommitdiff
path: root/buildSrc/src/main/kotlin
diff options
context:
space:
mode:
Diffstat (limited to 'buildSrc/src/main/kotlin')
-rw-r--r--buildSrc/src/main/kotlin/org/jetbrains/CrossPlatformExec.kt63
-rw-r--r--buildSrc/src/main/kotlin/org/jetbrains/DokkaVersion.kt26
-rw-r--r--buildSrc/src/main/kotlin/org/jetbrains/SetupMaven.kt48
-rw-r--r--buildSrc/src/main/kotlin/org/jetbrains/ValidatePublications.kt79
-rw-r--r--buildSrc/src/main/kotlin/org/jetbrains/projectUtils.kt16
-rw-r--r--buildSrc/src/main/kotlin/org/jetbrains/publication.kt61
-rw-r--r--buildSrc/src/main/kotlin/org/jetbrains/taskUtils.kt13
7 files changed, 306 insertions, 0 deletions
diff --git a/buildSrc/src/main/kotlin/org/jetbrains/CrossPlatformExec.kt b/buildSrc/src/main/kotlin/org/jetbrains/CrossPlatformExec.kt
new file mode 100644
index 00000000..e02bdd61
--- /dev/null
+++ b/buildSrc/src/main/kotlin/org/jetbrains/CrossPlatformExec.kt
@@ -0,0 +1,63 @@
+package org.jetbrains
+
+import org.gradle.api.tasks.AbstractExecTask
+import org.gradle.internal.os.OperatingSystem
+import java.io.File
+import java.nio.file.Files
+import java.nio.file.Path
+import java.nio.file.Paths
+
+open class CrossPlatformExec : AbstractExecTask<CrossPlatformExec>(CrossPlatformExec::class.java) {
+ private val windowsExtensions = listOf(".bat", ".cmd", ".exe")
+ private val unixExtensions = listOf("", ".sh")
+
+ private val isWindows = OperatingSystem.current().isWindows
+
+ override fun exec() {
+ val commandLine: MutableList<String> = this.commandLine
+
+ if (commandLine.isNotEmpty()) {
+ commandLine[0] = findCommand(commandLine[0])
+ }
+
+ if (isWindows && commandLine.isNotEmpty() && commandLine[0].isNotBlank()) {
+ this.commandLine = listOf("cmd", "/c") + commandLine
+ } else {
+ this.commandLine = commandLine
+ }
+
+ super.exec()
+ }
+
+ private fun findCommand(command: String): String {
+ val command = normalizeCommandPaths(command)
+ val extensions = if (isWindows) windowsExtensions else unixExtensions
+
+ return extensions.map { extension ->
+ resolveCommandFromFile(Paths.get("$command$extension"))
+ }.firstOrNull { it.isNotBlank() } ?: command
+ }
+
+ private fun resolveCommandFromFile(commandFile: Path) =
+ if (!Files.isExecutable(commandFile)) {
+ ""
+ } else {
+ commandFile.toAbsolutePath().normalize().toString()
+ }
+
+
+ private fun normalizeCommandPaths(command: String): String {
+ // need to escape backslash so it works with regex
+ val backslashSeparator = "\\"
+ val forwardSlashSeparator = "/"
+
+ // get the actual separator
+ val separator = if (File.separatorChar == '\\') backslashSeparator else File.separator
+
+ return command
+ // first replace all of the backslashes with forward slashes
+ .replace(backslashSeparator, forwardSlashSeparator)
+ // then replace all forward slashes with whatever the separator actually is
+ .replace(forwardSlashSeparator, separator)
+ }
+} \ No newline at end of file
diff --git a/buildSrc/src/main/kotlin/org/jetbrains/DokkaVersion.kt b/buildSrc/src/main/kotlin/org/jetbrains/DokkaVersion.kt
new file mode 100644
index 00000000..2a5c21a7
--- /dev/null
+++ b/buildSrc/src/main/kotlin/org/jetbrains/DokkaVersion.kt
@@ -0,0 +1,26 @@
+package org.jetbrains
+
+import org.gradle.api.Project
+import org.gradle.kotlin.dsl.extra
+import org.gradle.kotlin.dsl.provideDelegate
+
+fun Project.configureDokkaVersion(): String {
+ var dokka_version: String? by this.extra
+ if (dokka_version == null) {
+ val dokka_version_base: String by this
+ dokka_version = dokkaVersionFromBase(dokka_version_base)
+ }
+ return checkNotNull(dokka_version)
+}
+
+private fun dokkaVersionFromBase(baseVersion: String): String {
+ val buildNumber = System.getenv("BUILD_NUMBER")
+ val forceSnapshot = System.getenv("FORCE_SNAPSHOT") != null
+ if (forceSnapshot || buildNumber == null) {
+ return "$baseVersion-SNAPSHOT"
+ }
+ return "$baseVersion-$buildNumber"
+}
+
+val Project.dokkaVersion: String
+ get() = configureDokkaVersion()
diff --git a/buildSrc/src/main/kotlin/org/jetbrains/SetupMaven.kt b/buildSrc/src/main/kotlin/org/jetbrains/SetupMaven.kt
new file mode 100644
index 00000000..4ef26a73
--- /dev/null
+++ b/buildSrc/src/main/kotlin/org/jetbrains/SetupMaven.kt
@@ -0,0 +1,48 @@
+package org.jetbrains
+
+import org.gradle.api.artifacts.Configuration
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.Internal
+import org.gradle.api.tasks.Sync
+import org.gradle.kotlin.dsl.creating
+import org.gradle.kotlin.dsl.dependencies
+import org.gradle.kotlin.dsl.getValue
+import java.io.File
+
+@Suppress("LeakingThis")
+open class SetupMaven : Sync() {
+ @get:Input
+ var mavenVersion = "3.5.0"
+
+ @get:Input
+ var mavenPluginToolsVersion = "3.5.2"
+
+ @get:Input
+ var aetherVersion = "1.1.0"
+
+ @get:Internal
+ val mavenBuildDir = "${project.buildDir}/maven"
+
+ @get:Internal
+ val mavenBinDir = "${project.buildDir}/maven-bin"
+
+ @get:Internal
+ val mvn = File(mavenBinDir, "apache-maven-$mavenVersion/bin/mvn")
+
+ private val mavenBinaryConfiguration: Configuration by project.configurations.creating {
+ project.dependencies {
+ this@creating.invoke(
+ group = "org.apache.maven",
+ name = "apache-maven",
+ version = mavenVersion,
+ classifier = "bin", ext = "zip"
+ )
+ }
+ }
+
+ init {
+ from(mavenBinaryConfiguration.map { file -> project.zipTree(file) })
+ into(mavenBinDir)
+ }
+
+}
diff --git a/buildSrc/src/main/kotlin/org/jetbrains/ValidatePublications.kt b/buildSrc/src/main/kotlin/org/jetbrains/ValidatePublications.kt
new file mode 100644
index 00000000..84c48b96
--- /dev/null
+++ b/buildSrc/src/main/kotlin/org/jetbrains/ValidatePublications.kt
@@ -0,0 +1,79 @@
+package org.jetbrains
+
+import com.jfrog.bintray.gradle.BintrayExtension
+import org.gradle.api.DefaultTask
+import org.gradle.api.GradleException
+import org.gradle.api.Project
+import org.gradle.api.artifacts.ProjectDependency
+import org.gradle.api.publish.PublishingExtension
+import org.gradle.api.publish.maven.MavenPublication
+import org.gradle.api.tasks.TaskAction
+import org.gradle.kotlin.dsl.findByType
+import org.gradle.kotlin.dsl.provideDelegate
+
+open class ValidatePublications : DefaultTask() {
+ class MissingBintrayPublicationException(project: Project, publication: MavenPublication) : GradleException(
+ "Project ${project.path} has publication ${publication.name} that is not configured for bintray publication"
+ )
+
+ class UnpublishedProjectDependencyException(
+ project: Project, dependencyProject: Project
+ ) : GradleException(
+ "Published project ${project.path} cannot depend on unpublished projed ${dependencyProject.path}"
+ )
+
+
+ @TaskAction
+ fun validatePublicationConfiguration() {
+ @Suppress("LocalVariableName")
+ project.subprojects.forEach { subProject ->
+ val publishing = subProject.extensions.findByType<PublishingExtension>() ?: return@forEach
+ publishing.publications
+ .filterIsInstance<MavenPublication>()
+ .filter { it.version == project.dokkaVersion }
+ .forEach { publication ->
+ checkPublicationIsConfiguredForBintray(subProject, publication)
+ checkProjectDependenciesArePublished(subProject)
+ }
+ }
+ }
+
+ private fun checkPublicationIsConfiguredForBintray(project: Project, publication: MavenPublication) {
+ val bintrayExtension = project.extensions.findByType<BintrayExtension>()
+ ?: throw MissingBintrayPublicationException(project, publication)
+
+ val isPublicationConfiguredForBintray = bintrayExtension.publications.orEmpty()
+ .any { publicationName -> publicationName == publication.name }
+
+ if (!isPublicationConfiguredForBintray) {
+ throw MissingBintrayPublicationException(project, publication)
+ }
+ }
+
+ private fun checkProjectDependenciesArePublished(project: Project) {
+ (project.configurations.findByName("implementation")?.allDependencies.orEmpty() +
+ project.configurations.findByName("api")?.allDependencies.orEmpty())
+ .filterIsInstance<ProjectDependency>()
+ .forEach { projectDependency ->
+ val publishing = projectDependency.dependencyProject.extensions.findByType<PublishingExtension>()
+ ?: throw UnpublishedProjectDependencyException(
+ project = project, dependencyProject = projectDependency.dependencyProject
+ )
+
+ val isPublished = publishing.publications.filterIsInstance<MavenPublication>()
+ .filter { it.version == project.dokkaVersion }
+ .any()
+
+ if (!isPublished) {
+ throw UnpublishedProjectDependencyException(project, projectDependency.dependencyProject)
+ }
+ }
+ }
+
+ init {
+ group = "verification"
+ project.tasks.named("check") {
+ dependsOn(this@ValidatePublications)
+ }
+ }
+}
diff --git a/buildSrc/src/main/kotlin/org/jetbrains/projectUtils.kt b/buildSrc/src/main/kotlin/org/jetbrains/projectUtils.kt
new file mode 100644
index 00000000..46d803a5
--- /dev/null
+++ b/buildSrc/src/main/kotlin/org/jetbrains/projectUtils.kt
@@ -0,0 +1,16 @@
+package org.jetbrains
+
+import org.gradle.api.Project
+
+fun Project.whenEvaluated(action: Project.() -> Unit) {
+ if (state.executed) {
+ action()
+ } else {
+ afterEvaluate { action() }
+ }
+}
+
+fun Project.invokeWhenEvaluated(action: (project: Project) -> Unit) {
+ whenEvaluated { action(this) }
+}
+
diff --git a/buildSrc/src/main/kotlin/org/jetbrains/publication.kt b/buildSrc/src/main/kotlin/org/jetbrains/publication.kt
new file mode 100644
index 00000000..289bd117
--- /dev/null
+++ b/buildSrc/src/main/kotlin/org/jetbrains/publication.kt
@@ -0,0 +1,61 @@
+package org.jetbrains
+
+import com.github.jengelman.gradle.plugins.shadow.ShadowExtension
+import com.jfrog.bintray.gradle.BintrayExtension
+import org.gradle.api.Project
+import org.gradle.api.publish.PublishingExtension
+import org.gradle.api.publish.maven.MavenPublication
+import org.gradle.kotlin.dsl.*
+
+class DokkaPublicationBuilder {
+ enum class Component {
+ Java, Shadow
+ }
+
+ var artifactId: String? = null
+ var component: Component = Component.Java
+}
+
+fun Project.registerDokkaArtifactPublication(publicationName: String, configure: DokkaPublicationBuilder.() -> Unit) {
+ configure<PublishingExtension> {
+ publications {
+ register<MavenPublication>(publicationName) {
+ val builder = DokkaPublicationBuilder().apply(configure)
+ this.artifactId = builder.artifactId
+ when (builder.component) {
+ DokkaPublicationBuilder.Component.Java -> from(components["java"])
+ DokkaPublicationBuilder.Component.Shadow -> run {
+ artifact(tasks["sourcesJar"])
+ extensions.getByType(ShadowExtension::class.java).component(this)
+ }
+ }
+ }
+ }
+ }
+
+ configureBintrayPublication(publicationName)
+}
+
+fun Project.configureBintrayPublication(vararg publications: String) {
+ val dokka_version: String by this
+ val dokka_publication_channel: String by this
+ extensions.configure<BintrayExtension>("bintray") {
+ user = System.getenv("BINTRAY_USER")
+ key = System.getenv("BINTRAY_KEY")
+ dryRun = System.getenv("BINTRAY_DRY_RUN") == "true" ||
+ project.properties["bintray_dry_run"] == "true"
+ pkg = PackageConfig().apply {
+ repo = dokka_publication_channel
+ name = "dokka"
+ userOrg = "kotlin"
+ desc = "Dokka, the Kotlin documentation tool"
+ vcsUrl = "https://github.com/kotlin/dokka.git"
+ setLicenses("Apache-2.0")
+ version = VersionConfig().apply {
+ name = dokka_version
+ }
+ }
+ setPublications(*publications)
+ }
+}
+
diff --git a/buildSrc/src/main/kotlin/org/jetbrains/taskUtils.kt b/buildSrc/src/main/kotlin/org/jetbrains/taskUtils.kt
new file mode 100644
index 00000000..ef9c5e6a
--- /dev/null
+++ b/buildSrc/src/main/kotlin/org/jetbrains/taskUtils.kt
@@ -0,0 +1,13 @@
+package org.jetbrains
+
+import org.gradle.api.Task
+
+fun Task.dependsOnMavenLocalPublication() {
+ project.rootProject.allprojects.forEach { otherProject ->
+ otherProject.invokeWhenEvaluated { evaluatedProject ->
+ evaluatedProject.tasks.findByName("publishToMavenLocal")?.let { publishingTask ->
+ this.dependsOn(publishingTask)
+ }
+ }
+ }
+}