i had some problems to really understand the logic of the up-to-date checks. I prepared a simple
build.gradle
to show the problems i had.
task a{
dstFile= new File(temporaryDir, 'dummy')
outputs.file dstFile
doLast{
println('do not create output but finish successful - subsequent run will yield "UP-TO-DATE" (this was my problem')
}
}
task b{
dstFile= new File(temporaryDir, 'dummy')
outputs.file dstFile
doLast{
println('do not create output but stop execution - subsequent run should execute task (but does not)')
throw new StopExecutionException()
}
}
task c{
dstFile= new File(temporaryDir, 'dummy')
outputs.file dstFile
doLast{
println('create output but stop execution - subsequent run should execute task (but does not)')
dstFile.createNewFile()
throw new StopExecutionException()
}
}
task d{
dstFile= new File(temporaryDir, 'dummy')
outputs.file dstFile
doLast{
println('create output and finish successful - subsequent run will yield "UP-TO-DATE" (good)')
dstFile.createNewFile()
}
}
task clean(type: Delete){
delete 'build'
doLast{
println('now all of the tasks should execute again because the buildDir is gone - this is not the case')
}
}
task all {
dependsOn
a,b,c,d
}
maybe we can add a line to the documentation which clearly states that “the nonexisting output of a task is treated as up-to-date for the next run”.
The logic is this: If the inputs haven’t changed and the outputs still exist (and haven’t been tampered with), then the task is up-to-date. Did you make any observation that contradicts this logic?
my observation is, that if a task fails to write it’s defined output the up-to-date check is happy with that non-existing output in the next run and says ‘UP-TO-DATE’, essentially because nothing is equals to nothing
so if you want to have a look at tasks A,B,C of my example it will be more clear.
The tasks a, b, c and d references the same file, so when task d creates it, tasks a, b and c are up-to-date with regards to the rules Peter referred to.
Maybe your confusion is caused by a misconception of what StopExecutionException means. It’s merely a way to stop executing the current task. It doesn’t mean that the task has failed.
One important point is that the up-to-date logic is only applicable to tasks that always produce the same output (as described by the task) given the same input. If you have a task for which this doesn’t hold, you can make sure that it’s never considered up-to-date with task.outputs.upToDateWhen { false }. Or, if you implemented the task yourself, don’t describe its inputs/outputs in the first place. You can also disable all up-to-date checks with the –no-opt flag.
The fact that your tasks don’t declare any inputs effectively tells Gradle that they will always produce the same output. Hence, once they have run successfully once they will always be up-to-date unless their output is tampered with.
To get a general understanding of how up-to-date works, it would be better to study more well-behaved/well-designed tasks.
so my xlst-task failed to write ‘cool-file’ in the first place because of a stylesheet problem. (which would be a common problem for xslt-developers - failing in the first place i mean scnr)
now src-xml didn’t changed => xml-resolved stayed the same => xslt did not run
never,ever. so i asked myself for an hour or two - ‘why does it not run even the promised output is not there?’ and then i thought it would be a good idea to ask here.
p.s.: one improvement was to add the stylesheet itself as an input.
This should only happen if your xslt task didn’t fail (i.e. didn’t throw an exception) although it failed to write the file. A failed task will never be up-to-date on the next execution.