I have the following code in Groovy DSL. The idea is to save repositories configuration in variable and than use it later in several places. Could you please tell me how to do that in Kotlin?
val repos = closureOf<RepositoryHandler> {
mavenLocal()
maven(url = "...")
}
However, this won’t give you exactly what you want because the repositories method in Project takes a Closure<RepositoryHandler>, but the repositories method in Settings.pluginManagement takes an Action<RepositoryHandler>. In Groovy, a Closure works for both, but in Kotlin, the strong typing means you can’t pass in the exact same value as is. You’d have to do some conversion.
Don’t use a Closure in Kotlin code unless you are forced to, for example by some plugin that depends on getting a Closure as parameter.
But for Gradle built-in things this should not be the case.
Settings.pluginManagement.repositories takes an Action<? super RepositoryHandler>. Project.repositories takes a Closure, but ProjectExtensions.kt of the kotlin-dsl classes defines an exstension function Project.repositories that takes a RepositoryHandler.() -> Unit.
And RepositoryHandler.() -> Unit does work as Action<? super RepositoryHandler>.
So what you want is
val repos: RepositoryHandler.() -> Unit = {
mavenLocal()
maven("...")
}
But be aware that pluginManagement block is special and executed before the rest of the script, so that settings plugins for the same settings script are resolved from the repositories and with the rules defined in the pluginManagement block, so you can for example not do something like this as then repo is not found:
val repos: RepositoryHandler.() -> Unit = {
}
pluginManagement {
repositories(repos)
}
What you can do is for example
pluginManagement {
val repos: RepositoryHandler.() -> Unit = {
}
repositories(repos)
dependencyResolutionManagement.repositories(repos)
}
as the pluginManagement block is evaluated first separately, but can still configure the whole settings object, it is more like a beforeEvaluate with a different name and special methods additional that are only available inside.
Or you could do it like
pluginManagement {
var repos: RepositoryHandler.() -> Unit by extra
repos = {
}
repositories(repos)
}
dependencyResolutionManagement {
val repos: RepositoryHandler.() -> Unit by settings
repositories(repos)
}
One more questions please. Documentation says that it is possible execute several init scripts but it’s not quite clear whether is it possible to mix Groovy and Kotlin scripts? Say, if USER_HOME/.gradle/ contains both init.gradle and init.gradle.kts which one will be executed?
@Vampire, thank you a lot for you help! Could you please also advice whether is it possible to share variables between different init scripts, especially if they are written in different languages. Say, I have init.gradle and init.gradle.kts in init.d. Which one will be executed first? May I define variable or property in one script and use it in another?
The order is defined in the docs.
Iirc it is lexicographically within a folder.
If you want to share data between the init scripts you probably have to use the ext properties on the Gradle object.
You are not.
It does not declare it implements it in the code.
But like all instances that get decorated by Gradle through implicit instantiation, the extension awareness is added dynamically at runtime.
Well, could you please advice how to declare and consume variables in Gradle context. I define variable in Groovy script: ext { inhouseUrl = "..." }
than try to use in Kotlin one: val inhouseUrl: String by Gradle.extra
and got an error: Unresolved reference: extra