Slackbot
05/16/2022, 2:34 PMCristianGM
05/16/2022, 2:44 PMephemient
05/16/2022, 2:45 PMfeatureEnabled
2. Make configFile
a property. The Kotlin DSL syntax will have to change to configFile.set("...")
but this will allow you to configure task inputs before the extension is configuredCristianGM
05/16/2022, 2:47 PMMartin
05/16/2022, 2:52 PMmyPlugin {
enableFeature(featureEnabled: Boolean, configFile: File)
}
CristianGM
05/16/2022, 2:54 PMephemient
05/16/2022, 2:54 PMMartin
05/16/2022, 2:55 PMephemient
05/16/2022, 2:55 PMChris Lee
05/16/2022, 2:59 PMJavi
05/16/2022, 3:01 PMephemient
05/16/2022, 3:04 PMNicola Corti
05/16/2022, 3:10 PMconfigFile
, that's already a Property, I used the Groovy dsl in the example for simplicity.
The problem is that the configFile is a YAML file in my case, that contains paths which I'd like to use as @InputFile
/`@InputFiles` for some of my tasks.
I could set configFile
itself as @InputFile
for the task, but I haven't found an elegant way to parse the content of the provided file + pass the user provided paths as @InputFile
for the task I'm creating.ephemient
05/16/2022, 3:22 PMephemient
05/16/2022, 3:25 PMCristianGM
05/16/2022, 3:34 PMNicola Corti
05/17/2022, 2:25 PMyou could create yet another task that reads the config file, outputs the collection of files it references, and is untracked; then use that as the other tasks' input filesThanks for the hint @ephemient. I'm still trying to find a way to make it work correctly. Not sure how the first task should outputs the collection of files it references. The problem is that this list of file will be known only at execution time and won't be accounted for the UP-TO-DATE checks of the second task
ephemient
05/17/2022, 2:30 PMephemient
05/17/2022, 2:31 PMNicola Corti
05/17/2022, 2:53 PMand copy the referenced files to itBut then I'll end up copying over and over the files for every build no?
ephemient
05/17/2022, 2:54 PMNicola Corti
05/17/2022, 3:06 PMproject.afterEvaluate
is probably better?ephemient
05/17/2022, 3:07 PMChris Lee
05/17/2022, 3:08 PMChris Lee
05/17/2022, 3:23 PM// extension class
abstract class ProjectsExtension @Inject constructor(private val objectFactory: ObjectFactory) {
@get:Input
abstract val buildFiles: DomainObjectSet<File>
}
// plugin code
val projectsExt = extensions.create("projects", ProjectsExtension::class)
projectsExt.buildFiles.whenObjectAdded {
// do magic here
}
ephemient
05/17/2022, 3:30 PMFile
anyway) but whenObjectAdded
is not lazy (like all
)Chris Lee
05/17/2022, 3:33 PMNicola Corti
05/17/2022, 4:17 PMDomainObjectSet
to do this).
The annoying part here is that:
1. My configFile
is actually a RegularFileProperty
. Changing it to a DomainObjectSet<File>
would be a breaking change
2. I don't have multiple files, but just one. So modelling it with a DomainObjectSet
would not reflect reality. I.e. would give the false sense to the user that they can provide multiple configFile
which in reality they can'tChris Lee
05/17/2022, 4:23 PMJendrik Johannes
05/17/2022, 5:32 PMproject.providers.fileContents(configFile).asText.get()
(like I did here). Then when you use configuration cache, the file will be tracked as âinput to configurationâ and only parsed again if something changed.
Then you can do all of the lazily and you do not need to worry about order. Something like this:
tasks.register<MyType>("myTaks") {
someInputFile.set(myPluginExtension.configFile.map {
parsePathFromFile(it)
})
}
fun parsePathFromFile(it: Provider<RegularFile>) =
project.layout.projectDirectory.file(
providers.fileContents(it.get()).asText.get().substring(0, 10)) // Instead of 'substring' do the real parsing
Jendrik Johannes
05/17/2022, 5:35 PMproviders
API.Chris Lee
05/17/2022, 5:36 PMget()
is called - assuming that itâ only called once, youâd be good, but have the risk of multiple executions. Have added a memoize capability to providers for expensive operations (parsing, API calls) to enforce at-most-once execution.Chris Lee
05/17/2022, 5:39 PMfun <T> Provider<T>.memoize(): Provider<T> {
return MemoizingProvider(this as ProviderInternal<T>)
}
internal class MemoizingProvider<T>(private val provider: ProviderInternal<T>) :
AbstractMinimalProvider<T>() {
private var memoizedValue: ValueSupplier.Value<out T>? = null
override fun getType(): Class<T>? {
return provider.type
}
override fun calculateOwnValue(consumer: ValueSupplier.ValueConsumer): ValueSupplier.Value<out T> {
if (memoizedValue == null) {
memoizedValue = provider.calculateValue(consumer)
}
return memoizedValue as ValueSupplier.Value<out T>
}
override fun toString(): String {
return "memoized($provider)"
}
}
Nicola Corti
05/17/2022, 10:36 PMJendrik Johannes
05/18/2022, 1:36 PM