Sync and War (at least) have problems with non-canonical CopySpecs

With the following gradle file and a file ‘good’ and a file ‘bad’ aside the problem is reproducible with Gradle 1.12.

task sync(type: Sync) {
    outputs.upToDateWhen { false }
    from('good') {
        into '2/3'
    }
    from('bad') {
        into '2/../4/5'
    }
    into buildDir
}
  defaultTasks = ['sync']

The ‘Sync’ will copy ‘good’ to ‘build/2/3/good’ and ‘bad’ to ‘build/4/5/bad’ but then deletes ‘bad’ again. If you use the ‘War’ task with the same ‘CopySpec’, ‘bad’ also does not make it into the generated WAR file.

This is not a made up use-case, just a stripped down example. My use-case is, that I generate ‘JavaHelp’ documentation from ‘DocBook’ files and then parse through the generated HTML files to prepare a ‘CopySpec’ for including all the referenced images some of which have such non-canonical paths. I’ll try to work-around it by canonicalizing my ‘CopySpec’, but it seems to be a bug to me.

For Sync the problem manifests in ‘SyncCopyActionDecorator.maybeDelete()’, because it checks for ‘4/5/bad’ but only finds ‘2/…/4/5/bad’ in the ‘visited’ ‘Set’ and as it is not found, it is deleted.

I didn’t investigate where this manifests for War.