Hi folks!
I have a task and I’d like to make it cacheable.
So there is an InputFile property and an OutputFile property in the task.
The problem is that I don’t know the OutputFile path until the task is completed.
To create the OutputFile I have to run an external application. It creates a file and returns the file path. The path is stable (there is a hash of the contents in the subdirectory name) but it is a private API and impossible to predict.
So the simple solution doesn’t work
@CacheableTask
class MyTask: DefaultTask() {
@InputFile
val x: project.objects.fileProperty()
@OutputFile
val y: project.objects.fileProperty()
@TaskAction
fun action() {
// this is pseudo code, but it shows an idea
// I get y path once an external app generates it
y = callExternalApplication(x)
}
}
I can’t set the “y” path during configuration, so the task is always out of date.
Another approach I invented
@CacheableTask
class MyTask: DefaultTask() {
@InputFile
val x: project.objects.fileProperty()
@OutputFile
val localPathCache: project.layout.buildDirectory.file("path.txt")
@OutputFile
val externalOutputFile = localPathCache.map {
if (it.exists()) {
val path = it.readLines().first()
File(path)
} else {
File("doen-not-exist") // It's impossible to return null from provider
}
}
@TaskAction
fun action() {
val path = callExternalApplication(x)
localPathCache.writeText(path)
}
}
I write the path in an intermediate file. I suppose if the file does not exist or if the path from the file does not exist, task should run. But that doesn’t work either.
If I understand correctly, Gradle reads all properties Before the task is run, but not after. Next run Gradle thinks the externalOutputFile path has changed (it was “does-not-exist”) and runs the task again.
So the question is, is it possible to implement such a case?
Any advice is highly appreciated