Last active
January 30, 2025 15:14
-
-
Save aSemy/c6b4acdd0667e559c34d3d495ce1a923 to your computer and use it in GitHub Desktop.
Gradle environment variable container
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.gradle.api.Named | |
import org.gradle.api.NamedDomainObjectContainer | |
import org.gradle.api.SupportsKotlinAssignmentOverloading | |
import org.gradle.api.model.ObjectFactory | |
import org.gradle.api.plugins.ExtensionAware | |
import org.gradle.api.provider.Property | |
import org.gradle.api.provider.Provider | |
import org.gradle.api.tasks.Input | |
import org.gradle.api.tasks.Internal | |
import org.gradle.api.tasks.Nested | |
import org.gradle.api.tasks.Optional | |
import javax.inject.Inject | |
/** | |
* Key-value store of environment variables. | |
*/ | |
// workaround for Gradle's confusing behaviour with MapProperty | |
// https://github.com/gradle/gradle/issues/12222 | |
// https://github.com/gradle/gradle/issues/13364 | |
// https://github.com/gradle/gradle/issues/32160 | |
// https://github.com/gradle/gradle/issues/32152 | |
// https://github.com/gradle/gradle/issues/32149 | |
// https://github.com/gradle/gradle/issues/18352 | |
// https://github.com/gradle/gradle/issues/17090 | |
// https://github.com/gradle/gradle/issues/12222 | |
internal abstract class EnvVarContainer @Inject constructor( | |
private val objects: ObjectFactory, | |
) : ExtensionAware { | |
/** | |
* Container for all environment variable key-values. | |
* | |
* The visibility must be 'protected' not 'private', otherwise Gradle can't see the nested values. | |
*/ | |
@get:Nested | |
protected val content: NamedDomainObjectContainer<Entry> = | |
objects.domainObjectContainer(Entry::class.java, { name -> | |
val entry = Entry( | |
key = name, | |
value = objects.property(String::class.java) | |
) | |
[email protected](name, entry) | |
entry | |
}) | |
fun set(key: String, value: String) { | |
content.maybeCreate(key).value.set(value) | |
} | |
fun set(key: String, value: Provider<String>) { | |
content.maybeCreate(key).value.set(value) | |
} | |
fun convention(key: String, value: String) { | |
content.maybeCreate(key).value.convention(value) | |
} | |
fun convention(key: String, value: Provider<String>) { | |
content.maybeCreate(key).value.convention(value) | |
} | |
/** | |
* Add all values from [other] into this container. | |
* | |
* The values from [other] will be [set][Property.set], | |
* overriding any [convention][Property.convention] values. | |
*/ | |
fun setAll(other: EnvVarContainer) { | |
other.content.all { entry -> | |
set(entry.key, entry.value) | |
} | |
} | |
/** | |
* Add all values from [other] into this container. | |
* | |
* The values from [other] will be [conventions][Property.convention], | |
* meaning any [set][Property.set] values will take precedence. | |
*/ | |
fun addConventions(other: EnvVarContainer) { | |
other.content.all { entry -> | |
convention(entry.key, entry.value) | |
} | |
} | |
/** | |
* Compute and return all values. | |
* This should only be done during Gradle's execution phase, when all values can be safely computed. | |
*/ | |
fun compute(): Map<String, String?> = | |
content.associate { it.key to it.value.orNull } | |
/** | |
* A single key-value entry in [EnvVarContainer]. | |
*/ | |
@SupportsKotlinAssignmentOverloading | |
class Entry internal constructor( | |
@get:Input | |
val key: String, | |
@get:Input | |
@get:Optional | |
val value: Property<String>, | |
) : Named { | |
@Suppress("unused") // IJ doesn't correctly detect assignment overloading usages | |
fun assign(value: String): Unit = this.value.set(value) | |
@Suppress("unused") // IJ doesn't correctly detect assignment overloading usages | |
fun assign(value: Provider<String>): Unit = this.value.set(value) | |
@Internal | |
override fun getName(): String = key | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment