All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.parmet.buf.gradle.Workspace.kt Maven / Gradle / Ivy

There is a newer version: 0.8.5
Show newest version
package com.parmet.buf.gradle

import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.file.SourceDirectorySet
import org.gradle.api.tasks.SourceSetContainer
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.the
import java.io.File
import java.nio.file.Files
import java.nio.file.Path

const val CREATE_SYM_LINKS_TO_MODULES_TASK_NAME = "createSymLinksToModules"
const val WRITE_WORKSPACE_YAML_TASK_NAME = "writeWorkspaceYaml"

private const val EXTRACT_INCLUDE_PROTO_TASK_NAME = "extractIncludeProto"
private const val BUILD_EXTRACTED_INCLUDE_PROTOS_MAIN = "build/extracted-include-protos/main"

private const val EXTRACT_PROTO_TASK_NAME = "extractProto"
private const val BUILD_EXTRACTED_PROTOS_MAIN = "build/extracted-protos/main"

internal fun Project.configureCreateSymLinksToModules() {
    tasks.register(CREATE_SYM_LINKS_TO_MODULES_TASK_NAME) {
        workspaceCommonConfig()
        doLast { protoDirs().forEach { createSymLink(it) } }
    }
}

private fun Project.createSymLink(protoDir: Path) {
    val symLinkFile = File(bufbuildDir, mangle(protoDir))
    if (!symLinkFile.exists()) {
        logger.info("Creating symlink for $protoDir at $symLinkFile")
        Files.createSymbolicLink(symLinkFile.toPath(), Path.of(bufbuildDir).relativize(file(protoDir).toPath()))
    }
}

internal fun Project.configureWriteWorkspaceYaml() {
    tasks.register(WRITE_WORKSPACE_YAML_TASK_NAME) {
        workspaceCommonConfig()

        doLast {
            val bufWork =
                """
                    |version: v1
                    |directories:
                    ${workspaceSymLinkEntries()}
                """.trimMargin()

            logger.info("Writing generated buf.work.yaml:\n$bufWork")

            File("$bufbuildDir/buf.work.yaml").writeText(bufWork)
        }
    }
}

private fun Task.workspaceCommonConfig() {
    dependsOn(EXTRACT_INCLUDE_PROTO_TASK_NAME)
    dependsOn(EXTRACT_PROTO_TASK_NAME)
    outputs.dir(project.bufbuildDir)
    doLast { File(project.bufbuildDir).mkdirs() }
}

private fun Project.workspaceSymLinkEntries() =
    protoDirs().joinToString("\n") { "|  - ${mangle(it)}" }

private fun Project.protoDirs(): List =
    (srcDirs() + extractDirs()).filter { anyProtos(it) }

private fun Project.srcDirs() =
    the()["main"]
        .extensions
        .getByName("proto")
        .let { it as SourceDirectorySet }
        .srcDirs
        .map { projectDir.toPath().relativize(it.toPath()) }

private fun extractDirs() =
    listOf(
        BUILD_EXTRACTED_INCLUDE_PROTOS_MAIN,
        BUILD_EXTRACTED_PROTOS_MAIN
    ).map(Path::of)

private fun Project.anyProtos(path: Path) =
    file(path).walkTopDown().any { it.extension == "proto" }

private fun mangle(name: Path) =
    name.toString().replace("-", "--").replace(File.separator, "-")




© 2015 - 2025 Weber Informatics LLC | Privacy Policy