'Why copy task delete stale output on first build?

I have this kotlin gradle build script representing my use case. I am working with Gradle 6.7.

This is my kotlin gradle build file:

plugins {
    java
}

tasks.register("createFile"){

    doLast{
        projectDir.resolve("tmp.txt").createNewFile()
        projectDir.resolve("tmp.txt").writeText("tmp")
    }

    dependsOn("assemble")
}

tasks.register("createExecFile", Exec::class){

    workingDir(buildDir)
    commandLine("cmd", "/c", "mkdir destdir\\subdir")

    dependsOn("createFile")
}

tasks.register("copyBug", Copy::class){

    from(projectDir.resolve("tmp.txt"))
    into(buildDir.resolve("destDir"))

    dependsOn("createExecFile")
}

Now run gradle copyBug -i.

The first time this will give you this output:

> Task :copyBug Deleting stale output file: E:\repo\BugCOpy\build\destDir Caching disabled for task ':copyBug' because:   Build cache is disabled Task ':copyBug' is not up-to-date because:   No history is available.

The copy task deletes the file created by the previous exec task.

Now if you rerun this command the copy task won't delete stale file.

So what are those stale file? How can I prevent those file to be deleted? My first build and is different than the other build.

Should I file a bug?



Solution 1:[1]

In your createExecFile task you produce output files without telling Gradle about them. So Gradle doesn’t know that this task and the copyBug task use the same output directory. Instead, Gradle believes that copyBug is the only task producing outputs under build/destdir and hence it’s safer to assume that any existing files in that directory should not be there (and are “stale”).

The solution is to tell Gradle that your createExecFile task outputs to build/destdir:

tasks.register("createExecFile", Exec::class) {

    workingDir(buildDir)
    commandLine("cmd", "/c", "mkdir destdir\\subdir")

    // tell Gradle about the output directory
    outputs.dir(buildDir.resolve("destdir"))

    dependsOn("createFile")
}

See this release notes section for why this behavior was introduced and this explanation to a very similar issue if you want some more background information.

Solution 2:[2]

My build process looks like

  1. run gradle (part 1)
  2. do something else
  3. run gradle (part 2)

For me annoyingly running gradle in step 3 would not just add a few files to the output directory but delete that folder as stale first. Even adding

outputs.dir(...)

did not prevent Gradle from removing it as stale. Working out the inputs and outputs of my task looked too tedious, but luckily I found a way to tell Gradle not to perform any up to date tracking:

Example 37. Ignoring up-to-date checks mentions to add

doNotTrackState("Comment why this is needed")

which ultimately helped me to keep the files from build step 1.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Chriki
Solution 2 Hiran Chaudhuri