Frage

I've hit a problem with the Copy task, demonstrated by the following example:

task deploy(type: Copy) {
    from "foo.txt"
    into "/deployment"
}

where the content of /deployment is as follows:

-rw-r--r--  1 oliverc  oliverc    343 Feb 20 14:18 foo.txt
drwxr-x--- 22 oliverc  oliverc   4096 Feb 22 00:00 basic
drwxr-x---  9 root     root      4096 Jan 24 17:55 important

When I run ./gradlew deploy --stacktrace (as the oliverc user), Gradle* complains:

org.gradle.api.GradleException: Could not list contents of directory '/deployment/important' as it is not readable.
    at org.gradle.api.internal.file.collections.DirectoryFileTree.walkDir(DirectoryFileTree.java:141)
    at ... 
    at org.gradle.api.internal.changedetection.state.DefaultFileSnapshotter.snapshot(DefaultFileSnapshotter.java:44)
    at ...

Clearly, the complaint is correct (/deployment/important is owned by root and doesn't have world-readable permissions). But it's apparent that Gradle's snapshot mechanism is trying to capture everything in the into target. So:

  1. Why should the Copy task care about irrelevant content in this directory?
  2. Is there a Gradle-level workaround for this?** (Let's assume that I'm stuck with these permissions and directory layout.)


* This was tested using Gradle 1.10. I haven't investigated whether this is an issue with other versions.

** I realise I could use Project.copy instead of a Copy task, but then I lose incremental deployment.

War es hilfreich?

Lösung

It snapshots everything in order to see if the task is up to date or not. If the sources and the target haven't changed since the last time the task was run, then Gradle optimizes it by not doing anything, and the task is marked as UP-TO-DATE.

My guess is that they don't try to be smart and determine exactly which files of the target directory must be snapshotted because the copy task also accepts include and rename closures, and the task thus can't assume that nothing won't end up being copied to the important folder.

In general, Gradle works better (and assumes) that every target directory can be cleaned, and that a target directory isn't shared by two separate tasks.

I've not tested this workaround, but I would try defining my own task, using Project.copy(), and specifying its inputs and outputs explicitely and precisely, in order to not lose incremental deployment.

Andere Tipps

It's a known limitation of the Copy task, whose outputs are currently defined as an output directory. I don't think there is a solution that involves the Copy task; you can either use Project.copy, or implement your own copy task type that, say, defines its outputs as a set of files rather than a directory.

PS: Copy isn't really incremental; it either copies everything, or nothing.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top