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

protokt.v1.gradle.BinaryInstaller.kt Maven / Gradle / Ivy

/*
 * Copyright (c) 2019 Toast, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package protokt.v1.gradle

import com.google.protobuf.gradle.GenerateProtoTask
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project
import org.gradle.api.artifacts.transform.InputArtifact
import org.gradle.api.artifacts.transform.TransformAction
import org.gradle.api.artifacts.transform.TransformOutputs
import org.gradle.api.artifacts.transform.TransformParameters
import org.gradle.api.artifacts.type.ArtifactTypeDefinition
import org.gradle.api.attributes.Attribute
import org.gradle.api.file.FileSystemLocation
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.PathSensitive
import org.gradle.api.tasks.PathSensitivity
import org.gradle.internal.file.PathTraversalChecker
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.registerTransform
import org.gradle.kotlin.dsl.withType
import org.gradle.work.DisableCachingByDefault
import java.io.BufferedInputStream
import java.io.File
import java.io.FileInputStream
import java.util.zip.ZipInputStream

private const val CODEGEN_CONFIGURATION = "_protokt_codegen_"
private val ARTIFACT_TYPE_ATTRIBUTE = Attribute.of("artifactType", String::class.java)
private val UNPACKED_CODEGEN_ATTRIBUTE = Attribute.of("unpackedCodegen", Boolean::class.javaObjectType)

/**
 * Unzip an application distribution and chmox +x the launchers.
 */
@DisableCachingByDefault(because = "Not worth caching")
abstract class UnzipDistTransform : TransformAction {
    @get:InputArtifact
    @get:PathSensitive(PathSensitivity.NAME_ONLY)
    abstract val zippedFile: Provider

    override fun transform(outputs: TransformOutputs) {
        val zippedFile = zippedFile.get().asFile
        val unzippedDirName = zippedFile.name.substringAfter('.')
        val unzipDir = outputs.dir(unzippedDirName)

        ZipInputStream(BufferedInputStream(FileInputStream(zippedFile))).use { inputStream ->
            generateSequence { inputStream.nextEntry }.filter { !it.isDirectory }.forEach {
                val file = File(unzipDir, PathTraversalChecker.safePathName(it.name))

                file.parentFile.mkdirs()

                file.outputStream().buffered().use {
                    inputStream.copyTo(it)
                }

                if (it.name.contains("/bin/")) {
                    file.setExecutable(true)
                }
            }
        }
    }
}

internal fun binaryFromArtifact(project: Project): String {
    val configuration = project.configurations.create(CODEGEN_CONFIGURATION) {
        attributes.attribute(UNPACKED_CODEGEN_ATTRIBUTE, true)
    }

    project.dependencies {
        attributesSchema {
            attribute(UNPACKED_CODEGEN_ATTRIBUTE)
        }

        artifactTypes.createIfNecessary("zip") {
            attributes.attribute(UNPACKED_CODEGEN_ATTRIBUTE, false)
        }

        registerTransform(UnzipDistTransform::class) {
            from.attribute(UNPACKED_CODEGEN_ATTRIBUTE, false).attribute(ARTIFACT_TYPE_ATTRIBUTE, "zip")
            to.attribute(UNPACKED_CODEGEN_ATTRIBUTE, true).attribute(ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.DIRECTORY_TYPE)
        }

        add(
            CODEGEN_CONFIGURATION,
            "com.toasttab.protokt:protokt-codegen:$PROTOKT_VERSION:dist@zip"
        )

        project.afterEvaluate {
            tasks.withType {
                inputs.files(project.configurations.getByName(CODEGEN_CONFIGURATION))
            }
        }
    }

    return configuration.singleFile.absolutePath + "/$CODEGEN_NAME-$PROTOKT_VERSION/bin/$CODEGEN_NAME"
}

private fun  NamedDomainObjectContainer.createIfNecessary(name: String, configure: T.() -> Unit) {
    (findByName(name) ?: create(name)).configure()
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy