Error with a copy task on Windows

UPDATE I just ran through my build process with various versions of Gradle 2: 2.0, 2.1, and 2.2.1. I got the same error with each of them. There has to be something odd about how I’m doing that copy operation, because otherwise copy tasks on Windows machines never would worked!

I have a copy task that is working properly on OSX, Centos, and Ubuntu, but is failing on Windows. The first thing I do is create a list of locations from which I want to copy. This works fine. Then the copy task starts. Here’s the code:

task copyResources(type: Copy) {
    from resources
    into "${pipelinePath}"
    exclude '.*/**'
    filter(ReplaceTokens, tokens: tokens)

The full code is available on my gist.

resources here is the list of locations from which I want to copy. It’s just a list of strings. And here’s where things go horribly horribly wrong. I run gradle (2.2.1) and get this:

Building pipeline engine to: D:\Tmp\work\pipeline_1_6dev
Site name: XNAT
Site URL: http://nrg115.nrg.mir
SMTP server:
:show UP-TO-DATE
  FAILURE: Build failed with an exception.
  * What went wrong:
Failed to capture snapshot of output files for task 'copyResources' during up-to-date check.
See stacktrace for details.
> Failed to create MD5 hash for file D:\Tmp\work\pipeline_1_6dev\.gradle.2.1\taskArtifacts\
  * Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
  Total time: 20.639 secs

Note that I’m running in a tmp folder here because I wanted to test this on a clean version of my code to make sure other gradle runs hadn’t possibly locked that file and then not relinquished the lock. This happens in every situation.

Turning on the stacktrace gives the following extra info (this is trimmed down: the full stacktrace and run info is on

org.gradle.api.UncheckedIOException: Failed to capture snapshot of output files for task 'copyResources' during up-to-date check.
See stacktrace for details.
        at org.gradle.api.internal.changedetection.rules.TaskUpToDateState.<init>(
Caused by: org.gradle.api.UncheckedIOException: Failed to create MD5 hash for file D:\Tmp\work\pipeline_1_6dev\.gradle.2.1\taskArtifacts\
        at org.gradle.internal.hash.HashUtil.createHash(
        ... 44 more
Caused by: The process cannot access the file because another process has locked a portion of the file
        at org.gradle.internal.hash.HashUtil.createHash(
        at org.gradle.internal.hash.HashUtil.createHash(
        ... 59 more

As I said, this works on OSX, Centos, and Ubuntu. The failure is limited to Windows machines. I’ve tested it on three separate machines, all Windows 7 64-bit and gotten the same failure on each of them.

I’m reasonably certain this is a bug and I’ll happily file a bug report on it, but if there was a workaround I could use in the short term, that would be outstanding as well.

Thanks in advance!

I just found the cause of this issue. I’m not sure how to work around it…

The problem is that I’m copying all of these files into the root build folder, that is, at the same level as the build.gradle and .gradle folder. Gradle is trying to build a map of MD5 hashes of the copy target so that it can just compare hashes on subsequent copy operations to determine what’s been updated. Part of the copy target is the very cache location where it’s storing the hashes. Because of Windows’s enthusiastic file locking, that file is locked and can’t be accessed, even read-only for calculating the MD5 hash, causing this error. *nix is much more lenient about file locking, so it just silently whisks over the files, even though they’ll never be copied over (it’s not gradle’s fault, or really ant’s, that it doesn’t know this).

You might say I should never have a gradle build that builds on top of itself and I’d have no argument with that. That just happens to be how this build has always worked, but then again this build is old enough that it has Maven 1.0.2 embedded in the middle of it. I don’t see any way to make it work on Windows machines without running into this problem, which is fine: it gives me a good reason to throw out the integrated build/install artifact model. I’ve actually already finished that work up and have my copy tasks working properly on all platforms now.

how to resolve the problem

Eson, the fix is to not copy into the same folder that has the .gradle folder in it. In my case, the folder indicated by ${pipelinePath} is the root build folder, i.e. where build.gradle and the .gradle folder are located. The first thing the Ant copy task does is to create md5 hashes of all of the files in the destination folder and store those hashes in its cache. As part of that process, it creates that file. Under normal build circumstances that’s fine, but when you’re copying to the build folder, one of the files under there is of course that file, which means that the Ant copy task tries to create an md5 hash of it. Windows is enthusiastic about its locking, and won’t let the copy task access the file to create the md5 hash, and that’s where the error comes into play.

My eventual fix was to not build on top of my build folder, but instead to copy everything into another destination folder, either build/pipeline (relative to the build folder) or to an external build folder somewhere else. That way there’s no overlap between the root build folder and the build itself. This required some re-working of other parts of our build process but we’ve ended up better off for it overall.