Zip task ignores output when checking if up to date

Hi

I’m trying to create a zip file with a zip task. Executing the build for the first time works like a charm, then if I manually delete the destination folder and execute the build again - I get “up to date” as though Gradle ignores the fact that the output file is missing (and it also ignores the upToDateWhen closure)

task bundle(type: Zip) {
    archiveName = "${project.name}.zip"
    destinationDir = new File("${project.buildDir}/dist/")
    exclude 'build', '*.gradle', 'gradle.properties', '.*', 'gradle', 'gradlew*'
    from '.'
    outputs.upToDateWhen {
        false
    }
}

(Essentially zips the project directory without the build files and hidden directories)
I checked the outputs container and it indeed contains the correct output file, albeit it ignores it when attempting to determine if the task state is up-to-date. When I added an empty file to the project directory it recognized that the input changed and executed the task.

Is checking for outputs is a limitation of the zip task? how can I bypass this issue? using --rerun-tasks won’t help in the long run as I want to make a plugin that needs this behavior.

(tested with 2.6 and 2.7)

Thanks,
Boaz

I’m not able to replicate this behavior. Also, the fact that you say you still get Gradle reporting the task is UP-TO-DATE even with the upToDateWhen { } configuration makes me think something else is going on in your build script. Can you provide a more complete example or perhaps a simplified one that reproduces your problem?

Thanks Mark for your quick reply!

Other then having includeEmptyDirs = true in the task configuration - this is the entire build (unless you care about group, version, name and the wrapper task. I’m not applying any plugins as of yet)

task bundle(type: Zip) {
    archiveName = "${project.name}.zip"
    destinationDir = new File("${project.buildDir}/dist/")
    includeEmptyDirs = true
    exclude 'build', '*.gradle', 'gradle.properties', '.*', 'gradle', 'gradlew*'
    from '.'
    outputs.upToDateWhen {
        false
    }
}

After reading your message I did some more tests and it seems like the problem is different then what I thought - sorry about that.
My directory structure is as follows:

build.gradle
Contents/
Contents/stuff/
gradle/ ...
.gradle/ ...
gradlew
gradlew.bat
settings.gradle

executing gradlew bundle gets up to date (even though there is no build directory at all) - expected behavior is to create a zip that contains Contents/ + Contents/stuff/.

executing touch a creates the empty file a and then executing gradlew bundle creates a zip file as expected (a + Contents/ + Contents/stuff/)

though executing (from the initial state) mkdir b creates the empty folder b and the executing gradlew bundle gets up to date (even though there is no build directory at all) - expected behavior is to create a zip that contains b/ + Contents/ + Contents/stuff/.

Seems like Gradle expects to have at least a single file to consider that “there is work to be done” even though includeEmptyDirs is on.

What am I missing here?

Thanks

This is correct. Running the build with --info would confirm your assumption.

Skipping task ':bundle' as it has no source files.
:bundle UP-TO-DATE

I don’t see any good workarounds for this other than ensuring there is at least one source file. If you often need to create “empty” archives you might also consider using the Ant zip task instead.

FYI: This is GRADLE-2579