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 parsingJendrik 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