Up-to-date check on Copy does not detect changed input

I have the following build.gradle

def copyFrom1 = fileTree(dir: 'source')
def copyFrom2 = copyFrom1.files

task foo(type: Copy) {
  into 'dest'
  from copyFrom1 // or use copyFrom2
}

and the following in ‘source’

source/dir/file.txt

I execute the script with either copying from copyFrom1 or copyFrom2. For this simple example I modify build.gradle, in my actual project copyFromN is the result of a method call that can returns both cases.

There is a different behaviour in the two cases. With copyFrom1 the directory structure is reproduced in ‘dest’ and you get

dest/dir/file.txt

with copyFrom2 the structure is ‘flatten’ and you get

dest/file.txt

(This behaviour surprised me but I assume that is working as designed. If not this is the bug, not the up-to-date check.)

The up-to-date check does not see a difference between these two cases. If you run with copyFrom1 and then again (leaving ‘dest’ as is) with copyFrom2 Gradle says foo is up-to-date. This is clearly wrong since a different result was expected.

I think this topic would be helpful for you.